mirror of
https://github.com/golang/go
synced 2024-11-22 20:50:05 -07:00
cmd/internal/obj/riscv: absorb rewriteMOV into instruction generation
Replace the now poorly named rewriteMOV function with a markRelocs function, absorbing the MOV validation into the instruction generation code. Change-Id: I6ae94553f7f300862c40310343ef0be8f44a4b0f Reviewed-on: https://go-review.googlesource.com/c/go/+/344459 Trust: Joel Sing <joel@sing.id.au> Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
parent
f5bdbf311c
commit
da790cccc5
@ -218,64 +218,28 @@ func movToStore(mnemonic obj.As) obj.As {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rewriteMOV rewrites MOV pseudo-instructions.
|
// markRelocs marks an obj.Prog that specifies a MOV pseudo-instruction and
|
||||||
func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) {
|
// requires relocation.
|
||||||
|
func markRelocs(p *obj.Prog) {
|
||||||
switch p.As {
|
switch p.As {
|
||||||
case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
|
case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
|
||||||
default:
|
switch {
|
||||||
panic(fmt.Sprintf("%+v is not a MOV pseudo-instruction", p.As))
|
case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
|
||||||
}
|
switch p.From.Name {
|
||||||
|
case obj.NAME_EXTERN, obj.NAME_STATIC:
|
||||||
switch {
|
p.Mark |= NEED_PCREL_ITYPE_RELOC
|
||||||
case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
|
}
|
||||||
|
case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
|
||||||
case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
|
switch p.From.Name {
|
||||||
switch p.From.Name {
|
case obj.NAME_EXTERN, obj.NAME_STATIC:
|
||||||
case obj.NAME_AUTO, obj.NAME_NONE, obj.NAME_PARAM:
|
p.Mark |= NEED_PCREL_ITYPE_RELOC
|
||||||
case obj.NAME_EXTERN, obj.NAME_STATIC:
|
}
|
||||||
p.Mark |= NEED_PCREL_ITYPE_RELOC
|
case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
|
||||||
default:
|
switch p.To.Name {
|
||||||
ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
|
case obj.NAME_EXTERN, obj.NAME_STATIC:
|
||||||
|
p.Mark |= NEED_PCREL_STYPE_RELOC
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
|
|
||||||
switch p.As {
|
|
||||||
case AMOVBU, AMOVHU, AMOVWU:
|
|
||||||
ctxt.Diag("unsupported unsigned store at %v", p)
|
|
||||||
}
|
|
||||||
switch p.To.Name {
|
|
||||||
case obj.NAME_AUTO, obj.NAME_NONE, obj.NAME_PARAM:
|
|
||||||
case obj.NAME_EXTERN, obj.NAME_STATIC:
|
|
||||||
p.Mark |= NEED_PCREL_STYPE_RELOC
|
|
||||||
default:
|
|
||||||
ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
|
|
||||||
}
|
|
||||||
|
|
||||||
case p.From.Type == obj.TYPE_CONST:
|
|
||||||
if p.As != AMOV {
|
|
||||||
ctxt.Diag("%v: unsupported constant load", p)
|
|
||||||
}
|
|
||||||
if p.To.Type != obj.TYPE_REG {
|
|
||||||
ctxt.Diag("%v: constant load must target register", p)
|
|
||||||
}
|
|
||||||
|
|
||||||
case p.From.Type == obj.TYPE_ADDR:
|
|
||||||
if p.As != AMOV {
|
|
||||||
ctxt.Diag("%v: unsupported address load", p)
|
|
||||||
}
|
|
||||||
if p.To.Type != obj.TYPE_REG {
|
|
||||||
ctxt.Diag("%v: address load must target register", p)
|
|
||||||
}
|
|
||||||
switch p.From.Name {
|
|
||||||
case obj.NAME_AUTO, obj.NAME_NONE, obj.NAME_PARAM:
|
|
||||||
case obj.NAME_EXTERN, obj.NAME_STATIC:
|
|
||||||
p.Mark |= NEED_PCREL_ITYPE_RELOC
|
|
||||||
default:
|
|
||||||
ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
ctxt.Diag("unsupported MOV at %v", p)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -641,14 +605,8 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewrite MOV pseudo-instructions. This cannot be done in
|
|
||||||
// progedit, as SP offsets need to be applied before we split
|
|
||||||
// up some of the Addrs.
|
|
||||||
for p := cursym.Func().Text; p != nil; p = p.Link {
|
for p := cursym.Func().Text; p != nil; p = p.Link {
|
||||||
switch p.As {
|
markRelocs(p)
|
||||||
case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
|
|
||||||
rewriteMOV(ctxt, newprog, p)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute instruction addresses. Once we do that, we need to check for
|
// Compute instruction addresses. Once we do that, we need to check for
|
||||||
@ -1746,6 +1704,11 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
|
|||||||
switch {
|
switch {
|
||||||
case p.From.Type == obj.TYPE_CONST && p.To.Type == obj.TYPE_REG:
|
case p.From.Type == obj.TYPE_CONST && p.To.Type == obj.TYPE_REG:
|
||||||
// Handle constant to register moves.
|
// Handle constant to register moves.
|
||||||
|
if p.As != AMOV {
|
||||||
|
p.Ctxt.Diag("%v: unsupported constant load", p)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
low, high, err := Split32BitImmediate(ins.imm)
|
low, high, err := Split32BitImmediate(ins.imm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err)
|
p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err)
|
||||||
@ -1769,6 +1732,10 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
|
|||||||
inss = append(inss, ins)
|
inss = append(inss, ins)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case p.From.Type == obj.TYPE_CONST && p.To.Type != obj.TYPE_REG:
|
||||||
|
p.Ctxt.Diag("%v: constant load must target register", p)
|
||||||
|
return nil
|
||||||
|
|
||||||
case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
|
case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
|
||||||
// Handle register to register moves.
|
// Handle register to register moves.
|
||||||
switch p.As {
|
switch p.As {
|
||||||
@ -1820,13 +1787,17 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
|
|||||||
insAUIPC := &instruction{as: AAUIPC, rd: ins.rd}
|
insAUIPC := &instruction{as: AAUIPC, rd: ins.rd}
|
||||||
ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), ins.rd, obj.REG_NONE, 0
|
ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), ins.rd, obj.REG_NONE, 0
|
||||||
inss = []*instruction{insAUIPC, ins}
|
inss = []*instruction{insAUIPC, ins}
|
||||||
|
|
||||||
|
default:
|
||||||
|
p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
|
case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
|
||||||
// Register to memory stores.
|
// Register to memory stores.
|
||||||
switch p.As {
|
switch p.As {
|
||||||
case AMOVBU, AMOVHU, AMOVWU:
|
case AMOVBU, AMOVHU, AMOVWU:
|
||||||
// rewriteMOV should have already added an error for these.
|
p.Ctxt.Diag("%v: unsupported unsigned store", p)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
switch p.To.Name {
|
switch p.To.Name {
|
||||||
@ -1843,11 +1814,18 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
|
|||||||
insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
|
insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
|
||||||
ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
|
ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
|
||||||
inss = []*instruction{insAUIPC, ins}
|
inss = []*instruction{insAUIPC, ins}
|
||||||
|
|
||||||
|
default:
|
||||||
|
p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
|
case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
|
||||||
// MOV $sym+off(SP/SB), R
|
// MOV $sym+off(SP/SB), R
|
||||||
|
if p.As != AMOV {
|
||||||
|
p.Ctxt.Diag("%v: unsupported address load", p)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
switch p.From.Name {
|
switch p.From.Name {
|
||||||
case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
|
case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
|
||||||
inss = instructionsForOpImmediate(p, AADDI, addrToReg(p.From))
|
inss = instructionsForOpImmediate(p, AADDI, addrToReg(p.From))
|
||||||
@ -1861,15 +1839,19 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
|
|||||||
insAUIPC := &instruction{as: AAUIPC, rd: ins.rd}
|
insAUIPC := &instruction{as: AAUIPC, rd: ins.rd}
|
||||||
ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, ins.rd, obj.REG_NONE, 0
|
ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, ins.rd, obj.REG_NONE, 0
|
||||||
inss = []*instruction{insAUIPC, ins}
|
inss = []*instruction{insAUIPC, ins}
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// If we get here with a MOV pseudo-instruction it is going to
|
p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
|
||||||
// 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 nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case p.From.Type == obj.TYPE_ADDR && p.To.Type != obj.TYPE_REG:
|
||||||
|
p.Ctxt.Diag("%v: address load must target register", p)
|
||||||
|
return nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
p.Ctxt.Diag("%v: unsupported MOV", p)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return inss
|
return inss
|
||||||
|
Loading…
Reference in New Issue
Block a user