Commit 236c567b authored by fanzha02's avatar fanzha02 Committed by Cherry Zhang

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/106815Reviewed-by: default avatarCherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 50ccbe1f
...@@ -132,14 +132,8 @@ func arm64RegisterNumber(name string, n int16) (int16, bool) { ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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) { ...@@ -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) { ...@@ -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)&REG_EXT != 0 { if (p.From.Reg-obj.RBaseARM64)&REG_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) { ...@@ -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) { ...@@ -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 { ...@@ -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 { ...@@ -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.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment