diff options
-rw-r--r-- | lib/Target/ARM/ARMInstrFormats.td | 29 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 116 | ||||
-rw-r--r-- | test/MC/ARM/simple-encoding.ll | 57 |
3 files changed, 129 insertions, 73 deletions
diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 0194e2d..a0f9a4b 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -988,11 +988,36 @@ class AExtI<bits<8> opcod, dag oops, dag iops, InstrItinClass itin, } // Misc Arithmetic instructions. -class AMiscA1I<bits<8> opcod, dag oops, dag iops, InstrItinClass itin, - string opc, string asm, list<dag> pattern> +class AMiscA1I<bits<8> opcod, bits<4> opc7_4, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list<dag> pattern> + : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, ArithMiscFrm, itin, + opc, asm, "", pattern> { + bits<4> Rd; + bits<4> Rm; + let Inst{27-20} = opcod; + let Inst{19-16} = 0b1111; + let Inst{15-12} = Rd; + let Inst{11-8} = 0b1111; + let Inst{7-4} = opc7_4; + let Inst{3-0} = Rm; +} + +// PKH instructions +class APKHI<bits<8> opcod, bit tb, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list<dag> pattern> : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, ArithMiscFrm, itin, opc, asm, "", pattern> { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + bits<8> sh; let Inst{27-20} = opcod; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-7} = sh{7-3}; + let Inst{6} = tb; + let Inst{5-4} = 0b01; + let Inst{3-0} = Rm; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index a99babb..c912740 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -2557,55 +2557,35 @@ defm SMUS : AI_sdml<1, "smus">; // Misc. Arithmetic Instructions. // -def CLZ : AMiscA1I<0b000010110, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, - "clz", "\t$dst, $src", - [(set GPR:$dst, (ctlz GPR:$src))]>, Requires<[IsARM, HasV5T]> { - let Inst{7-4} = 0b0001; - let Inst{11-8} = 0b1111; - let Inst{19-16} = 0b1111; -} - -def RBIT : AMiscA1I<0b01101111, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, - "rbit", "\t$dst, $src", - [(set GPR:$dst, (ARMrbit GPR:$src))]>, - Requires<[IsARM, HasV6T2]> { - let Inst{7-4} = 0b0011; - let Inst{11-8} = 0b1111; - let Inst{19-16} = 0b1111; -} - -def REV : AMiscA1I<0b01101011, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, - "rev", "\t$dst, $src", - [(set GPR:$dst, (bswap GPR:$src))]>, Requires<[IsARM, HasV6]> { - let Inst{7-4} = 0b0011; - let Inst{11-8} = 0b1111; - let Inst{19-16} = 0b1111; -} - -def REV16 : AMiscA1I<0b01101011, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, - "rev16", "\t$dst, $src", - [(set GPR:$dst, - (or (and (srl GPR:$src, (i32 8)), 0xFF), - (or (and (shl GPR:$src, (i32 8)), 0xFF00), - (or (and (srl GPR:$src, (i32 8)), 0xFF0000), - (and (shl GPR:$src, (i32 8)), 0xFF000000)))))]>, - Requires<[IsARM, HasV6]> { - let Inst{7-4} = 0b1011; - let Inst{11-8} = 0b1111; - let Inst{19-16} = 0b1111; -} - -def REVSH : AMiscA1I<0b01101111, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, - "revsh", "\t$dst, $src", - [(set GPR:$dst, +def CLZ : AMiscA1I<0b000010110, 0b0001, (outs GPR:$Rd), (ins GPR:$Rm), + IIC_iUNAr, "clz", "\t$Rd, $Rm", + [(set GPR:$Rd, (ctlz GPR:$Rm))]>, Requires<[IsARM, HasV5T]>; + +def RBIT : AMiscA1I<0b01101111, 0b0011, (outs GPR:$Rd), (ins GPR:$Rm), + IIC_iUNAr, "rbit", "\t$Rd, $Rm", + [(set GPR:$Rd, (ARMrbit GPR:$Rm))]>, + Requires<[IsARM, HasV6T2]>; + +def REV : AMiscA1I<0b01101011, 0b0011, (outs GPR:$Rd), (ins GPR:$Rm), + IIC_iUNAr, "rev", "\t$Rd, $Rm", + [(set GPR:$Rd, (bswap GPR:$Rm))]>, Requires<[IsARM, HasV6]>; + +def REV16 : AMiscA1I<0b01101011, 0b1011, (outs GPR:$Rd), (ins GPR:$Rm), + IIC_iUNAr, "rev16", "\t$Rd, $Rm", + [(set GPR:$Rd, + (or (and (srl GPR:$Rm, (i32 8)), 0xFF), + (or (and (shl GPR:$Rm, (i32 8)), 0xFF00), + (or (and (srl GPR:$Rm, (i32 8)), 0xFF0000), + (and (shl GPR:$Rm, (i32 8)), 0xFF000000)))))]>, + Requires<[IsARM, HasV6]>; + +def REVSH : AMiscA1I<0b01101111, 0b1011, (outs GPR:$Rd), (ins GPR:$Rm), + IIC_iUNAr, "revsh", "\t$Rd, $Rm", + [(set GPR:$Rd, (sext_inreg - (or (srl (and GPR:$src, 0xFF00), (i32 8)), - (shl GPR:$src, (i32 8))), i16))]>, - Requires<[IsARM, HasV6]> { - let Inst{7-4} = 0b1011; - let Inst{11-8} = 0b1111; - let Inst{19-16} = 0b1111; -} + (or (srl (and GPR:$Rm, 0xFF00), (i32 8)), + (shl GPR:$Rm, (i32 8))), i16))]>, + Requires<[IsARM, HasV6]>; def lsl_shift_imm : SDNodeXForm<imm, [{ unsigned Sh = ARM_AM::getSORegOpc(ARM_AM::lsl, N->getZExtValue()); @@ -2616,21 +2596,19 @@ def lsl_amt : PatLeaf<(i32 imm), [{ return (N->getZExtValue() < 32); }], lsl_shift_imm>; -def PKHBT : AMiscA1I<0b01101000, (outs GPR:$dst), - (ins GPR:$src1, GPR:$src2, shift_imm:$sh), - IIC_iALUsi, "pkhbt", "\t$dst, $src1, $src2$sh", - [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF), - (and (shl GPR:$src2, lsl_amt:$sh), - 0xFFFF0000)))]>, - Requires<[IsARM, HasV6]> { - let Inst{6-4} = 0b001; -} +def PKHBT : APKHI<0b01101000, 0, (outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, shift_imm:$sh), + IIC_iALUsi, "pkhbt", "\t$Rd, $Rn, $Rm$sh", + [(set GPR:$Rd, (or (and GPR:$Rn, 0xFFFF), + (and (shl GPR:$Rm, lsl_amt:$sh), + 0xFFFF0000)))]>, + Requires<[IsARM, HasV6]>; // Alternate cases for PKHBT where identities eliminate some nodes. -def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF), (and GPR:$src2, 0xFFFF0000)), - (PKHBT GPR:$src1, GPR:$src2, 0)>; -def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF), (shl GPR:$src2, imm16_31:$sh)), - (PKHBT GPR:$src1, GPR:$src2, (lsl_shift_imm imm16_31:$sh))>; +def : ARMV6Pat<(or (and GPR:$Rn, 0xFFFF), (and GPR:$Rm, 0xFFFF0000)), + (PKHBT GPR:$Rn, GPR:$Rm, 0)>; +def : ARMV6Pat<(or (and GPR:$Rn, 0xFFFF), (shl GPR:$Rm, imm16_31:$sh)), + (PKHBT GPR:$Rn, GPR:$Rm, (lsl_shift_imm imm16_31:$sh))>; def asr_shift_imm : SDNodeXForm<imm, [{ unsigned Sh = ARM_AM::getSORegOpc(ARM_AM::asr, N->getZExtValue()); @@ -2643,15 +2621,13 @@ def asr_amt : PatLeaf<(i32 imm), [{ // Note: Shifts of 1-15 bits will be transformed to srl instead of sra and // will match the pattern below. -def PKHTB : AMiscA1I<0b01101000, (outs GPR:$dst), - (ins GPR:$src1, GPR:$src2, shift_imm:$sh), - IIC_iBITsi, "pkhtb", "\t$dst, $src1, $src2$sh", - [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000), - (and (sra GPR:$src2, asr_amt:$sh), - 0xFFFF)))]>, - Requires<[IsARM, HasV6]> { - let Inst{6-4} = 0b101; -} +def PKHTB : APKHI<0b01101000, 1, (outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, shift_imm:$sh), + IIC_iBITsi, "pkhtb", "\t$Rd, $Rn, $Rm$sh", + [(set GPR:$Rd, (or (and GPR:$Rn, 0xFFFF0000), + (and (sra GPR:$Rm, asr_amt:$sh), + 0xFFFF)))]>, + Requires<[IsARM, HasV6]>; // Alternate cases for PKHTB where identities eliminate some nodes. Note that // a shift amount of 0 is *not legal* here, it is PKHBT instead. diff --git a/test/MC/ARM/simple-encoding.ll b/test/MC/ARM/simple-encoding.ll index 8cf8577..5bdad00 100644 --- a/test/MC/ARM/simple-encoding.ll +++ b/test/MC/ARM/simple-encoding.ll @@ -7,6 +7,9 @@ ; compiler never generates, so we need the integrated assembler to be ; able to test those at all. +declare void @llvm.trap() nounwind +declare i32 @llvm.ctlz.i32(i32) + define i32 @foo(i32 %a, i32 %b) { entry: ; CHECK: foo @@ -182,4 +185,56 @@ define i32 @f18(i32 %a, i16 %x, i32 %y) { ret i32 %tmp5 } -declare void @llvm.trap() nounwind +define i32 @f19(i32 %x) { +; CHECK: f19 +; CHECK: clz r0, r0 @ encoding: [0x10,0x0f,0x6f,0xe1] + %tmp.1 = call i32 @llvm.ctlz.i32( i32 %x ) + ret i32 %tmp.1 +} + +define i32 @f20(i32 %X) { +; CHECK: f20 +; CHECK: rev16 r0, r0 @ encoding: [0xb0,0x0f,0xbf,0xe6] + %tmp1 = lshr i32 %X, 8 + %X15 = bitcast i32 %X to i32 + %tmp4 = shl i32 %X15, 8 + %tmp2 = and i32 %tmp1, 16711680 + %tmp5 = and i32 %tmp4, -16777216 + %tmp9 = and i32 %tmp1, 255 + %tmp13 = and i32 %tmp4, 65280 + %tmp6 = or i32 %tmp5, %tmp2 + %tmp10 = or i32 %tmp6, %tmp13 + %tmp14 = or i32 %tmp10, %tmp9 + ret i32 %tmp14 +} + +define i32 @f21(i32 %X) { +; CHECK: f21 +; CHECK: revsh r0, r0 @ encoding: [0xb0,0x0f,0xff,0xe6] + %tmp1 = lshr i32 %X, 8 + %tmp1.upgrd.1 = trunc i32 %tmp1 to i16 + %tmp3 = trunc i32 %X to i16 + %tmp2 = and i16 %tmp1.upgrd.1, 255 + %tmp4 = shl i16 %tmp3, 8 + %tmp5 = or i16 %tmp2, %tmp4 + %tmp5.upgrd.2 = sext i16 %tmp5 to i32 + ret i32 %tmp5.upgrd.2 +} + +define i32 @f22(i32 %X, i32 %Y) { +; CHECK: f22 +; CHECK: pkhtb r0, r0, r1, asr #22 @ encoding: [0x51,0x0b,0x80,0xe6] + %tmp1 = and i32 %X, -65536 + %tmp3 = lshr i32 %Y, 22 + %tmp57 = or i32 %tmp3, %tmp1 + ret i32 %tmp57 +} + +define i32 @f23(i32 %X, i32 %Y) { +; CHECK: f23 +; CHECK: pkhbt r0, r0, r1, lsl #18 @ encoding: [0x11,0x09,0x80,0xe6] + %tmp19 = and i32 %X, 65535 + %tmp37 = shl i32 %Y, 18 + %tmp5 = or i32 %tmp37, %tmp19 + ret i32 %tmp5 +} |