go.arm64 icon indicating copy to clipboard operation
go.arm64 copied to clipboard

liblink: what does $0(SP) mean

Open 4ad opened this issue 10 years ago • 20 comments

Is it equal to the hardware SP (R31) register, or is it equal to the virtual SP register that "points" to the top of the local frame?

Our assembly assumes the former, while our tools generate the latter. Which one is right?

4ad avatar Feb 04 '15 14:02 4ad

On ppc64:

TEXT    foo(SB),7,$16
    MOVD    R1, R5
    MOVD    $0(SP), R6
    MOVD    $0(R1), R6
    BL bar(SB)
    RETURN

.data:0x00000000    7fe802a6    mflr    r31 
.data:0x00000004    fbe1ffe9    stdu    r31,-24(r1) 
.data:0x00000008    7c250b78    mr      r5,r1   
.data:0x0000000c    38c10018    addi    r6,r1,24    
.data:0x00000010    38c10000    addi    r6,r1,0     
.data:0x00000014    48000001    bl      func_00000014   
.data:0x00000018    ebe10000    ld      r31,0(r1)   
.data:0x0000001c    7fe803a6    mtlr    r31

on arm64:

TEXT    foo(SB),7,$16
    MOV SP, R5
    MOV $0(SP), R6
    BL bar(SB)
    RETURN

   0:   f81e0ffe    str x30, [sp,#-32]!
   4:   910003e5    mov x5, sp
   8:   910083e6    add x6, sp, #0x20
   c:   94000000    bl  0xc
  10:   f84207fe    ldr x30, [sp],#32
  14:   d65f03c0    ret

Note that we don't have $0(R31) on arm64. The output matches though, so it seems out assembly files are broken.

Also note that a plain SP really is the hardware SP, and ppc64 does not allow a plain SP.

All of this is extraordinarily inconsistent.

4ad avatar Feb 04 '15 14:02 4ad

On 4 February 2015 at 14:44, Aram Hăvărneanu [email protected] wrote:

Is it equal to the hardware R31 register, or is it equal to the virtual SP register that "points" to the top of the local frame? Our assembly assumes the former, while our tools generate the latter.

on arm64:

TEXT foo(SB),7,$16 MOV SP, R5 MOV $0(SP), R6 BL bar(SB) RETURN

0: f81e0ffe str x30, [sp,#-32]! 4: 910003e5 mov x5, sp 8: 910083e6 add x6, sp, #0x20

That is the virtual SP, though, isn't it, since it's adding 0x20? In the original 7a and 9a (as in the others), "SP" produced name D_AUTO, which would then have the right effect (ie, virtual SP).

forsyth avatar Feb 04 '15 17:02 forsyth

Yes, seems so.

4ad avatar Feb 04 '15 17:02 4ad

It seems we'd better introduce a new name for the real sp register, because SP in source code really means the virtual one, independent of how it's used.

minux avatar Feb 04 '15 19:02 minux

On 4 February 2015 at 19:17, Minux Ma [email protected] wrote:

independent of how it's used.

nearly: ADD $32, Rn, SP (say) will add exactly 32 to the hardware register, no messing about. It's one reason MOV $n(SP), Rm exists, to be able to express adding n, but with n adjusted to match the virtual stack.

forsyth avatar Feb 04 '15 19:02 forsyth

MOV SP, Rn is also the hardware register.

We can use R31 when we want the hardware register without doubt, but it's very tricky because depending on the instruction it might silently mean ZR.

4ad avatar Feb 04 '15 19:02 4ad

Nevermind, we can't say R31, the assembler doesn't accept it.

4ad avatar Feb 04 '15 19:02 4ad

Another very confusing thing is that the print routines don't generate valid assembly, and the meaning of something might be different when it's assembly listing, or when it's assembly input.

Somewhat related to this is that since a while, on amd64 the offsets used for accessing functions parameters in assembly and in the print version of assembly differ by 8 (the print is wrong).

4ad avatar Feb 04 '15 19:02 4ad

On Feb 4, 2015 2:36 PM, "Charles Forsyth" [email protected] wrote:

nearly: ADD $32, Rn, SP (say) will add exactly 32 to the hardware register, no messing about. Having SP as the destination is not ambiguous, but what about SP as a source?

MOV SP, Rn

Should this SP be the virtual one or the real one?

To avoid such ambiguity, I think we should introduce another HSP (hardware SP, or something like that) that always means the real SP. liblink should either synthesize the instruction or give an error if its use is inappropriate.

minux avatar Feb 04 '15 20:02 minux

Or we can adopt the x86 rule:

"On architectures with a real register namedSP, the name prefix distinguishes references to the virtual stack pointer from references to the architectural SP register. That is, x-8(SP) and -8(SP) are different memory locations: the first refers to the virtual stack pointer pseudo-register, while the second refers to the hardware's SP register."

So $0(SP) is the real SP add 0, while $x-0(SP) is the virtual SP add 0.

Note: 6a doesn't allow $0(SP).

minux avatar Feb 04 '15 20:02 minux

I'm just guessing, but I guess that a confusion like this can cause #99.

4ad avatar Feb 04 '15 20:02 4ad

On 4 February 2015 at 20:17, Minux Ma [email protected] wrote:

Having SP as the destination is not ambiguous, but what about SP as a source?

MOV SP, Rn

Should this SP be the virtual one or the real one?

It's the real one. The only use of SP as a virtual register is in the o(SP) and (similarly) the $o(SP) form, because the virtual stack pointer is only needed when referring to automatic variables.

forsyth avatar Feb 04 '15 21:02 forsyth

FYI, golang.org/cl/4823

Rob's new cmd/asm treat SP and PC on ARM as pseudo-registers, so if you want to refer to the real hardware register, you have to use R13 and R15 now.

What about SP on ARM64? Should we also introduce a new name for the hardware register?

minux avatar Feb 13 '15 23:02 minux

Rob's new cmd/asm treat SP and PC on ARM as pseudo-registers, so if you want to refer to the real hardware register, you have to use R13 and R15 now.

If that is the cost of removing the ambiguity, so be it. It's not a large cost to bear

At some point I want to ask you why PC and SP are virtual registers, I understand that FP is synthetic and is SP+some offset, but SP and PC always seem to mean what they say they mean

What about SP on ARM64? Should we also introduce a new name for the hardware register?

Can we call it R31 ? That leaves ZR free

— Reply to this email directly or view it on GitHub https://github.com/4ad/go/issues/95#issuecomment-74348302.

davecheney avatar Feb 14 '15 00:02 davecheney

On Fri, Feb 13, 2015 at 7:31 PM, Dave Cheney [email protected] wrote:

At some point I want to ask you why PC and SP are virtual registers, I understand that FP is synthetic and is SP+some offset, but SP and PC always seem to mean what they say they mean

SP is a pseudo register when used with offsets. a+0(SP), etc.

PC is pseudo register when used in jumps, JMP 2(PC)

it doesn't mean jump to 2 machine instructions (or even 2 bytes) off the current PC, it means jump to the 3rd instruction below.

minux avatar Feb 14 '15 00:02 minux

At some point I want to ask you why PC and SP are virtual registers, I understand that FP is synthetic and is SP+some offset, but SP and PC always seem to mean what they say they mean

SP is a pseudo register when used with offsets. a+0(SP), etc

PC is pseudo register when used in jumps,

JMP 2(PC)

ok, that makes sense, especially on intel, but that isn't really a virtual register, the value inside the PC register changes, just the assembler syntesis a label 2 instructions hence, then converts that into ADD offset, PC. I think the term virtual register here is confusing.

it doesn't mean jump to 2 machine instructions (or even 2 bytes) off the current PC, it means jump to the 3rd instruction below.

— Reply to this email directly or view it on GitHub https://github.com/4ad/go/issues/95#issuecomment-74352433.

davecheney avatar Feb 14 '15 01:02 davecheney

I like the idea of differentiating virtual SP from machine SP and from ZR. Disallowing a plain SP, keeping it only for the virtual SP satisfies the first goal. However, I am not too keep on R31 for the machine SP, but I don't have a better suggestion.

4ad avatar Feb 14 '15 10:02 4ad

On 14 February 2015 at 10:03, Aram Hăvărneanu [email protected] wrote:

However, I am not too keep on R31 for the machine SP, but I don't have a better suggestion.

7a already had RSP for the real register

forsyth avatar Feb 14 '15 12:02 forsyth

I missed that. That sounds great.

4ad avatar Feb 14 '15 12:02 4ad

I was bit by this problem again. Basically, each time I see $0(SP), the intent really is $0(RSP).

minux avatar Feb 18 '15 00:02 minux