It is interesting to note that GNU as (gas) expects you to provide aligned/pre-calculated displacements, which is apparently different from the official assembler. I haven't used it but the examples in the SH4 programming manual show that the displacement in both source and binary is an index just like a C-array.
In C, you always index by the (nth - 1) element and the compiler will do "index * sizeof(T)." The SH4 does the same internally and in the official assembler. Gas, however, expects you to do the (index * sizeof(char/short/long) and then it converts that back to an index in the encoded instruction. I suppose this is for historical clarity, consistency with other instruction sets or born of painful experiences with misaligned memory ops... Still, I wish the official syntax was available because it retains the feel of higher-level languages.
In kos/arch/dreamcast/kernel/entry.s
Code: Select all
mov.l r8,@(0x20,r0) ! save R8
mov.l r9,@(0x24,r0) ! save R9
mov.l r10,@(0x28,r0) ! save R10
Note that the displacement grows by 4 and not by 1
in the SH4 programming manual these are the examples shown
@(disp, GBR)
Code: Select all
mov.l @(2,gbr),r0 ;before execution (gbr+8) = h'12345670
;after execution r0 = (h'12345670)
mov.b r0, @(1, gbr) ;before execution r0 = h'ffff7f80
;after execution (gbr+1) = h'80
Note the first instruction gives a displacement of 2 and not 8 for a long access. (0x10)
@(disp, RN)
Code: Select all
mov.l @(3,pc),r3 ;r3 = h'12345678
Note that 3 is given as a displacement for a long access and not 3 * 4 (0x0C)
If you try to compile the same code using gas...
Code: Select all
mov.l @(2,gbr),r0
mov.b r0,@(1,gbr)
mov.l @(3,pc),r3
You get this:
Code: Select all
sh4-mov.s: Assembler messages:
sh4-mov.s:1: Error: misaligned offset
sh4-mov.s:3: Error: offset to unaligned destination