English Amiga Board


Go Back   English Amiga Board > Coders > Coders. General > Coders. Tutorials

 
 
Thread Tools
Old 05 December 2010, 23:18   #1
jman
Registered User
 
Join Date: Nov 2010
Location: .
Posts: 351
REQ:ASM getting elapsed time on A1200

Hello,

I've finally faced the problems of fiddling with ASM on an emulated A1200 instead of the A500.

I was reading on my idiot-proof tutorial about a method for getting real elapsed time between two tasks. Apparently the best way is to use the CIA timers of the 8520 chip onboard of the A500, which can be queried using these addresses: $BFE801,$BFE901,$BFEA01 (see this thread).

Well, to my dismal (but not surprise) I've realized these addresses are "mute" and do not return anything on an A1200.
Running the very same code on an emulated A500 with ks 1.3 works.
Now, which A1200 component's address should I query for such a task? Maybe "Paula" chip is responsible for that?

Anyway, this leads to the second question: how many if these inconsistences will I find from now on? Since I'm just playing with ASM for the sake of it (no real purpose actually), is it worth continuing with the A1200 way or should I backstep to the earlier classic Amiga and OCS chipset?

Thanks for clearing up this mist

EDIT: on this file I see that the A1200, too, has an 8520 and the memory range is (roughly) the same as per the A500. I'm more and more confused...

Last edited by jman; 15 August 2011 at 01:51.
jman is offline  
Old 06 December 2010, 01:47   #2
pmc
gone
 
pmc's Avatar
 
Join Date: Apr 2007
Location: completely gone
Posts: 1,596
As you say, you can use the CIA timers for getting accurate elapsed times.

I don't think there's any difference between how you would do this on an A500 or an A1200.
pmc is offline  
Old 06 December 2010, 08:09   #3
musashi5150
move.w #$4489,$dff07e
 
musashi5150's Avatar
 
Join Date: Sep 2005
Location: Norfolk, UK
Age: 42
Posts: 2,351
IIRC later versions of the OS used the CIAs differently to 1.3 on your A500. So it's very likely you would get different results with the same code. Where are you getting your code from? Is it the blue Abacus books?
musashi5150 is offline  
Old 06 December 2010, 09:44   #4
jman
Registered User
 
Join Date: Nov 2010
Location: .
Posts: 351
Quote:
Originally Posted by musashi5150 View Post
IIRC later versions of the OS used the CIAs differently to 1.3 on your A500. So it's very likely you would get different results with the same code. Where are you getting your code from? Is it the blue Abacus books?
Oh the joys of a custom architecture.
Yes, I'm following that book. The code snippet that should do the job is:
Code:
        gettime:
               move.b  $bfea01,d7
               lsl.l   #4,d7
               lsl.l   #4,d7
               move.b  $bfe901,d7
               lsl.l   #4,d7
               lsl.l   #4,d7
               move.b  $bfe801,d7
               rts
Your guess sounds resonable.

So, what are my options?
1) Run the emulator with an older KS ROM
2) Find documentation about the new addresses (would check the fine material downloaded if I have something more recent)
3) else?

Thanks for your insight.

Last edited by jman; 15 August 2011 at 01:51.
jman is offline  
Old 06 December 2010, 09:54   #5
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,515
KS uses CIA TOD counter for some timing tasks and resets it regularly.

Use timer.device GetSysTime() if your program does not take over the system. (It uses CIA counters internally)
Toni Wilen is offline  
Old 06 December 2010, 11:17   #6
pmc
gone
 
pmc's Avatar
 
Join Date: Apr 2007
Location: completely gone
Posts: 1,596
Quote:
Originally Posted by musashi5150
IIRC later versions of the OS used the CIAs differently to 1.3 on your A500.
Quote:
Originally Posted by Toni Wilen
Use timer.device GetSysTime() if your program does not take over the system.
But if you kill the OS and use the CIA's directly I take it timer code would function the same machine to machine...?
pmc is offline  
Old 06 December 2010, 12:44   #7
musashi5150
move.w #$4489,$dff07e
 
musashi5150's Avatar
 
Join Date: Sep 2005
Location: Norfolk, UK
Age: 42
Posts: 2,351
Quote:
Originally Posted by pmc View Post
But if you kill the OS and use the CIA's directly I take it timer code would function the same machine to machine...?
Yes, exactly
musashi5150 is offline  
Old 06 December 2010, 13:23   #8
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,515
If you do it properly. It must take over all interrupts and/or disable them. (including level 2 and 6), not just vblank like in early days..
Toni Wilen is offline  
Old 06 December 2010, 14:22   #9
jman
Registered User
 
Join Date: Nov 2010
Location: .
Posts: 351
Quote:
Originally Posted by Toni Wilen View Post
If you do it properly. It must take over all interrupts and/or disable them. (including level 2 and 6), not just vblank like in early days..
Ok, so if I understand correctly my best option is to open the timer.device library and invoke the GetSysTime(). That makes sense.

