]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/arm: support BFX/BFXU instructions
authorBen Shi <powerman1st@163.com>
Wed, 16 Aug 2017 07:05:34 +0000 (07:05 +0000)
committerCherry Zhang <cherryyz@google.com>
Mon, 21 Aug 2017 16:29:59 +0000 (16:29 +0000)
BFX extracts given bits from the source register, sign extends them
to 32-bit, and writes to destination register. BFXU does the similar
operation with zero extention.

They were introduced in ARMv6T2.

Change-Id: I6822ebf663497a87a662d3645eddd7c611de2b1e
Reviewed-on: https://go-review.googlesource.com/56071
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/asm/internal/arch/arm.go
src/cmd/asm/internal/asm/asm.go
src/cmd/asm/internal/asm/testdata/arm.s
src/cmd/asm/internal/asm/testdata/armerror.s
src/cmd/internal/obj/arm/a.out.go
src/cmd/internal/obj/arm/anames.go
src/cmd/internal/obj/arm/asm5.go

index 40443d5ecafa0636be75ad301c750e02bb83d841..4ee494a74ca4e499a388ae2e5241aa66988548b8 100644 (file)
@@ -122,6 +122,15 @@ func IsARMMRC(op obj.As) bool {
        return false
 }
 
+// IsARMBFX reports whether the op is arm.BFX or arm.BFXU
+func IsARMBFX(op obj.As) bool {
+       switch op {
+       case arm.ABFX, arm.ABFXU:
+               return true
+       }
+       return false
+}
+
 // IsARMFloatCmp reports whether the op is a floating comparison instruction.
 func IsARMFloatCmp(op obj.As) bool {
        switch op {
index df23856c474ea89a0bb9e5321584603d459f6fea..7e9e59daf45d340e531681895e3221eb92a8226c 100644 (file)
@@ -564,6 +564,13 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
                                prog.To = a[2]
                                break
                        }
+                       if arch.IsARMBFX(op) {
+                               // a[0] and a[1] must be constants, a[2] must be a register
+                               prog.From = a[0]
+                               prog.From3 = newAddr(a[1])
+                               prog.To = a[2]
+                               break
+                       }
                        // Otherwise the 2nd operand (a[1]) must be a register.
                        prog.From = a[0]
                        prog.Reg = p.getRegister(prog, op, &a[1])
@@ -635,18 +642,28 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
                        return
                }
        case 4:
