return false
}
-// IsARMBFX reports whether the op is arm.BFX or arm.BFXU
+// IsARMBFX reports whether the op (as defined by an arm.A* constant) is one the
+// BFX-like instructions which are in the form of "op $width, $LSB, (Reg,) Reg".
func IsARMBFX(op obj.As) bool {
switch op {
- case arm.ABFX, arm.ABFXU:
+ case arm.ABFX, arm.ABFXU, arm.ABFC, arm.ABFI:
return true
}
return false
SWI $65535 // ffff00ef
SWI // 000000ef
-// BFX/BFXU
+// BFX/BFXU/BFC/BFI
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
+ BFC $29, $2, R8 // 1f81dee7
+ BFI $29, $2, R8 // 1881dee7
+ BFI $16, $8, R1, R2 // BFI $16, R1, $8, R2 // 1124d7e7
// synthetic arithmatic
ADD $0xffffffaa, R2, R3 // ADD $4294967210, R2, R3 // 55b0e0e30b3082e0
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"
+ BFC $12, $8, R2, R3 // ERROR "illegal combination"
MOVB R0>>8, R2 // ERROR "illegal shift"
MOVH R0<<16, R2 // ERROR "illegal shift"
MOVBS R0->8, R2 // ERROR "illegal shift"
ABFX
ABFXU
+ ABFC
+ ABFI
AMULWT
AMULWB
"XTAHU",
"BFX",
"BFXU",
+ "BFC",
+ "BFI",
"MULWT",
"MULWB",
"MULBB",
param int16
flag int8
pcrelsiz uint8
- scond uint8 // optional flags accepted by the instruction
+ scond uint8 // optional flags accepted by the instruction
}
type Opcross [32][2][32]uint8
case ABFX:
opset(ABFXU, r0)
+ opset(ABFC, r0)
+ opset(ABFI, r0)
case ACLZ:
opset(AREV, 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 */
+ case 18: /* BFX/BFXU/BFC/BFI */
o1 = c.oprrr(p, p.As, int(p.Scond))
rt := int(p.To.Reg)
r := int(p.Reg)
if r == 0 {
r = rt
+ } else if p.As == ABFC { // only "BFC $width, $lsb, Reg" is accepted, p.Reg must be 0
+ c.ctxt.Diag("illegal combination: %v", p)
}
if p.GetFrom3() == nil || p.GetFrom3().Type != obj.TYPE_CONST {
c.ctxt.Diag("%v: missing or wrong LSB", p)
}
lsb := p.GetFrom3().Offset
width := p.From.Offset
- if lsb < 0 || lsb > 31 || width <= 0 || (lsb+width) > 31 {
+ if lsb < 0 || lsb > 31 || width <= 0 || (lsb+width) > 32 {
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
+ switch p.As {
+ case ABFX, ABFXU: // (width-1) is encoded
+ o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(width-1)<<16
+ case ABFC, ABFI: // MSB is encoded
+ o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(lsb+width-1)<<16
+ default:
+ c.ctxt.Diag("illegal combination: %v", p)
+ }
case 20: /* mov/movb/movbu R,O(R) */
c.aclass(&p.To)
case ABFXU:
return o | 0x3f<<21 | 0x5<<4
+ case ABFC:
+ return o | 0x3e<<21 | 0x1f
+
+ case ABFI:
+ return o | 0x3e<<21 | 0x1<<4
+
case AXTAB:
return o | 0x6a<<20 | 0x7<<4