REVSH R1, R2 // b12fffe6
RBIT R1, R2 // 312fffe6
+// XTAB/XTAH/XTABU/XTAHU
+ XTAB R2@>0, R8 // 7280a8e6
+ XTAB R2@>8, R8 // 7284a8e6
+ XTAB R2@>16, R8 // 7288a8e6
+ XTAB R2@>24, R8 // 728ca8e6
+ XTAH R3@>0, R9 // 7390b9e6
+ XTAH R3@>8, R9 // 7394b9e6
+ XTAH R3@>16, R9 // 7398b9e6
+ XTAH R3@>24, R9 // 739cb9e6
+ XTABU R4@>0, R7 // 7470e7e6
+ XTABU R4@>8, R7 // 7474e7e6
+ XTABU R4@>16, R7 // 7478e7e6
+ XTABU R4@>24, R7 // 747ce7e6
+ XTAHU R5@>0, R1 // 7510f1e6
+ XTAHU R5@>8, R1 // 7514f1e6
+ XTAHU R5@>16, R1 // 7518f1e6
+ XTAHU R5@>24, R1 // 751cf1e6
+ XTAB R2@>0, R4, R8 // 7280a4e6
+ XTAB R2@>8, R4, R8 // 7284a4e6
+ XTAB R2@>16, R4, R8 // 7288a4e6
+ XTAB R2@>24, R4, R8 // 728ca4e6
+ XTAH R3@>0, R4, R9 // 7390b4e6
+ XTAH R3@>8, R4, R9 // 7394b4e6
+ XTAH R3@>16, R4, R9 // 7398b4e6
+ XTAH R3@>24, R4, R9 // 739cb4e6
+ XTABU R4@>0, R0, R7 // 7470e0e6
+ XTABU R4@>8, R0, R7 // 7474e0e6
+ XTABU R4@>16, R0, R7 // 7478e0e6
+ XTABU R4@>24, R0, R7 // 747ce0e6
+ XTAHU R5@>0, R9, R1 // 7510f9e6
+ XTAHU R5@>8, R9, R1 // 7514f9e6
+ XTAHU R5@>16, R9, R1 // 7518f9e6
+ XTAHU R5@>24, R9, R1 // 751cf9e6
+
// DIVHW R0, R1, R2: R1 / R0 -> R2
DIVHW R0, R1, R2 // 11f012e7
DIVUHW R0, R1, R2 // 11f032e7
// MOVW
MOVW R3, R4 // 0340a0e1
MOVW R9, R2 // 0920a0e1
+ MOVW R5>>1, R2 // a520a0e1
+ MOVW R5<<1, R2 // 8520a0e1
+ MOVW R5->1, R2 // c520a0e1
+ MOVW R5@>1, R2 // e520a0e1
MOVW $0xff, R9 // MOVW $255, R9 // ff90a0e3
MOVW $0xff000000, R9 // MOVW $4278190080, R9 // ff94a0e3
MOVW $0xff(R0), R1 // MOVW $255(R0), R1 // ff1080e2
MOVB.U R0<<0(R1), R2 // d02011e1
MOVB.W R0<<0(R1), R2 // d020b1e1
MOVB.P R0<<0(R1), R2 // d02091e0
+ MOVBS R2@>0, R8 // 7280afe6
+ MOVBS R2@>8, R8 // 7284afe6
+ MOVBS R2@>16, R8 // 7288afe6
+ MOVBS R2@>24, R8 // 728cafe6
+ MOVB R2@>0, R8 // 7280afe6
+ MOVB R2@>8, R8 // 7284afe6
+ MOVB R2@>16, R8 // 7288afe6
+ MOVB R2@>24, R8 // 728cafe6
+ MOVBU R4@>0, R7 // 7470efe6
+ MOVBU R4@>8, R7 // 7474efe6
+ MOVBU R4@>16, R7 // 7478efe6
+ MOVBU R4@>24, R7 // 747cefe6
// MOVH
MOVH R3, R4 // 0340a0e1
MOVHU.U R2, R5<<0(R1) // b52001e1
MOVHU.W R2, R5<<0(R1) // b520a1e1
MOVHU.P R2, R5<<0(R1) // b52081e0
+ MOVHS R3@>0, R9 // 7390bfe6
+ MOVHS R3@>8, R9 // 7394bfe6
+ MOVHS R3@>16, R9 // 7398bfe6
+ MOVHS R3@>24, R9 // 739cbfe6
+ MOVH R3@>0, R9 // 7390bfe6
+ MOVH R3@>8, R9 // 7394bfe6
+ MOVH R3@>16, R9 // 7398bfe6
+ MOVH R3@>24, R9 // 739cbfe6
+ MOVHU R5@>0, R1 // 7510ffe6
+ MOVHU R5@>8, R1 // 7514ffe6
+ MOVHU R5@>16, R1 // 7518ffe6
+ MOVHU R5@>24, R1 // 751cffe6
//
// END
{AMOVW, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
{AMOVBU, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
{AMOVBU, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
+ {AXTAB, C_SHIFT, C_REG, C_REG, 22, 4, 0, 0, 0},
+ {AXTAB, C_SHIFT, C_NONE, C_REG, 22, 4, 0, 0, 0},
+ {AMOVW, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
+ {AMOVB, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
+ {AMOVBS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
+ {AMOVBU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
+ {AMOVH, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
+ {AMOVHS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
+ {AMOVHU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0},
{AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
{AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
{AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
{ANEGF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0},
{AMOVW, C_REG, C_NONE, C_FCR, 56, 4, 0, 0, 0},
{AMOVW, C_FCR, C_NONE, C_REG, 57, 4, 0, 0, 0},
- {AMOVW, C_SHIFT, C_NONE, C_REG, 59, 4, 0, 0, 0},
- {AMOVBU, C_SHIFT, C_NONE, C_REG, 59, 4, 0, 0, 0},
- {AMOVB, C_SHIFT, C_NONE, C_REG, 60, 4, 0, 0, 0},
- {AMOVBS, C_SHIFT, C_NONE, C_REG, 60, 4, 0, 0, 0},
- {AMOVH, C_SHIFT, C_NONE, C_REG, 60, 4, 0, 0, 0},
- {AMOVHS, C_SHIFT, C_NONE, C_REG, 60, 4, 0, 0, 0},
- {AMOVHU, C_SHIFT, C_NONE, C_REG, 60, 4, 0, 0, 0},
- {AMOVW, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
- {AMOVB, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
- {AMOVBS, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
- {AMOVBU, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
- {AMOVH, C_REG, C_NONE, C_SHIFT, 62, 4, 0, 0, 0},
- {AMOVHS, C_REG, C_NONE, C_SHIFT, 62, 4, 0, 0, 0},
- {AMOVHU, C_REG, C_NONE, C_SHIFT, 62, 4, 0, 0, 0},
+ {AMOVW, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0},
+ {AMOVBU, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0},
+ {AMOVB, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0},
+ {AMOVBS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0},
+ {AMOVH, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0},
+ {AMOVHS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0},
+ {AMOVHU, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0},
+ {AMOVW, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0},
+ {AMOVB, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0},
+ {AMOVBS, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0},
+ {AMOVBU, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0},
+ {AMOVH, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0},
+ {AMOVHS, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0},
+ {AMOVHU, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0},
{AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
{AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
{AMOVHS, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
return C_REGLIST
case obj.TYPE_SHIFT:
- return C_SHIFT
+ if a.Reg == 0 {
+ // register shift R>>i
+ return C_SHIFT
+ } else {
+ // memory address with shifted offset R>>i(R)
+ return C_SHIFTADDR
+ }
case obj.TYPE_MEM:
switch a.Name {
// check illegal base register
switch a1 {
- case C_SHIFT:
- if p.From.Reg == 0 { // no base register
- break
- }
- fallthrough
- case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG:
+ case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR:
if p.From.Reg < REG_R0 || REG_R15 < p.From.Reg {
c.ctxt.Diag("illegal base register: %v", p)
}
default:
}
switch a3 {
- case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFT:
+ case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR:
if p.To.Reg < REG_R0 || REG_R15 < p.To.Reg {
c.ctxt.Diag("illegal base register: %v", p)
}
opset(AREVSH, r0)
opset(ARBIT, r0)
+ case AXTAB:
+ opset(AXTAH, r0)
+ opset(AXTABU, r0)
+ opset(AXTAHU, r0)
+
case ALDREX,
ASTREX,
ALDREXD,
o1 |= 1 << 22
}
+ case 22: /* XTAB R@>i, [R], R */
+ o1 = c.oprrr(p, p.As, int(p.Scond))
+ switch p.From.Offset &^ 0xf {
+ // only 0/8/16/24 bits rotation is accepted
+ case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7:
+ o1 |= uint32(p.From.Offset) & 0xc0f
+ default:
+ c.ctxt.Diag("illegal shift: %v", p)
+ }
+ rt := p.To.Reg
+ r := p.Reg
+ if r == 0 {
+ r = rt
+ }
+ o1 |= (uint32(rt)&15)<<12 | (uint32(r)&15)<<16
+
+ case 23: /* MOVW/MOVB/MOVH R@>i, R */
+ switch p.As {
+ case AMOVW:
+ o1 = c.mov(p)
+ case AMOVBU, AMOVBS, AMOVB, AMOVHU, AMOVHS, AMOVH:
+ o1 = c.movxt(p)
+ default:
+ c.ctxt.Diag("illegal combination: %v", p)
+ }
+
case 30: /* mov/movb/movbu R,L(R) */
o1 = c.omvl(p, &p.To, REGTMP)
case 59: /* movw/bu R<<I(R),R -> ldr indexed */
if p.From.Reg == 0 {
- if p.As != AMOVW {
- c.ctxt.Diag("byte MOV from shifter operand")
- }
- o1 = c.mov(p)
+ c.ctxt.Diag("source operand is not a memory address: %v", p)
break
}
-
if p.From.Offset&(1<<4) != 0 {
c.ctxt.Diag("bad shift in LDR")
+ break
}
o1 = c.olrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
if p.As == AMOVBU {
case 60: /* movb R(R),R -> ldrsb indexed */
if p.From.Reg == 0 {
- c.ctxt.Diag("byte MOV from shifter operand")
- o1 = c.mov(p)
+ c.ctxt.Diag("source operand is not a memory address: %v", p)
break
}
-
if p.From.Offset&(^0xf) != 0 {
c.ctxt.Diag("bad shift: %v", p)
+ break
}
o1 = c.olhrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
switch p.As {
return
}
+func (c *ctxt5) movxt(p *obj.Prog) uint32 {
+ o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
+ switch p.As {
+ case AMOVB, AMOVBS:
+ o1 |= 0x6af<<16 | 0x7<<4
+ case AMOVH, AMOVHS:
+ o1 |= 0x6bf<<16 | 0x7<<4
+ case AMOVBU:
+ o1 |= 0x6ef<<16 | 0x7<<4
+ case AMOVHU:
+ o1 |= 0x6ff<<16 | 0x7<<4
+ default:
+ c.ctxt.Diag("illegal combination: %v", p)
+ }
+ switch p.From.Offset &^ 0xf {
+ // only 0/8/16/24 bits rotation is accepted
+ case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7:
+ o1 |= uint32(p.From.Offset) & 0xc0f
+ default:
+ c.ctxt.Diag("illegal shift: %v", p)
+ }
+ o1 |= (uint32(p.To.Reg) & 15) << 12
+ return o1
+}
+
func (c *ctxt5) mov(p *obj.Prog) uint32 {
c.aclass(&p.From)
o1 := c.oprrr(p, p.As, int(p.Scond))
case ABFXU:
return o | 0x3f<<21 | 0x5<<4
+ case AXTAB:
+ return o | 0x6a<<20 | 0x7<<4
+
+ case AXTAH:
+ return o | 0x6b<<20 | 0x7<<4
+
+ case AXTABU:
+ return o | 0x6e<<20 | 0x7<<4
+
+ case AXTAHU:
+ return o | 0x6f<<20 | 0x7<<4
+
// CLZ doesn't support .nil
case ACLZ:
return o&(0xf<<28) | 0x16f<<16 | 0xf1<<4