diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s index 3d3de1d9b13..033c4cda6c8 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64error.s +++ b/src/cmd/asm/internal/asm/testdata/arm64error.s @@ -417,8 +417,8 @@ TEXT errors(SB),$0 CASPD (R2, R4), (R2), (R8, R9) // ERROR "source register pair must be contiguous" CASPD (R2, R3), (R2), (R8, R10) // ERROR "destination register pair must be contiguous" ADD R1>>2, RSP, R3 // ERROR "illegal combination" - ADDS R2<<3, R3, RSP // ERROR "unexpected SP reference" - CMP R1<<5, RSP // ERROR "the left shift amount out of range 0 to 4" + ADDS R2<<3, R3, RSP // ERROR "illegal destination register" + CMP R1<<5, RSP // ERROR "shift amount out of range 0 to 4" MOVD.P y+8(FP), R1 // ERROR "illegal combination" MOVD.W x-8(SP), R1 // ERROR "illegal combination" LDP.P x+8(FP), (R0, R1) // ERROR "illegal combination" diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index f4111f4f5cd..5435b2248fa 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -321,11 +321,8 @@ var optab = []Optab{ {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}, @@ -1687,7 +1684,8 @@ func rclass(r int16) int { 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 @@ -3666,52 +3664,18 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { rt := int(p.To.Reg) o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) - case 26: // op R<> 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<= 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 @@ -5344,7 +5308,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { 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) @@ -5360,7 +5324,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { 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) @@ -7427,7 +7391,7 @@ func roff(rm int16, o uint32, amount int16) uint32 { } // encRegShiftOrExt returns the encoding of shifted/extended register, Rx<> 5) & 7 rm = r & 31 @@ -7472,8 +7436,13 @@ func (c *ctxt7) encRegShiftOrExt(a *obj.Addr, r int16) uint32 { } 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.") } diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go index 43f7b16d6e2..ee5a6fa273e 100644 --- a/src/cmd/internal/obj/arm64/obj7.go +++ b/src/cmd/internal/obj/arm64/obj7.go @@ -1089,6 +1089,24 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } } } + if p.From.Type == obj.TYPE_SHIFT && (p.To.Reg == REG_RSP || p.Reg == REG_RSP) { + offset := p.From.Offset + op := offset & (3 << 22) + if op != SHIFT_LL { + ctxt.Diag("illegal combination: %v", p) + } + r := (offset >> 16) & 31 + shift := (offset >> 10) & 63 + if shift > 4 { + // the shift amount is out of range, in order to avoid repeated error + // reportings, don't call ctxt.Diag, because asmout case 27 has the + // same check. + shift = 7 + } + p.From.Type = obj.TYPE_REG + p.From.Reg = int16(REG_LSL + r + (shift&7)<<5) + p.From.Offset = 0 + } } }