diff --git a/src/cmd/asm/internal/arch/arch.go b/src/cmd/asm/internal/arch/arch.go index d989e7511fa80..102dc592b1fd4 100644 --- a/src/cmd/asm/internal/arch/arch.go +++ b/src/cmd/asm/internal/arch/arch.go @@ -442,6 +442,11 @@ var riscvJumps = map[string]bool{ } func archRiscv() *Arch { + // Pseudo-registers. + riscv.Registers["SB"] = RSB + riscv.Registers["FP"] = RFP + riscv.Registers["PC"] = RPC + return &Arch{ LinkArch: &riscv.LinkRISCV, Instructions: riscv.Instructions, diff --git a/src/cmd/asm/internal/asm/testdata/riscv_hello.s b/src/cmd/asm/internal/asm/testdata/riscv_hello.s index 60bca2ae9710a..6f8e873df94db 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv_hello.s +++ b/src/cmd/asm/internal/asm/testdata/riscv_hello.s @@ -2,18 +2,15 @@ #define SYS_WRITE 64 // func helloChar() uint64 -TEXT helloChar(SB),0,$8 +TEXT helloChar(SB),0,$0 MOV $72, T0 - // FIXME(mpratt): this should use FP. - MOV T0, 0(SP) + MOV T0, ret+0(FP) RET // _rt0_riscv_linux is the entry point. -TEXT mainĀ·main(SB),0,$8 +TEXT mainĀ·main(SB),0,$8-0 // Write "H" to stdout...not quite to hello world, yet CALL helloChar(SB) - MOV -8(SP), T0 - MOVW T0, 0(SP) MOV SP, A1 // ptr to data MOV $1, A0 // fd 1 for stdout MOV $1, A2 // len("H") == 1 diff --git a/src/cmd/internal/obj/riscv/asm.go b/src/cmd/internal/obj/riscv/asm.go index f47db9460705b..4cf1924b27462 100644 --- a/src/cmd/internal/obj/riscv/asm.go +++ b/src/cmd/internal/obj/riscv/asm.go @@ -41,13 +41,11 @@ import ( "fmt" ) -// resolvepseudoreg concretizes pseudo-registers in an Addr. -func resolvepseudoreg(a *obj.Addr) { - if a.Type == obj.TYPE_MEM { - switch a.Name { - case obj.NAME_PARAM: - a.Reg = REG_FP - } +// stackOffset updates Addr offsets based on the current stack size. +func stackOffset(a *obj.Addr, stacksize int64) { + switch a.Name { + case obj.NAME_AUTO, obj.NAME_PARAM: + a.Offset += stacksize } } @@ -108,11 +106,9 @@ func movtos(mnemonic obj.As) obj.As { } } -// addrtoreg extracts the register from an addr, handling SB and SP. +// addrtoreg extracts the register from an Addr, handling special Addr.Names. func addrtoreg(a obj.Addr) int16 { switch a.Name { - case obj.NAME_EXTERN: - return REG_SB case obj.NAME_PARAM, obj.NAME_AUTO: return REG_SP } @@ -164,11 +160,6 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { } } - // Concretize pseudo-registers. - resolvepseudoreg(&p.From) - resolvepseudoreg(p.From3) - resolvepseudoreg(&p.To) - // Do additional single-instruction rewriting. switch p.As { // Turn JMP into JAL ZERO or JALR ZERO. @@ -272,10 +263,10 @@ func InvertBranch(i obj.As) obj.As { } } -// preprocess generates prologue and epilogue code and computes PC-relative -// branch and jump offsets. +// preprocess generates prologue and epilogue code, computes PC-relative branch +// and jump offsets, and resolves psuedo-registers. // -// preprocess is called once for each linker symbol. +// preprocess is called once per linker symbol. // // When preprocess finishes, all instructions in the symbol are either // concrete, real RISC-V instructions or directive pseudo-ops like TEXT, @@ -287,7 +278,12 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { ctxt.Diag("preprocess: found symbol that does not start with TEXT directive") return } + stacksize := text.To.Offset + + cursym.Args = text.To.Val.(int32) + cursym.Locals = int32(stacksize) + // Insert stack adjustment if necessary. if stacksize != 0 { spadj := obj.Appendp(ctxt, text) @@ -300,11 +296,25 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { spadj.Spadj = int32(-stacksize) } + // Update stack-based offsets. + for p := cursym.Text; p != nil; p = p.Link { + stackOffset(&p.From, stacksize) + if p.From3 != nil { + stackOffset(p.From3, stacksize) + } + stackOffset(&p.To, stacksize) + + // TODO: update stacksize when instructions that modify SP are + // found, or disallow it entirely. + } + // Additional instruction rewriting. for p := cursym.Text; p != nil; p = p.Link { switch p.As { - // Rewrite MOV. + // Rewrite MOV. This couldn't be done in progedit, as SP + // offsets needed to be applied before we split up some of the + // Addrs. case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU: switch p.From.Type { case obj.TYPE_MEM: // MOV c(Rs), Rd -> L $c, Rs, Rd @@ -404,7 +414,8 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) { p.From.Type = obj.TYPE_CONST switch p.From.Name { case obj.NAME_EXTERN: - p.From3.Reg = REG_SB + // Doesn't matter, we'll add a + // relocation later. case obj.NAME_PARAM, obj.NAME_AUTO: p.From3.Reg = REG_SP default: diff --git a/src/cmd/internal/obj/riscv/cpu.go b/src/cmd/internal/obj/riscv/cpu.go index 6028adee5f0e1..e4bc5b5d4a28c 100644 --- a/src/cmd/internal/obj/riscv/cpu.go +++ b/src/cmd/internal/obj/riscv/cpu.go @@ -116,7 +116,6 @@ const ( REG_T1 = REG_X6 REG_T2 = REG_X7 REG_S0 = REG_X8 - REG_FP = REG_X8 // S0 and FP are the same. REG_S1 = REG_X9 REG_A0 = REG_X10 REG_A1 = REG_X11 @@ -142,7 +141,6 @@ const ( REG_T6 = REG_X31 // Go runtime register names. - REG_SB = REG_X3 // Static base. REG_G = REG_X4 // G pointer. REG_RT1 = REG_S2 // Reserved for runtime (duffzero and duffcopy). REG_RT2 = REG_S3 // Reserved for runtime (duffcopy). diff --git a/src/cmd/internal/obj/riscv/list.go b/src/cmd/internal/obj/riscv/list.go index 4702008eaad58..1765b45a15670 100644 --- a/src/cmd/internal/obj/riscv/list.go +++ b/src/cmd/internal/obj/riscv/list.go @@ -48,13 +48,12 @@ var ( REG_ZERO: "ZERO", REG_RA: "RA", REG_SP: "SP", - // REG_GP is REG_SB + REG_GP: "GP", // REG_TP is REG_G REG_T0: "T0", REG_T1: "T1", REG_T2: "T2", REG_S0: "S0", - // REG_FP is REG_S0. REG_S1: "S1", REG_A0: "A0", REG_A1: "A1", @@ -80,7 +79,6 @@ var ( REG_T6: "T6", // Go runtime register names. - REG_SB: "SB", REG_RT1: "RT1", REG_RT2: "RT2", REG_CTXT: "CTXT", @@ -122,6 +120,8 @@ var ( } ) +// initRegisters initializes the Registers map. arch.archRiscv will also add +// some psuedoregisters. func initRegisters() { // Standard register names. for i := REG_X0; i <= REG_X31; i++ { @@ -134,7 +134,6 @@ func initRegisters() { } // General registers with ABI names. - Registers["ZERO"] = REG_ZERO Registers["RA"] = REG_RA Registers["SP"] = REG_SP @@ -144,7 +143,6 @@ func initRegisters() { Registers["T1"] = REG_T1 Registers["T2"] = REG_T2 Registers["S0"] = REG_S0 - Registers["FP"] = REG_FP Registers["S1"] = REG_S1 Registers["A0"] = REG_A0 Registers["A1"] = REG_A1 @@ -170,7 +168,6 @@ func initRegisters() { Registers["T6"] = REG_T6 // Golang runtime register names. - Registers["SB"] = REG_SB Registers["RT1"] = REG_RT1 Registers["RT2"] = REG_RT2 Registers["CTXT"] = REG_CTXT