aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/asm
diff options
context:
space:
mode:
authorBen Shi <powerman1st@163.com>2017-08-16 07:05:34 +0000
committerCherry Zhang <cherryyz@google.com>2017-08-21 16:29:59 +0000
commit9bf521b2b467f00f21752cafd97cadabbc2e8879 (patch)
treef4239b9ea4015ac199f46c20c73ecd474c9e7cf9 /src/cmd/asm
parent07ec4385f16ad5d10933f4540624aba8b48b1891 (diff)
downloadgo-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.go9
-rw-r--r--src/cmd/asm/internal/asm/asm.go41
-rw-r--r--src/cmd/asm/internal/asm/testdata/arm.s6
-rw-r--r--src/cmd/asm/internal/asm/testdata/armerror.s7
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