Skip to content

Commit e4d2172

Browse files
committed
all: handle FP offsets
Remove both FP and SB as concrete registers; they are purely psuedo-registers. FP offsets are handled by adding the current SP adjustment to the offset of NAME_PARAM Addrs. I am unsure of my arg and frame sizes in riscv_hello.s. It is not clear to me if callers are supposed to leave room for return values in their frame size or if callees are supposed to add them to their argument size. The assembly in the runtime seems to be inconsistent. Fixes golang#8 Change-Id: Ib79efb4fea8629f22461b4ebfc987bc8785a3ce3
1 parent 06c03cc commit e4d2172

File tree

5 files changed

+42
-34
lines changed

5 files changed

+42
-34
lines changed

src/cmd/asm/internal/arch/arch.go

+5
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,11 @@ var riscvJumps = map[string]bool{
442442
}
443443

444444
func archRiscv() *Arch {
445+
// Pseudo-registers.
446+
riscv.Registers["SB"] = RSB
447+
riscv.Registers["FP"] = RFP
448+
riscv.Registers["PC"] = RPC
449+
445450
return &Arch{
446451
LinkArch: &riscv.LinkRISCV,
447452
Instructions: riscv.Instructions,

src/cmd/asm/internal/asm/testdata/riscv_hello.s

+3-6
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,15 @@
22
#define SYS_WRITE 64
33

44
// func helloChar() uint64
5-
TEXT helloChar(SB),0,$8
5+
TEXT helloChar(SB),0,$0
66
MOV $72, T0
7-
// FIXME(mpratt): this should use FP.
8-
MOV T0, 0(SP)
7+
MOV T0, ret+0(FP)
98
RET
109

1110
// _rt0_riscv_linux is the entry point.
12-
TEXT main·main(SB),0,$8
11+
TEXT main·main(SB),0,$8-0
1312
// Write "H" to stdout...not quite to hello world, yet
1413
CALL helloChar(SB)
15-
MOV -8(SP), T0
16-
MOVW T0, 0(SP)
1714
MOV SP, A1 // ptr to data
1815
MOV $1, A0 // fd 1 for stdout
1916
MOV $1, A2 // len("H") == 1

src/cmd/internal/obj/riscv/asm.go

+31-20
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,11 @@ import (
4141
"fmt"
4242
)
4343

44-
// resolvepseudoreg concretizes pseudo-registers in an Addr.
45-
func resolvepseudoreg(a *obj.Addr) {
46-
if a.Type == obj.TYPE_MEM {
47-
switch a.Name {
48-
case obj.NAME_PARAM:
49-
a.Reg = REG_FP
50-
}
44+
// stackOffset updates Addr offsets based on the current stack size.
45+
func stackOffset(a *obj.Addr, stacksize int64) {
46+
switch a.Name {
47+
case obj.NAME_AUTO, obj.NAME_PARAM:
48+
a.Offset += stacksize
5149
}
5250
}
5351

@@ -108,11 +106,9 @@ func movtos(mnemonic obj.As) obj.As {
108106
}
109107
}
110108

111-
// addrtoreg extracts the register from an addr, handling SB and SP.
109+
// addrtoreg extracts the register from an Addr, handling special Addr.Names.
112110
func addrtoreg(a obj.Addr) int16 {
113111
switch a.Name {
114-
case obj.NAME_EXTERN:
115-
return REG_SB
116112
case obj.NAME_PARAM, obj.NAME_AUTO:
117113
return REG_SP
118114
}
@@ -164,11 +160,6 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
164160
}
165161
}
166162

167-
// Concretize pseudo-registers.
168-
resolvepseudoreg(&p.From)
169-
resolvepseudoreg(p.From3)
170-
resolvepseudoreg(&p.To)
171-
172163
// Do additional single-instruction rewriting.
173164
switch p.As {
174165
// Turn JMP into JAL ZERO or JALR ZERO.
@@ -272,10 +263,10 @@ func InvertBranch(i obj.As) obj.As {
272263
}
273264
}
274265

275-
// preprocess generates prologue and epilogue code and computes PC-relative
276-
// branch and jump offsets.
266+
// preprocess generates prologue and epilogue code, computes PC-relative branch
267+
// and jump offsets, and resolves psuedo-registers.
277268
//
278-
// preprocess is called once for each linker symbol.
269+
// preprocess is called once per linker symbol.
279270
//
280271
// When preprocess finishes, all instructions in the symbol are either
281272
// concrete, real RISC-V instructions or directive pseudo-ops like TEXT,
@@ -287,7 +278,12 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
287278
ctxt.Diag("preprocess: found symbol that does not start with TEXT directive")
288279
return
289280
}
281+
290282
stacksize := text.To.Offset
283+
284+
cursym.Args = text.To.Val.(int32)
285+
cursym.Locals = int32(stacksize)
286+
291287
// Insert stack adjustment if necessary.
292288
if stacksize != 0 {
293289
spadj := obj.Appendp(ctxt, text)
@@ -300,11 +296,25 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
300296
spadj.Spadj = int32(-stacksize)
301297
}
302298

299+
// Update stack-based offsets.
300+
for p := cursym.Text; p != nil; p = p.Link {
301+
stackOffset(&p.From, stacksize)
302+
if p.From3 != nil {
303+
stackOffset(p.From3, stacksize)
304+
}
305+
stackOffset(&p.To, stacksize)
306+
307+
// TODO: update stacksize when instructions that modify SP are
308+
// found, or disallow it entirely.
309+
}
310+
303311
// Additional instruction rewriting.
304312
for p := cursym.Text; p != nil; p = p.Link {
305313
switch p.As {
306314

307-
// Rewrite MOV.
315+
// Rewrite MOV. This couldn't be done in progedit, as SP
316+
// offsets needed to be applied before we split up some of the
317+
// Addrs.
308318
case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU:
309319
switch p.From.Type {
310320
case obj.TYPE_MEM: // MOV c(Rs), Rd -> L $c, Rs, Rd
@@ -404,7 +414,8 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
404414
p.From.Type = obj.TYPE_CONST
405415
switch p.From.Name {
406416
case obj.NAME_EXTERN:
407-
p.From3.Reg = REG_SB
417+
// Doesn't matter, we'll add a
418+
// relocation later.
408419
case obj.NAME_PARAM, obj.NAME_AUTO:
409420
p.From3.Reg = REG_SP
410421
default:

src/cmd/internal/obj/riscv/cpu.go

-2
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ const (
116116
REG_T1 = REG_X6
117117
REG_T2 = REG_X7
118118
REG_S0 = REG_X8
119-
REG_FP = REG_X8 // S0 and FP are the same.
120119
REG_S1 = REG_X9
121120
REG_A0 = REG_X10
122121
REG_A1 = REG_X11
@@ -142,7 +141,6 @@ const (
142141
REG_T6 = REG_X31
143142

144143
// Go runtime register names.
145-
REG_SB = REG_X3 // Static base.
146144
REG_G = REG_X4 // G pointer.
147145
REG_RT1 = REG_S2 // Reserved for runtime (duffzero and duffcopy).
148146
REG_RT2 = REG_S3 // Reserved for runtime (duffcopy).

src/cmd/internal/obj/riscv/list.go

+3-6
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,12 @@ var (
4848
REG_ZERO: "ZERO",
4949
REG_RA: "RA",
5050
REG_SP: "SP",
51-
// REG_GP is REG_SB
51+
REG_GP: "GP",
5252
// REG_TP is REG_G
5353
REG_T0: "T0",
5454
REG_T1: "T1",
5555
REG_T2: "T2",
5656
REG_S0: "S0",
57-
// REG_FP is REG_S0.
5857
REG_S1: "S1",
5958
REG_A0: "A0",
6059
REG_A1: "A1",
@@ -80,7 +79,6 @@ var (
8079
REG_T6: "T6",
8180

8281
// Go runtime register names.
83-
REG_SB: "SB",
8482
REG_RT1: "RT1",
8583
REG_RT2: "RT2",
8684
REG_CTXT: "CTXT",
@@ -122,6 +120,8 @@ var (
122120
}
123121
)
124122

123+
// initRegisters initializes the Registers map. arch.archRiscv will also add
124+
// some psuedoregisters.
125125
func initRegisters() {
126126
// Standard register names.
127127
for i := REG_X0; i <= REG_X31; i++ {
@@ -134,7 +134,6 @@ func initRegisters() {
134134
}
135135

136136
// General registers with ABI names.
137-
138137
Registers["ZERO"] = REG_ZERO
139138
Registers["RA"] = REG_RA
140139
Registers["SP"] = REG_SP
@@ -144,7 +143,6 @@ func initRegisters() {
144143
Registers["T1"] = REG_T1
145144
Registers["T2"] = REG_T2
146145
Registers["S0"] = REG_S0
147-
Registers["FP"] = REG_FP
148146
Registers["S1"] = REG_S1
149147
Registers["A0"] = REG_A0
150148
Registers["A1"] = REG_A1
@@ -170,7 +168,6 @@ func initRegisters() {
170168
Registers["T6"] = REG_T6
171169

172170
// Golang runtime register names.
173-
Registers["SB"] = REG_SB
174171
Registers["RT1"] = REG_RT1
175172
Registers["RT2"] = REG_RT2
176173
Registers["CTXT"] = REG_CTXT

0 commit comments

Comments
 (0)