diff options
| author | Joel Sing <joel@sing.id.au> | 2021-08-24 01:01:06 +1000 |
|---|---|---|
| committer | Joel Sing <joel@sing.id.au> | 2021-09-03 05:27:58 +0000 |
| commit | ab7c904bf2bb883b83001d8bb188d1809d74eee6 (patch) | |
| tree | 4eafe9dbc8d8c20671fd22271c65d9f4381604d5 /src/cmd/internal/obj/riscv/obj.go | |
| parent | 17910ed4ff5a3cb3dcf4367d4af23ad5a7fe5809 (diff) | |
| download | go-ab7c904bf2bb883b83001d8bb188d1809d74eee6.tar.xz | |
cmd/internal/obj/riscv: factor out instructions for MOV pseudo-instructions
This factors out the machine instruction generation for MOV pseudo-instructions,
which will simplify further changes.
Change-Id: Ic0d2c3ae9e0881f7894af50ed45e93b0e4961632
Reviewed-on: https://go-review.googlesource.com/c/go/+/344461
Trust: Joel Sing <joel@sing.id.au>
Trust: Meng Zhuo <mzh@golangcn.org>
Run-TryBot: Joel Sing <joel@sing.id.au>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Meng Zhuo <mzh@golangcn.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/cmd/internal/obj/riscv/obj.go')
| -rw-r--r-- | src/cmd/internal/obj/riscv/obj.go | 103 |
1 files changed, 65 insertions, 38 deletions
diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 6de967319c..f602183e04 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -1823,8 +1823,8 @@ func (ins *instruction) validate(ctxt *obj.Link) { enc.validate(ctxt, ins) } -// instructionsForProg returns the machine instructions for an *obj.Prog. -func instructionsForProg(p *obj.Prog) []*instruction { +// instructionForProg returns the default *obj.Prog to instruction mapping. +func instructionForProg(p *obj.Prog) *instruction { ins := &instruction{ as: p.As, rd: uint32(p.To.Reg), @@ -1832,49 +1832,21 @@ func instructionsForProg(p *obj.Prog) []*instruction { rs2: uint32(p.From.Reg), imm: p.From.Offset, } - if len(p.RestArgs) == 1 { ins.rs3 = uint32(p.RestArgs[0].Reg) - } else if len(p.RestArgs) > 0 { - p.Ctxt.Diag("too many source registers") } + return ins +} +// instructionsForMOV returns the machine instructions for an *obj.Prog that +// uses a MOV pseudo-instruction. +func instructionsForMOV(p *obj.Prog) []*instruction { + ins := instructionForProg(p) inss := []*instruction{ins} - switch ins.as { - case AJAL, AJALR: - ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.To.Reg), obj.REG_NONE - ins.imm = p.To.Offset - case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ: - switch ins.as { - case ABEQZ: - ins.as, ins.rs1, ins.rs2 = ABEQ, REG_ZERO, uint32(p.From.Reg) - case ABGEZ: - ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg) - case ABGT: - ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), uint32(p.Reg) - case ABGTU: - ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.From.Reg), uint32(p.Reg) - case ABGTZ: - ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO - case ABLE: - ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), uint32(p.Reg) - case ABLEU: - ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.From.Reg), uint32(p.Reg) - case ABLEZ: - ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO - case ABLTZ: - ins.as, ins.rs1, ins.rs2 = ABLT, REG_ZERO, uint32(p.From.Reg) - case ABNEZ: - ins.as, ins.rs1, ins.rs2 = ABNE, REG_ZERO, uint32(p.From.Reg) - } - ins.imm = p.To.Offset - - case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: + switch { + case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG: // Handle register to register moves. - if p.From.Type != obj.TYPE_REG || p.To.Type != obj.TYPE_REG { - return nil - } switch p.As { case AMOV: // MOV Ra, Rb -> ADDI $0, Ra, Rb ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, uint32(p.From.Reg), obj.REG_NONE, 0 @@ -1908,6 +1880,61 @@ func instructionsForProg(p *obj.Prog) []*instruction { inss = append(inss, ins2) } + default: + // If we get here with a MOV pseudo-instruction it is going to + // remain unhandled. For now we trust rewriteMOV to catch these. + switch p.As { + case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: + return nil + } + } + + return inss +} + +// instructionsForProg returns the machine instructions for an *obj.Prog. +func instructionsForProg(p *obj.Prog) []*instruction { + ins := instructionForProg(p) + inss := []*instruction{ins} + + if len(p.RestArgs) > 1 { + p.Ctxt.Diag("too many source registers") + return nil + } + + switch ins.as { + case AJAL, AJALR: + ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.To.Reg), obj.REG_NONE + ins.imm = p.To.Offset + + case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ: + switch ins.as { + case ABEQZ: + ins.as, ins.rs1, ins.rs2 = ABEQ, REG_ZERO, uint32(p.From.Reg) + case ABGEZ: + ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg) + case ABGT: + ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), uint32(p.Reg) + case ABGTU: + ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.From.Reg), uint32(p.Reg) + case ABGTZ: + ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO + case ABLE: + ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), uint32(p.Reg) + case ABLEU: + ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.From.Reg), uint32(p.Reg) + case ABLEZ: + ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO + case ABLTZ: + ins.as, ins.rs1, ins.rs2 = ABLT, REG_ZERO, uint32(p.From.Reg) + case ABNEZ: + ins.as, ins.rs1, ins.rs2 = ABNE, REG_ZERO, uint32(p.From.Reg) + } + ins.imm = p.To.Offset + + case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD: + return instructionsForMOV(p) + case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD: if p.From.Type != obj.TYPE_MEM { p.Ctxt.Diag("%v requires memory for source", p) |
