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 {
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])
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
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
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
AREVSH
ARBIT
+ ABFX
+ ABFXU
+
AMULWT
AMULWB
AMULBB
"REV16",
"REVSH",
"RBIT",
+ "BFX",
+ "BFXU",
"MULWT",
"MULWB",
"MULBB",
{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},
opset(AMMULA, r0)
opset(AMMULS, r0)
+ case ABFX:
+ opset(ABFXU, r0)
+
case ACLZ:
opset(AREV, r0)
opset(AREV16, r0)
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)
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