-               if p.arch.Family == sys.ARM && arch.IsARMMULA(op) {
-                       // All must be registers.
-                       p.getRegister(prog, op, &a[0])
-                       r1 := p.getRegister(prog, op, &a[1])
-                       r2 := p.getRegister(prog, op, &a[2])
-                       p.getRegister(prog, op, &a[3])
-                       prog.From = a[0]
-                       prog.To = a[3]
-                       prog.To.Type = obj.TYPE_REGREG2
-                       prog.To.Offset = int64(r2)
-                       prog.Reg = r1
-                       break
+               if p.arch.Family == sys.ARM {
+                       if arch.IsARMBFX(op) {
+                               // a[0] and a[1] must be constants, a[2] and a[3] must be registers
+                               prog.From = a[0]
+                               prog.From3 = newAddr(a[1])
+                               prog.Reg = p.getRegister(prog, op, &a[2])
+                               prog.To = a[3]
+                               break
+                       }
+                       if arch.IsARMMULA(op) {
+                               // All must be registers.
+                               p.getRegister(prog, op, &a[0])
+                               r1 := p.getRegister(prog, op, &a[1])
+                               r2 := p.getRegister(prog, op, &a[2])
+                               p.getRegister(prog, op, &a[3])
+                               prog.From = a[0]
+                               prog.To = a[3]
+                               prog.To.Type = obj.TYPE_REGREG2
+                               prog.To.Offset = int64(r2)
+                               prog.Reg = r1
+                               break
+                       }
                }
                if p.arch.Family == sys.AMD64 {
                        // 4 operand instruction have form  ymm1, ymm2, ymm3/m256, imm8
index cd1d11f518d04fc0601b052ad1e9204ce8db9c83..662ab180d778c26b502bb02969607b9857cafc90 100644 (file)
@@ -1007,6 +1007,12 @@ jmp_label_3:
        SWI     $65535         // ffff00ef
        SWI                    // 000000ef
 
+// BFX/BFXU
+       BFX     $16, $8, R1, R2 // BFX $16, R1, $8, R2   // 5124afe7
+       BFX     $29, $2, R8                              // 5881bce7
+       BFXU    $16, $8, R1, R2 // BFXU $16, R1, $8, R2  // 5124efe7
+       BFXU    $29, $2, R8                              // 5881fce7
+
 // synthetic arithmatic
        ADD     $0xffffffaa, R2, R3 // ADD $4294967210, R2, R3   // 55b0e0e30b3082e0
        ADD     $0xffffff55, R5     // ADD $4294967125, R5       // aab0e0e30b5085e0
index 2959a2f47bc6d2771e805d9aff0a26637c3b7eaf..a0bb13ed8bbdae2aea6fa97a95106d7393bad563 100644 (file)
@@ -124,5 +124,12 @@ TEXT errors(SB),$0
        MOVFW   CPSR, R2           // ERROR "illegal combination"
        MOVDW   R1, CPSR           // ERROR "illegal combination"
        MOVFW   R1, CPSR           // ERROR "illegal combination"
+       BFX     $12, $41, R2, R3   // ERROR "wrong width or LSB"
+       BFX     $12, $-2, R2       // ERROR "wrong width or LSB"
+       BFXU    $40, $4, R2, R3    // ERROR "wrong width or LSB"
+       BFXU    $-40, $4, R2       // ERROR "wrong width or LSB"
+       BFX     $-2, $4, R2, R3    // ERROR "wrong width or LSB"
+       BFXU    $4, R2, R5, R2     // ERROR "missing or wrong LSB"
+       BFXU    $4, R2, R5         // ERROR "missing or wrong LSB"
 
        END
index 6ea7d4be3b88b962f5a20f0cb43ddad6daf0ae9c..462cbca433329a3f55f8aac07465c686ba9146f5 100644 (file)
@@ -294,6 +294,9 @@ const (
        AREVSH
        ARBIT
 
+       ABFX
+       ABFXU
+
        AMULWT
        AMULWB
        AMULBB
index 63cc5da393a9d356468ce2b0baaedb10e78198cb..edb2c5a21e149c6de6420a943d6a6a9f02f6be4a 100644 (file)
@@ -107,6 +107,8 @@ var Anames = []string{
        "REV16",
        "REVSH",
        "RBIT",
+       "BFX",
+       "BFXU",
        "MULWT",
        "MULWB",
        "MULBB",
index 6188414f933f6f78054d6da12cf7e61b1b30d55b..3be98256980267d38053b7aaea882527fe9b7217 100644 (file)
@@ -180,6 +180,8 @@ var optab = []Optab{
        {ADIVHW, C_REG, C_REG, C_REG, 105, 4, 0, 0, 0},
        {ADIVHW, C_REG, C_NONE, C_REG, 105, 4, 0, 0, 0},
        {AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0, 0, 0},
+       {ABFX, C_LCON, C_REG, C_REG, 18, 4, 0, 0, 0},  // width in From, LSB in From3
+       {ABFX, C_LCON, C_NONE, C_REG, 18, 4, 0, 0, 0}, // width in From, LSB in From3
        {AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
        {AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
        {AMOVB, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
@@ -1691,6 +1693,9 @@ func buildop(ctxt *obj.Link) {
                        opset(AMMULA, r0)
                        opset(AMMULS, r0)
 
+               case ABFX:
+                       opset(ABFXU, r0)
+
                case ACLZ:
                        opset(AREV, r0)
                        opset(AREV16, r0)
@@ -2038,6 +2043,24 @@ func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
                r := int(p.Reg)
                o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16 | (uint32(rt2)&15)<<12
 
+       case 18: /* BFX/BFXU */
+               o1 = c.oprrr(p, p.As, int(p.Scond))
+               rt := int(p.To.Reg)
+               r := int(p.Reg)
+               if r == 0 {
+                       r = rt
+               }
+               if p.From3 == nil || p.From3.Type != obj.TYPE_CONST {
+                       c.ctxt.Diag("%v: missing or wrong LSB", p)
+                       break
+               }
+               lsb := p.From3.Offset
+               width := p.From.Offset
+               if lsb < 0 || lsb > 31 || width <= 0 || (lsb+width) > 31 {
+                       c.ctxt.Diag("%v: wrong width or LSB", p)
+               }
+               o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(width-1)<<16
+
        case 20: /* mov/movb/movbu R,O(R) */
                c.aclass(&p.To)
 
@@ -2911,6 +2934,12 @@ func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 {
        case -ACMP: // cmp imm
                return o | 0x3<<24 | 0x5<<20
 
+       case ABFX:
+               return o | 0x3d<<21 | 0x5<<4
+
+       case ABFXU:
+               return o | 0x3f<<21 | 0x5<<4
+
                // CLZ doesn't support .nil
        case ACLZ:
                return o&(0xf<<28) | 0x16f<<16 | 0xf1<<4