From 44a0da4ff11a5447dcfe2b62ac46bca134736d81 Mon Sep 17 00:00:00 2001 From: eric fang Date: Tue, 20 Apr 2021 02:46:33 +0000 Subject: [PATCH] cmd/internal/obj/arm64: refactor the handling of shifted RSP Some arithmetic operation instructions such as ADD and SUB support two formats of left shift (<<) operation, namely shifted register format and extended register format. And the encoding, supported registers and shifted amount are both different. The assembly parser doesn't distinguish them and parses them into TYPE_SHIFT type, because the parser can't tell them apart and in most cases extended left-shift can be replaced by shifted left-shift. The only exception is when the second source register or the destination register is RSP. This CL converts this case into the extended format in the preprocess stage, which helps to simplify some of the logic of the new assembler implementation and also makes this situation look more reasonable. Change-Id: I2cd7d2d663b38a7ba77a9fef1092708b8cb9bc3d Reviewed-on: https://go-review.googlesource.com/c/go/+/311709 Trust: Eric Fang Run-TryBot: Eric Fang TryBot-Result: Gopher Robot Reviewed-by: Cherry Mui --- .../asm/internal/asm/testdata/arm64error.s | 4 +- src/cmd/internal/obj/arm64/asm7.go | 61 +++++-------------- src/cmd/internal/obj/arm64/obj7.go | 18 ++++++ 3 files changed, 35 insertions(+), 48 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s index 3d3de1d9b1..033c4cda6c 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 f4111f4f5c..5435b2248f 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 43f7b16d6e..ee5a6fa273 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 + } } } -- 2.48.1