With gas-2.23 (and I presume, every other version), consider this code : ************************* bt/s call_handler mov.l p_orig, r2 call_handler: rts nop .BALIGN 4 p_orig: .long 0x13BEC ************************* The expected result is of course to have the assembler magically replace that mov.l with the appropriate "mov.l @(disp, PC), Rn" form. The problem is that, being in the delay slot, any opcode with the @(disp, PC) offset actually does the access with the value PC = PC_of_branch_target + 2. This is documented in the SH docs, and there's even an example: (from REJ09B0316-0200 SH-2E software manual) ************************* 100A BRA NEXT ;Delayed branch instruction 100C MOV.L @(4,PC),R3 ;R3 = H’12345678 1012 NEXT JMP @R3 ;Branch destination of the BRA instruction 1014 CMP/EQ #0,R0 ;← PC location used for address calculation for the ;MOV.L instruction .align 4 ; 1018 .data.l H'12345678 ; ************************* To summarize : 1- the main problem is that the usually helpful syntax "mov.l <label>, rX" does not work as expected if placed in a delay slot ! 2- further : if the branch opcode is a {braf, bsrf, jmp, jsr, rts, rte}, then writing "mov.l <label>, rX" in their delay slot is asking for trouble, since usually gas will have no way of knowing the value of PC after the branch. Workaround for the first sample: manually calculating the displacement will work, like this: mov.l @(p_orig - call_handler + 2, PC), r2 But ugly.