Unfortunately this topic (opening an external library) will be treated later in the tutorial so I think I'm posting questions a little before my schedule and will have to first learn how to do such a trivial task.
I don't have clear your observation about the interrupts, though. But I guess that's asking too much to my poor knowledge, for the moment.

Thanks.

Antonio
jman is offline  
Old 26 December 2010, 13:10   #10
jman
Registered User
 
Join Date: Nov 2010
Location: .
Posts: 351
Quote:
Originally Posted by Toni Wilen View Post
KS uses CIA TOD counter for some timing tasks and resets it regularly.

Use timer.device GetSysTime() if your program does not take over the system. (It uses CIA counters internally)
Ok, after some investigations I came to an end, I do need some basic input on how to open and use that device.

The syntax of the call to the OpenDevice is clear:
Code:
OpenDevice(DEVICENAME,unit,ioRequest,flags)
but I don't understand how to implement it, whenever I invoke the "_LVOOpenDevice(a6)" the debugger raises an illegal exception, obviously because I'm not preparing the necessary parameters correctly.

I'm not pasting here any code I tried because it's just a bunch of rubbish, I just need a simple, clean example on how to invoke _LVOOpenDevice and _LVOGetSysTime.

Thanks for your help.
jman is offline  
Old 26 December 2010, 22:16   #11
StingRay
move.l #$c0ff33,throat
 
StingRay's Avatar
 
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
If you get an illegal exception when you try to open the timer.device something is really wrong, check that you have a pointer to exec library in a6 as otherwise all things go wrong and might cause the exception, if a6 is not exec base but any other library (or, even worse, contains "random" data) OpenDevice can't work for obvious reasons.

To open the timer.device you need to do these 3 things:

1. Create a message port [Exec->CreateMsgPort()]
2. Create an IO request [Exec->CreateIORequest]
3. Open the device and use the IO request structure created in 2. as parameter


Code for this could look like this (no error checks etc, you'll have to add these yourself):

Code:
; Create message Port
	move.l	$4.w,a6
	jsr	_LVOCreateMsgPort(a6)

; Create IORequest
	move.l	d0,a0
	moveq	#IOTV_SIZE,d0
	jsr	_LVOCreateIORequest(a6)
	move.l	d0,a4

; Open timer.device
	move.l	d0,a1
	lea	tdname(pc),a0
	moveq	#0,d0
	moveq	#0,d1
	jsr	_LVOOpenDevice(a6)
This code will open the timer.device. To use the GetSysTime() function you need to obtain the device base (so you can use it like a library), this you can find in the "IO_DEVICE" field of the IORequest structure once OpenDevice returns (and was successful opening timer.device of course). Then you can call GetSysTime and it will fill the timeval structure you pass to it.

Code:
	move.l	IO_DEVICE(a4),a6
	lea	time(pc),a0
	jsr	_LVOGetSysTime(a6)
You'll then have the time (in seconds) that has passed since 01.01.1978 in the TV_SECS field of the timeval structure. What you do with this info is up to you.
StingRay is offline  
Old 27 December 2010, 23:57   #12
jman
Registered User
 
Join Date: Nov 2010
Location: .
Posts: 351
Quote:
Originally Posted by StingRay View Post
To open the timer.device you need to do these 3 things:
...
Hey, just a quick note to express my appreciation for your clear explaination.
Unfortunately now I can't open the Amiga emulator due to a close deadline at work (oh the joys of software developers) but in the following days I want to have a thorough look at all that useful info.
As a funny side note, I have always been 'allergic' to C and derivatives because I've never learnt how to manage memory and memory pointers. Thansk to asm, I'm realizing that eventually I will also learn all that :-)
jman is offline  
Old 09 January 2011, 20:06   #13
jman
Registered User
 
Join Date: Nov 2010
Location: .
Posts: 351
Quote:
Originally Posted by StingRay View Post
You'll then have the time (in seconds) that has passed since 01.01.1978 in the TV_SECS field of the timeval structure. What you do with this info is up to you.
Hello again.

It was no easy task (for a beginner) but I found the right way to use that device and have the seconds elapsed.

Now I'd like to do some calculations on this number, for example transform it in years,months,days,etc.

However, while doing calculations I've stomped over two strange things (not striclty related) that I don't understand:

1) The behaviour of the status register after following instructions:
Code:
move.w #$7fff,d0   ; the SR is OK, nothing is set
move.w #$8000,d0   ; after this the 'N' bit is set
can you explain why? If I use a "move.l" the 'N' bit is not set

2) Why this division overflows:
Code:
move.w #$ffff,d0
move.w #$ffff,d1
divs d1,d0
I'm still inside the valid range for a word. That should not bother DIVS (it is my understanding that the source parameter should be a 16bit).

Thanks

Last edited by jman; 09 January 2011 at 20:45. Reason: corrected typo :)
jman is offline  
Old 09 January 2011, 20:22   #14
StingRay
move.l #$c0ff33,throat
 
