{ACMP, C_VCON, C_REG, C_NONE, C_NONE, 13, 20, 0, 0, 0},
{AADD, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
{AADD, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
- {AADD, C_SHIFT, C_RSP, C_NONE, C_RSP, 26, 4, 0, 0, 0},
- {AADD, C_SHIFT, C_NONE, C_NONE, C_RSP, 26, 4, 0, 0, 0},
{AMVN, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
{ACMP, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0},
- {ACMP, C_SHIFT, C_RSP, C_NONE, C_NONE, 26, 4, 0, 0, 0},
{ANEG, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
{AADD, C_REG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0},
{AADD, C_REG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0},
return C_ARNG
case r >= REG_ELEM && r < REG_ELEM_END:
return C_ELEM
- case r >= REG_UXTB && r < REG_SPECIAL:
+ case r >= REG_UXTB && r < REG_SPECIAL,
+ r >= REG_LSL && r < REG_ARNG:
return C_EXTREG
case r >= REG_SPECIAL:
return C_SPR
rt := int(p.To.Reg)
o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
- case 26: // op R<<n, RSP, RSP (extended register)
- // Refer to ARM reference manual, if "Rd" or "Rn" is RSP,
- // it can be encoded as op(extended regster) instruction.
- if !(p.To.Reg == REGSP || p.Reg == REGSP) {
- c.ctxt.Diag("expected SP reference: %v", p)
- break
- }
- if p.To.Reg == REGSP && (p.As == AADDS || p.As == AADDSW || p.As == ASUBS || p.As == ASUBSW) {
- c.ctxt.Diag("unexpected SP reference: %v", p)
- break
- }
- amount := (p.From.Offset >> 10) & 63
- shift := (p.From.Offset >> 22) & 3
- if shift != 0 {
- c.ctxt.Diag("illegal combination: %v", p)
- break
- }
-
- if amount > 4 {
- c.ctxt.Diag("the left shift amount out of range 0 to 4: %v", p)
- break
- }
- rf := (p.From.Offset >> 16) & 31
- rt := int(p.To.Reg)
- r := int(p.Reg)
- if p.To.Type == obj.TYPE_NONE {
- rt = REGZERO
- }
- if r == 0 {
- r = rt
- }
-
- o1 = c.opxrrr(p, p.As, false)
- o1 |= uint32(rf)<<16 | uint32(amount&7)<<10 | (uint32(r&31) << 5) | uint32(rt&31)
-
case 27: /* op Rm<<n[,Rn],Rd (extended register) */
if p.To.Reg == REG_RSP && isADDSop(p.As) {
c.ctxt.Diag("illegal destination register: %v\n", p)
}
- if (p.From.Reg-obj.RBaseARM64)®_EXT != 0 {
+ if (p.From.Reg-obj.RBaseARM64)®_EXT != 0 ||
+ (p.From.Reg >= REG_LSL && p.From.Reg < REG_ARNG) {
amount := (p.From.Reg >> 5) & 7
if amount > 4 {
c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
}
o1 = c.opxrrr(p, p.As, true)
- o1 |= c.encRegShiftOrExt(&p.From, p.From.Reg) /* includes reg, op, etc */
+ o1 |= c.encRegShiftOrExt(p, &p.From, p.From.Reg) /* includes reg, op, etc */
} else {
o1 = c.opxrrr(p, p.As, false)
o1 |= uint32(p.From.Reg&31) << 16
c.checkShiftAmount(p, &p.From)
o1 = c.opldrr(p, p.As, true)
- o1 |= c.encRegShiftOrExt(&p.From, p.From.Index) /* includes reg, op, etc */
+ o1 |= c.encRegShiftOrExt(p, &p.From, p.From.Index) /* includes reg, op, etc */
} else {
// (Rn)(Rm), no extension or shift.
o1 = c.opldrr(p, p.As, false)
c.checkShiftAmount(p, &p.To)
o1 = c.opstrr(p, p.As, true)
- o1 |= c.encRegShiftOrExt(&p.To, p.To.Index) /* includes reg, op, etc */
+ o1 |= c.encRegShiftOrExt(p, &p.To, p.To.Index) /* includes reg, op, etc */
} else {
// (Rn)(Rm), no extension or shift.
o1 = c.opstrr(p, p.As, false)
}
// 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 {
+func (c *ctxt7) encRegShiftOrExt(p *obj.Prog, a *obj.Addr, r int16) uint32 {
var num, rm int16
num = (r >> 5) & 7
rm = r & 31
} else {
return roff(rm, 7, num)
}
- case REG_LSL <= r && r < (REG_LSL+1<<8):
- return roff(rm, 3, 6)
+ case REG_LSL <= r && r < REG_ARNG:
+ if a.Type == obj.TYPE_MEM { // (R1)(R2<<1)
+ return roff(rm, 3, 6)
+ } else if isADDWop(p.As) {
+ return roff(rm, 2, num)
+ }
+ return roff(rm, 3, num)
default:
c.ctxt.Diag("unsupported register extension type.")
}