mirror of
https://github.com/golang/go
synced 2024-11-26 05:48:05 -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:
parent
17910ed4ff
commit
ab7c904bf2
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user