]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/arm64: refactor the handling of shifted RSP
authoreric fang <eric.fang@arm.com>
Tue, 20 Apr 2021 02:46:33 +0000 (02:46 +0000)
committerEric Fang <eric.fang@arm.com>
Tue, 15 Mar 2022 01:00:36 +0000 (01:00 +0000)
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 <eric.fang@arm.com>
Run-TryBot: Eric Fang <eric.fang@arm.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
src/cmd/asm/internal/asm/testdata/arm64error.s
src/cmd/internal/obj/arm64/asm7.go
src/cmd/internal/obj/arm64/obj7.go

index 3d3de1d9b13770ba9efbd403359a7b0a1abac0d6..033c4cda6c8666f32b6c4cdf49b128ca856ddc32 100644 (file)
@@ -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"
index f4111f4f5cd3896aa9b0a469257d546cae4c880d..5435b2248fa37fcacb4b2cbb68802eec752fae57 100644 (file)
@@ -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<<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)&REG_EXT != 0 {
+               if (p.From.Reg-obj.RBaseARM64)&REG_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
@@ -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<<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
@@ -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.")
        }
index 43f7b16d6e2453c9f4325b88a4b00a9a62d64b71..ee5a6fa273ee226657abb184aa4176cfe6bd43b5 100644 (file)
@@ -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
+               }
        }
 }