StingRay's Avatar
 
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
Quote:
Originally Posted by jman View Post
1) The behaviour of the status register after following instructions:
Code:
move.w #$7fff,d0   ; the SR is OK, nothing is set
move.w #$8000,d0   ; after this the 'N' bit is set
can you explain why? If I use a "move.l" the 'N' bit is not set
N = Negative flag, it is set if the "sign bit" is set, in case of a word that is bit 15. Thus, after your move. w #$8000,d0 instruction the N flag is set since bit 15 is set. In case of a long word the sign bit is 31 which explains why the N flag won't be set if you change the move.w to a move.l



Quote:
Originally Posted by jman View Post
2) Why this division overflows:
Code:
move.w $ffff,d0
move.w $ffff,d1
divs d1,d0
I'm still inside the valid range for a word. That should not bother DIVS (it is my understanding that the source parameter should be a 16bit).
Divs is 32/16, i.e. your move.w #$ffff,d0 [I hope it's a typo that you forgot the "#" ]will lead to wrong results since the upper part of d0 contains "random" data. Change it to move.l and all will be fine.

Quote:
Originally Posted by jman View Post
Thanks
You're welcome.
StingRay is offline  
Old 09 January 2011, 21:08   #15
jman
Registered User
 
Join Date: Nov 2010
Location: .
Posts: 351
Quote:
Originally Posted by StingRay View Post
N = Negative flag, it is set if the "sign bit" is set, in case of a word that is bit 15. Thus, after your move. w #$8000,d0 instruction the N flag is set since bit 15 is set. In case of a long word the sign bit is 31 which explains why the N flag won't be set if you change the move.w to a move.l
Ok, that's clear!

Quote:
Originally Posted by StingRay View Post
Divs is 32/16, i.e. your move.w #$ffff,d0 [I hope it's a typo that you forgot the "#" ]will lead to wrong results since the upper part of d0 contains "random" data. Change it to move.l and all will be fine.
Yes that was a typo, thanks for pointing that.
However even I copy a full longword to d0 the division still overflows. I've even tried to do some 'padding' like:
Code:
move.l #$0000ffff, d0
to no avail. Divisions up to "#$fffe" work. So what am I doing wrong?

thanks,
a.
jman is offline  
Old 10 January 2011, 02:43   #16
Leffmann
 
Join Date: Jul 2008
Location: Sweden
Posts: 2,269
The DIVS.W instruction gives only a 16-bit quotient, and so you get an overflow because you're calculating 65535/-1 = -65535 which is too large to be represented as a 16-bit two's complement number. If you have a 68020 or better you can use longer forms of DIVS that give 32-bit results.
Leffmann is offline  
Old 10 January 2011, 22:23   #17
jman
Registered User
 
Join Date: Nov 2010
Location: .
Posts: 351
Quote:
Originally Posted by Leffmann View Post
The DIVS.W instruction gives only a 16-bit quotient, and so you get an overflow because you're calculating 65535/-1 = -65535 which is too large to be represented as a 16-bit two's complement number. If you have a 68020 or better you can use longer forms of DIVS that give 32-bit results.
Hi Leffmann,

can you please further explain?

1) Why am I calculating 65535/-1? Shoulnd't be 65535/65535 thus = 1?
2) I'm already running an emulated (on WinUAE) 68020, so I don't understand.

Sorry for this kind of trivial questions but it's important to me to understand these basics.

Thanks,
Antonio
jman is offline  
Old 11 January 2011, 08:21   #18
pmc
gone
 
pmc's Avatar
 
Join Date: Apr 2007
Location: completely gone
Posts: 1,596
Good morning jman

Recall what StingRay said about the N flag of the status register and the sign bit and remember that $ffff doesn't equal 65535 when dealing with signed numbers.

This might give you a clue when you also see that you're using the signed version (divs) of the divide mnemonic.

Also, 68020 allows divs.l whereas 68000 only allows divs.w - again thinking about the N flag and the sign bit, you can see that doing a division with $ffff.w is different to doing a division with $0000ffff.l
pmc is offline  
Old 11 January 2011, 22:24   #19
jman
Registered User
 
Join Date: Nov 2010
Location: .
Posts: 351
Quote:
Originally Posted by pmc View Post
Recall what StingRay said about the N flag of the status register and the sign bit and remember that $ffff doesn't equal 65535 when dealing with signed numbers.
All of a sudden I understand what you're all trying to explain.
And the sad fact is that I've also checked this post and the following ones without realizing it was the answer I was looking for.

Thank you all for your help, now things are clear.

Man, sometimes I'm so thick I have to stop thinking in decimal, binary it's easier.
jman is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
[REQ:ASM] Reading a keystroke jman Coders. Tutorials 34 17 August 2023 12:36
[REQ:ASM] Sprite collisions basics jman Coders. Tutorials 5 03 September 2011 00:07
[REQ:ASM] Loading a static image and its palette jman Coders. Tutorials 3 04 June 2011 14:08
[REQ:ASM] Assembling and running jman Coders. Tutorials 9 07 May 2011 18:39
REQ:ASM How to use buffers jman Coders. Tutorials 7 01 December 2010 01:41

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 02:04.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.09865 seconds with 13 queries