mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/internal/obj/arm64: refactor the extended/shifted register encoding to the backend
The current code encodes the register and the shift/extension into a.Offset field and this is done in the frontend. The CL refactors it to have the frontend record the register/shift/extension information in a.Reg or a.Index and leave the encoding stuff for the backend. Change-Id: I600f456aec95377b7b79cd58e94afcb30aca5d19 Reviewed-on: https://go-review.googlesource.com/106815 Reviewed-by: Cherry Zhang <cherryyz@google.com> Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
50ccbe1fc2
commit
236c567ba9
3 changed files with 70 additions and 48 deletions
|
|
@ -132,14 +132,8 @@ func arm64RegisterNumber(name string, n int16) (int16, bool) {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// rm is the Rm register value, o is the extension, amount is the left shift value.
|
|
||||||
func roff(rm uint32, o uint32, amount int16) int64 {
|
|
||||||
return int64((rm&31)<<16 | o<<13 | uint32(amount)<<10)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ARM64RegisterExtension parses an ARM64 register with extension or arrangement.
|
// ARM64RegisterExtension parses an ARM64 register with extension or arrangement.
|
||||||
func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, isIndex bool) error {
|
func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, isIndex bool) error {
|
||||||
rm := uint32(reg)
|
|
||||||
Rnum := (reg & 31) + int16(num<<5)
|
Rnum := (reg & 31) + int16(num<<5)
|
||||||
if isAmount {
|
if isAmount {
|
||||||
if num < 0 || num > 7 {
|
if num < 0 || num > 7 {
|
||||||
|
|
@ -155,7 +149,6 @@ func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, i
|
||||||
return errors.New("invalid shift for the register offset addressing mode")
|
return errors.New("invalid shift for the register offset addressing mode")
|
||||||
}
|
}
|
||||||
a.Reg = arm64.REG_UXTB + Rnum
|
a.Reg = arm64.REG_UXTB + Rnum
|
||||||
a.Offset = roff(rm, 0, num)
|
|
||||||
case "UXTH":
|
case "UXTH":
|
||||||
if !isAmount {
|
if !isAmount {
|
||||||
return errors.New("invalid register extension")
|
return errors.New("invalid register extension")
|
||||||
|
|
@ -164,7 +157,6 @@ func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, i
|
||||||
return errors.New("invalid shift for the register offset addressing mode")
|
return errors.New("invalid shift for the register offset addressing mode")
|
||||||
}
|
}
|
||||||
a.Reg = arm64.REG_UXTH + Rnum
|
a.Reg = arm64.REG_UXTH + Rnum
|
||||||
a.Offset = roff(rm, 1, num)
|
|
||||||
case "UXTW":
|
case "UXTW":
|
||||||
if !isAmount {
|
if !isAmount {
|
||||||
return errors.New("invalid register extension")
|
return errors.New("invalid register extension")
|
||||||
|
|
@ -172,14 +164,8 @@ func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, i
|
||||||
// effective address of memory is a base register value and an offset register value.
|
// effective address of memory is a base register value and an offset register value.
|
||||||
if a.Type == obj.TYPE_MEM {
|
if a.Type == obj.TYPE_MEM {
|
||||||
a.Index = arm64.REG_UXTW + Rnum
|
a.Index = arm64.REG_UXTW + Rnum
|
||||||
if num == 0 {
|
|
||||||
a.Offset = roff(rm, 2, 2)
|
|
||||||
} else {
|
|
||||||
a.Offset = roff(rm, 2, 6)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
a.Reg = arm64.REG_UXTW + Rnum
|
a.Reg = arm64.REG_UXTW + Rnum
|
||||||
a.Offset = roff(rm, 2, num)
|
|
||||||
}
|
}
|
||||||
case "UXTX":
|
case "UXTX":
|
||||||
if !isAmount {
|
if !isAmount {
|
||||||
|
|
@ -189,13 +175,11 @@ func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, i
|
||||||
return errors.New("invalid shift for the register offset addressing mode")
|
return errors.New("invalid shift for the register offset addressing mode")
|
||||||
}
|
}
|
||||||
a.Reg = arm64.REG_UXTX + Rnum
|
a.Reg = arm64.REG_UXTX + Rnum
|
||||||
a.Offset = roff(rm, 3, num)
|
|
||||||
case "SXTB":
|
case "SXTB":
|
||||||
if !isAmount {
|
if !isAmount {
|
||||||
return errors.New("invalid register extension")
|
return errors.New("invalid register extension")
|
||||||
}
|
}
|
||||||
a.Reg = arm64.REG_SXTB + Rnum
|
a.Reg = arm64.REG_SXTB + Rnum
|
||||||
a.Offset = roff(rm, 4, num)
|
|
||||||
case "SXTH":
|
case "SXTH":
|
||||||
if !isAmount {
|
if !isAmount {
|
||||||
return errors.New("invalid register extension")
|
return errors.New("invalid register extension")
|
||||||
|
|
@ -204,21 +188,14 @@ func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, i
|
||||||
return errors.New("invalid shift for the register offset addressing mode")
|
return errors.New("invalid shift for the register offset addressing mode")
|
||||||
}
|
}
|
||||||
a.Reg = arm64.REG_SXTH + Rnum
|
a.Reg = arm64.REG_SXTH + Rnum
|
||||||
a.Offset = roff(rm, 5, num)
|
|
||||||
case "SXTW":
|
case "SXTW":
|
||||||
if !isAmount {
|
if !isAmount {
|
||||||
return errors.New("invalid register extension")
|
return errors.New("invalid register extension")
|
||||||
}
|
}
|
||||||
if a.Type == obj.TYPE_MEM {
|
if a.Type == obj.TYPE_MEM {
|
||||||
a.Index = arm64.REG_SXTW + Rnum
|
a.Index = arm64.REG_SXTW + Rnum
|
||||||
if num == 0 {
|
|
||||||
a.Offset = roff(rm, 6, 2)
|
|
||||||
} else {
|
|
||||||
a.Offset = roff(rm, 6, 6)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
a.Reg = arm64.REG_SXTW + Rnum
|
a.Reg = arm64.REG_SXTW + Rnum
|
||||||
a.Offset = roff(rm, 6, num)
|
|
||||||
}
|
}
|
||||||
case "SXTX":
|
case "SXTX":
|
||||||
if !isAmount {
|
if !isAmount {
|
||||||
|
|
@ -226,21 +203,14 @@ func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, i
|
||||||
}
|
}
|
||||||
if a.Type == obj.TYPE_MEM {
|
if a.Type == obj.TYPE_MEM {
|
||||||
a.Index = arm64.REG_SXTX + Rnum
|
a.Index = arm64.REG_SXTX + Rnum
|
||||||
if num == 0 {
|
|
||||||
a.Offset = roff(rm, 7, 2)
|
|
||||||
} else {
|
|
||||||
a.Offset = roff(rm, 7, 6)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
a.Reg = arm64.REG_SXTX + Rnum
|
a.Reg = arm64.REG_SXTX + Rnum
|
||||||
a.Offset = roff(rm, 7, num)
|
|
||||||
}
|
}
|
||||||
case "LSL":
|
case "LSL":
|
||||||
if !isAmount {
|
if !isAmount {
|
||||||
return errors.New("invalid register extension")
|
return errors.New("invalid register extension")
|
||||||
}
|
}
|
||||||
a.Index = arm64.REG_LSL + Rnum
|
a.Index = arm64.REG_LSL + Rnum
|
||||||
a.Offset = roff(rm, 3, 6)
|
|
||||||
case "B8":
|
case "B8":
|
||||||
if isIndex {
|
if isIndex {
|
||||||
return errors.New("invalid register extension")
|
return errors.New("invalid register extension")
|
||||||
|
|
|
||||||
|
|
@ -2511,11 +2511,12 @@ func (c *ctxt7) checkShiftAmount(p *obj.Prog, a *obj.Addr) {
|
||||||
if amount != 2 && amount != 0 {
|
if amount != 2 && amount != 0 {
|
||||||
c.ctxt.Diag("invalid index shift amount: %v", p)
|
c.ctxt.Diag("invalid index shift amount: %v", p)
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMOVD:
|
case AMOVD:
|
||||||
if amount != 3 && amount != 0 {
|
if amount != 3 && amount != 0 {
|
||||||
c.ctxt.Diag("invalid index shift amount: %v", p)
|
c.ctxt.Diag("invalid index shift amount: %v", p)
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
panic("invalid operation")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2955,14 +2956,13 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
||||||
o1 |= (REGZERO & 31 << 5) | uint32(rt&31)
|
o1 |= (REGZERO & 31 << 5) | uint32(rt&31)
|
||||||
|
|
||||||
case 27: /* op Rm<<n[,Rn],Rd (extended register) */
|
case 27: /* op Rm<<n[,Rn],Rd (extended register) */
|
||||||
|
|
||||||
if (p.From.Reg-obj.RBaseARM64)®_EXT != 0 {
|
if (p.From.Reg-obj.RBaseARM64)®_EXT != 0 {
|
||||||
amount := (p.From.Reg >> 5) & 7
|
amount := (p.From.Reg >> 5) & 7
|
||||||
if amount > 4 {
|
if amount > 4 {
|
||||||
c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
|
c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
|
||||||
}
|
}
|
||||||
o1 = c.opxrrr(p, p.As, true)
|
o1 = c.opxrrr(p, p.As, true)
|
||||||
o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
|
o1 |= c.encRegShiftOrExt(&p.From, p.From.Reg) /* includes reg, op, etc */
|
||||||
} else {
|
} else {
|
||||||
o1 = c.opxrrr(p, p.As, false)
|
o1 = c.opxrrr(p, p.As, false)
|
||||||
o1 |= uint32(p.From.Reg&31) << 16
|
o1 |= uint32(p.From.Reg&31) << 16
|
||||||
|
|
@ -4467,11 +4467,12 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
||||||
o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31)
|
o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31)
|
||||||
|
|
||||||
case 98: /* MOVD (Rn)(Rm.SXTW[<<amount]),Rd */
|
case 98: /* MOVD (Rn)(Rm.SXTW[<<amount]),Rd */
|
||||||
if p.From.Offset != 0 {
|
if isRegShiftOrExt(&p.From) {
|
||||||
// extended or shifted offset register.
|
// extended or shifted offset register.
|
||||||
c.checkShiftAmount(p, &p.From)
|
c.checkShiftAmount(p, &p.From)
|
||||||
|
|
||||||
o1 = c.opldrr(p, p.As, true)
|
o1 = c.opldrr(p, p.As, true)
|
||||||
o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
|
o1 |= c.encRegShiftOrExt(&p.From, p.From.Index) /* includes reg, op, etc */
|
||||||
} else {
|
} else {
|
||||||
// (Rn)(Rm), no extension or shift.
|
// (Rn)(Rm), no extension or shift.
|
||||||
o1 = c.opldrr(p, p.As, false)
|
o1 = c.opldrr(p, p.As, false)
|
||||||
|
|
@ -4482,11 +4483,12 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
||||||
o1 |= uint32(rt & 31)
|
o1 |= uint32(rt & 31)
|
||||||
|
|
||||||
case 99: /* MOVD Rt, (Rn)(Rm.SXTW[<<amount]) */
|
case 99: /* MOVD Rt, (Rn)(Rm.SXTW[<<amount]) */
|
||||||
if p.To.Offset != 0 {
|
if isRegShiftOrExt(&p.To) {
|
||||||
// extended or shifted offset register.
|
// extended or shifted offset register.
|
||||||
c.checkShiftAmount(p, &p.To)
|
c.checkShiftAmount(p, &p.To)
|
||||||
|
|
||||||
o1 = c.opstrr(p, p.As, true)
|
o1 = c.opstrr(p, p.As, true)
|
||||||
o1 |= uint32(p.To.Offset) /* includes reg, op, etc */
|
o1 |= c.encRegShiftOrExt(&p.To, p.To.Index) /* includes reg, op, etc */
|
||||||
} else {
|
} else {
|
||||||
// (Rn)(Rm), no extension or shift.
|
// (Rn)(Rm), no extension or shift.
|
||||||
o1 = c.opstrr(p, p.As, false)
|
o1 = c.opstrr(p, p.As, false)
|
||||||
|
|
@ -6093,3 +6095,63 @@ func movesize(a obj.As) int {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rm is the Rm register value, o is the extension, amount is the left shift value.
|
||||||
|
func roff(rm int16, o uint32, amount int16) uint32 {
|
||||||
|
return uint32(rm&31)<<16 | o<<13 | uint32(amount)<<10
|
||||||
|
}
|
||||||
|
|
||||||
|
// encRegShiftOrExt returns the encoding of shifted/extended register, Rx<<n and Rx.UXTW<<n, etc.
|
||||||
|
func (c *ctxt7) encRegShiftOrExt(a *obj.Addr, r int16) uint32 {
|
||||||
|
var num, rm int16
|
||||||
|
num = (r >> 5) & 7
|
||||||
|
rm = r & 31
|
||||||
|
switch {
|
||||||
|
case REG_UXTB <= r && r < REG_UXTH:
|
||||||
|
return roff(rm, 0, num)
|
||||||
|
case REG_UXTH <= r && r < REG_UXTW:
|
||||||
|
return roff(rm, 1, num)
|
||||||
|
case REG_UXTW <= r && r < REG_UXTX:
|
||||||
|
if a.Type == obj.TYPE_MEM {
|
||||||
|
if num == 0 {
|
||||||
|
return roff(rm, 2, 2)
|
||||||
|
} else {
|
||||||
|
return roff(rm, 2, 6)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return roff(rm, 2, num)
|
||||||
|
}
|
||||||
|
case REG_UXTX <= r && r < REG_SXTB:
|
||||||
|
return roff(rm, 3, num)
|
||||||
|
case REG_SXTB <= r && r < REG_SXTH:
|
||||||
|
return roff(rm, 4, num)
|
||||||
|
case REG_SXTH <= r && r < REG_SXTW:
|
||||||
|
return roff(rm, 5, num)
|
||||||
|
case REG_SXTW <= r && r < REG_SXTX:
|
||||||
|
if a.Type == obj.TYPE_MEM {
|
||||||
|
if num == 0 {
|
||||||
|
return roff(rm, 6, 2)
|
||||||
|
} else {
|
||||||
|
return roff(rm, 6, 6)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return roff(rm, 6, num)
|
||||||
|
}
|
||||||
|
case REG_SXTX <= r && r < REG_SPECIAL:
|
||||||
|
if a.Type == obj.TYPE_MEM {
|
||||||
|
if num == 0 {
|
||||||
|
return roff(rm, 7, 2)
|
||||||
|
} else {
|
||||||
|
return roff(rm, 7, 6)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return roff(rm, 7, num)
|
||||||
|
}
|
||||||
|
case REG_LSL <= r && r < (REG_LSL+1<<8):
|
||||||
|
return roff(rm, 3, 6)
|
||||||
|
default:
|
||||||
|
c.ctxt.Diag("unsupported register extension type.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -299,17 +299,7 @@ func Mconv(a *Addr) string {
|
||||||
case a.Offset == 0:
|
case a.Offset == 0:
|
||||||
str = fmt.Sprintf("(%v)", Rconv(int(a.Reg)))
|
str = fmt.Sprintf("(%v)", Rconv(int(a.Reg)))
|
||||||
case a.Offset != 0:
|
case a.Offset != 0:
|
||||||
switch objabi.GOARCH {
|
str = fmt.Sprintf("%d(%v)", a.Offset, Rconv(int(a.Reg)))
|
||||||
case "arm64":
|
|
||||||
// the register and the extension/shift are encoded in a.Offset.
|
|
||||||
if a.Index != 0 {
|
|
||||||
str = fmt.Sprintf("(%v)", Rconv(int(a.Reg)))
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
fallthrough
|
|
||||||
default:
|
|
||||||
str = fmt.Sprintf("%d(%v)", a.Offset, Rconv(int(a.Reg)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: a.Reg == REG_NONE encodes the default base register for the NAME_ type.
|
// Note: a.Reg == REG_NONE encodes the default base register for the NAME_ type.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue