1
0
mirror of https://github.com/golang/go synced 2024-11-26 10:18:12 -07:00

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>
This commit is contained in:
Joel Sing 2021-08-24 01:01:06 +10:00
parent 17910ed4ff
commit ab7c904bf2

View File

@ -1823,8 +1823,8 @@ func (ins *instruction) validate(ctxt *obj.Link) {
enc.validate(ctxt, ins) enc.validate(ctxt, ins)
} }
// instructionsForProg returns the machine instructions for an *obj.Prog. // instructionForProg returns the default *obj.Prog to instruction mapping.
func instructionsForProg(p *obj.Prog) []*instruction { func instructionForProg(p *obj.Prog) *instruction {
ins := &instruction{ ins := &instruction{
as: p.As, as: p.As,
rd: uint32(p.To.Reg), rd: uint32(p.To.Reg),
@ -1832,49 +1832,21 @@ func instructionsForProg(p *obj.Prog) []*instruction {
rs2: uint32(p.From.Reg), rs2: uint32(p.From.Reg),
imm: p.From.Offset, imm: p.From.Offset,
} }
if len(p.RestArgs) == 1 { if len(p.RestArgs) == 1 {
ins.rs3 = uint32(p.RestArgs[0].Reg) 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} 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 {
switch ins.as { case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
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:
// Handle register to register moves. // Handle register to register moves.
if p.From.Type != obj.TYPE_REG || p.To.Type != obj.TYPE_REG {
return nil
}
switch p.As { switch p.As {
case AMOV: // MOV Ra, Rb -> ADDI $0, Ra, Rb 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 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) 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: case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD:
if p.From.Type != obj.TYPE_MEM { if p.From.Type != obj.TYPE_MEM {
p.Ctxt.Diag("%v requires memory for source", p) p.Ctxt.Diag("%v requires memory for source", p)