01 August 2021, 12:05 | #1 |
Registered User
Join Date: Aug 2006
Location: Finland
Age: 52
Posts: 244
|
I got fooled by address register word size operations
I had a bug that haunted me for quite some time.. me and my stupid premature optimizations. Anyway, typically address register word size operations sign extend and stuff automatically to 32 bits. I tend to use that routinely. So, my code had:
Code:
SUBA.W A2,A2 Code:
MOVE.L #$00AA0001,A0 MOVE.L #$00110002,A1 SUBA.W A1,A0 |
01 August 2021, 12:21 | #2 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,490
|
Is the source that is sign extended in Ax.w operations.
So this is like: Code:
MOVE.L #$00AA0001,A0 MOVE.L #$00110002,A1 MOVE.W A1,A1 SUBA.L A1,A0 This explain also the SUBA.W A2,A2 |
01 August 2021, 12:36 | #3 |
Registered User
Join Date: Aug 2006
Location: Finland
Age: 52
Posts: 244
|
Right.. I had to reread what the manual actually says and yes "Word-sized source operands are sign-extended to 32-bit quantities prior to the subtraction." Sigh, I have actually missed this detail all these years
|
02 August 2021, 07:50 | #4 |
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,355
|
There is also the trick to use CMPA.W on same reg to check if a signed value fits in 16-bit (i.e. is between $ffff8000 and $00007fff).
|
02 August 2021, 19:54 | #5 |
Moderator
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,652
|
SUB and CMP should use the exact same logic, cmp is sub without store. From memory there is no time gain (or loss of time loss ) for An as there is for Dn (on 68000) because of the extra operations (also includes ADD). I.e. if you go by 6c instead of 8c check footnotes.
Code:
move.l #$0ffffffff,a0 sub.w a0,a0 move.l #$ffff0fff,a1 sub.w a1,a1 a0=$10000000 a1=$ffff0000 Last edited by Photon; 02 August 2021 at 20:57. |
02 August 2021, 20:48 | #6 |
Registered User
Join Date: Jun 2016
Location: europe
Posts: 1,062
|
Nope, that specific mode/reg combo of sub is used to encode subx.
|
02 August 2021, 21:52 | #7 |
Moderator
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,652
|
OK, I was thinking of MOVEA. No diff there either? And flags unaffected?
Also, ADDA/ADD ea,An (and same for move) doesn't sign-extend according to Motorola. (I'm only following through and being exhaustive.) So, only SUB and CMP. But where there's an unusual behavior there could be a niche case to abuse for those two. |
02 August 2021, 22:36 | #8 |
Registered User
Join Date: Jun 2016
Location: europe
Posts: 1,062
|
No difference on opcode level, each movea variant is using a unique opcode (there is no opcode duplication with move). Basically, it's all move $2xxx/$3xxx but if destination is an areg, move is changed to movea (to indicate different behaviour regarding ccr etc.). Move $1xxx (.b) to areg are all invalid (exception).
|
02 August 2021, 22:43 | #9 |
Registered User
Join Date: Aug 2006
Location: Finland
Age: 52
Posts: 244
|
Ha, that was neat Never thought about that before. Maybe I find use for that some day.
Last edited by mr.spiv; 03 August 2021 at 08:09. |
02 August 2021, 23:24 | #10 |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,436
|
This is certainly something I ran into as well. It's a good source for rather subtle bugs
|
03 August 2021, 00:06 | #11 | |
Moderator
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,652
|
Quote:
|
|
03 August 2021, 10:05 | #12 | |||
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,355
|
Quote:
Quote:
If you like odd things : even though everything byte related is invalid if address regs are used, 020+ MOVES instruction isn't. Quote:
Because contrary to ADDA,SUBA,CMPA which all have specific opcodes, MOVEA occupies natural space where MOVE (to An) would be. |
|||
03 August 2021, 10:31 | #13 | |
bye
Join Date: Jun 2016
Location: Some / Where
Posts: 681
|
Quote:
a0 = $00000000 the sub.w a0,a0 uses a0.w sign extended $ffff -> $ffffffff $ffffffff - $ffffffff = $00000000 the word used in adda/suba is sign extended before a long add/sub is calculated |
|
03 August 2021, 13:38 | #14 | |
Moderator
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,652
|
Quote:
Code:
move.l #$0000ffff,a0 move.l #$0000ffff,a1 add.w a0,a1 ;a1=$0000fffe move.w a0,a2 ;a2=$ffffffff Maybe for the Debugger, but I mean changing the opcode from an imaginary existing move ea,An to movea ea,An. As in two different instructions in the CPU, one of them would then be in an unnatural space |
|
03 August 2021, 14:06 | #15 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,490
|
Quote:
Code:
move.l #$0000ffff,a0 move.w a0,a0 move.l #$0000ffff,a1 add.l a0,a1 ;a1=$0000fffe move.w a0,a2 ;a2=$ffffffff The arithmetic operations are always full 32bit as far as the Ax registers are concerned. |
|
03 August 2021, 14:28 | #16 | |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,307
|
Quote:
Operations on Ax registers sign extend the source, not the destinatiion. That is, the left operand is extended, but not the target address register (that would not really make sense...). For "movea" (not to be confused with "move" which does not take an address register as target), the left-hand operand is thus sign extended to 32 bit before performing the move. For "adda" (not to be confused with "add" which does not take an address register as target), the operand to be added is sign extended, but not the target to which it is added. Likewise for suba (not "sub" which does not exist for address register targets). That your assembler converts move to movea, sub to suba and add to adda is just a convenience function. The opcodes work differently. (sign extension just being one difference, setting flags being another). |
|
03 August 2021, 16:27 | #17 |
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,355
|
|
05 August 2021, 13:16 | #18 | |
Moderator
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,652
|
Quote:
adda.w sign extends source and performs a full 32-bit add. |
|
05 August 2021, 14:00 | #19 | |
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,355
|
Quote:
Code:
move.l #$55558888,a0 move.l #$11111111,a1 adda.w a0,a1 ; a1=$11109999 |
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Address register indirect, word vs long | deimos | Coders. Asm / Hardware | 4 | 15 November 2019 16:58 |
Logging Blitter Operations? | mcgeezer | support.WinUAE | 2 | 02 June 2019 10:23 |
Address register expected | Nightfox | Coders. Asm / Hardware | 4 | 12 August 2016 11:51 |
WinUAE Debugger - Address Register Watchpoints | SparkyNZ | Coders. Asm / Hardware | 3 | 16 June 2015 22:39 |
Word vs not word aligned playfield question | nandius_c | Coders. Asm / Hardware | 8 | 03 December 2013 12:03 |
|
|