diff options
| author | Ben Shi <powerman1st@163.com> | 2017-08-16 07:05:34 +0000 |
|---|---|---|
| committer | Cherry Zhang <cherryyz@google.com> | 2017-08-21 16:29:59 +0000 |
| commit | 9bf521b2b467f00f21752cafd97cadabbc2e8879 (patch) | |
| tree | f4239b9ea4015ac199f46c20c73ecd474c9e7cf9 /src/cmd/asm | |
| parent | 07ec4385f16ad5d10933f4540624aba8b48b1891 (diff) | |
| download | go-9bf521b2b467f00f21752cafd97cadabbc2e8879.tar.xz | |
cmd/internal/obj/arm: support BFX/BFXU instructions
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>
Diffstat (limited to 'src/cmd/asm')
| -rw-r--r-- | src/cmd/asm/internal/arch/arm.go | 9 | ||||
| -rw-r--r-- | src/cmd/asm/internal/asm/asm.go | 41 | ||||
| -rw-r--r-- | src/cmd/asm/internal/asm/testdata/arm.s | 6 | ||||
| -rw-r--r-- | src/cmd/asm/internal/asm/testdata/armerror.s | 7 |
4 files changed, 51 insertions, 12 deletions
diff --git a/src/cmd/asm/internal/arch/arm.go b/src/cmd/asm/internal/arch/arm.go index 40443d5eca..4ee494a74c 100644 --- a/src/cmd/asm/internal/arch/arm.go +++ b/src/cmd/asm/internal/arch/arm.go @@ -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 { diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go index df23856c47..7e9e59daf4 100644 --- a/src/cmd/asm/internal/asm/asm.go +++ b/src/cmd/asm/internal/asm/asm.go @@ -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 diff --git a/src/cmd/asm/internal/asm/testdata/arm.s b/src/cmd/asm/internal/asm/testdata/arm.s index cd1d11f518..662ab180d7 100644 --- a/src/cmd/asm/internal/asm/testdata/arm.s +++ b/src/cmd/asm/internal/asm/testdata/arm.s @@ -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 diff --git a/src/cmd/asm/internal/asm/testdata/armerror.s b/src/cmd/asm/internal/asm/testdata/armerror.s index 2959a2f47b..a0bb13ed8b 100644 --- a/src/cmd/asm/internal/asm/testdata/armerror.s +++ b/src/cmd/asm/internal/asm/testdata/armerror.s @@ -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 |
