mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-27 05:10:41 +00:00
--- Reverse-merging r98637 into '.':
U test/CodeGen/ARM/tls2.ll U test/CodeGen/ARM/arm-negative-stride.ll U test/CodeGen/ARM/2009-10-30.ll U test/CodeGen/ARM/globals.ll U test/CodeGen/ARM/str_pre-2.ll U test/CodeGen/ARM/ldrd.ll U test/CodeGen/ARM/2009-10-27-double-align.ll U test/CodeGen/Thumb2/thumb2-strb.ll U test/CodeGen/Thumb2/ldr-str-imm12.ll U test/CodeGen/Thumb2/thumb2-strh.ll U test/CodeGen/Thumb2/thumb2-ldr.ll U test/CodeGen/Thumb2/thumb2-str_pre.ll U test/CodeGen/Thumb2/thumb2-str.ll U test/CodeGen/Thumb2/thumb2-ldrh.ll U utils/TableGen/TableGen.cpp U utils/TableGen/DisassemblerEmitter.cpp D utils/TableGen/RISCDisassemblerEmitter.h D utils/TableGen/RISCDisassemblerEmitter.cpp U Makefile.rules U lib/Target/ARM/ARMInstrNEON.td U lib/Target/ARM/Makefile U lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp U lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp U lib/Target/ARM/AsmPrinter/ARMInstPrinter.h D lib/Target/ARM/Disassembler U lib/Target/ARM/ARMInstrFormats.td U lib/Target/ARM/ARMAddressingModes.h U lib/Target/ARM/Thumb2ITBlockPass.cpp llvm-svn: 98640
This commit is contained in:
parent
ff030064fb
commit
34aca030c5
@ -1614,11 +1614,6 @@ $(ObjDir)/%GenIntrinsics.inc.tmp : %.td $(ObjDir)/.dir
|
||||
$(Echo) "Building $(<F) intrinsics information with tblgen"
|
||||
$(Verb) $(TableGen) -gen-tgt-intrinsic -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(ObjDir)/ARMDisassemblerTables.inc.tmp : ARM.td $(ObjDir)/.dir
|
||||
$(Echo) "Building ARM disassembly tables with tblgen"
|
||||
$(Verb) $(TableGen) -gen-risc-disassembler -o $(call SYSPATH, $@) $<
|
||||
|
||||
|
||||
clean-local::
|
||||
-$(Verb) $(RM) -f $(INCFiles)
|
||||
|
||||
|
@ -35,10 +35,6 @@ namespace ARM_AM {
|
||||
add = '+', sub = '-'
|
||||
};
|
||||
|
||||
static inline const char *getAddrOpcStr(AddrOpc Op) {
|
||||
return Op == sub ? "-" : "";
|
||||
}
|
||||
|
||||
static inline const char *getShiftOpcStr(ShiftOpc Op) {
|
||||
switch (Op) {
|
||||
default: assert(0 && "Unknown shift opc!");
|
||||
@ -131,20 +127,6 @@ namespace ARM_AM {
|
||||
return (Imm >> 8) * 2;
|
||||
}
|
||||
|
||||
/// getSOImmValOneRotate - Try to handle Imm with an immediate shifter
|
||||
/// operand, computing the rotate amount to use. If this immediate value
|
||||
/// cannot be handled with a single shifter-op, return 0.
|
||||
static inline unsigned getSOImmValOneRotate(unsigned Imm) {
|
||||
// A5.2.4 Constants with multiple encodings
|
||||
// The lowest unsigned value of rotation wins!
|
||||
for (unsigned R = 1; R <= 15; ++R)
|
||||
if ((Imm & rotr32(~255U, 2*R)) == 0)
|
||||
return 2*R;
|
||||
|
||||
// Failed to find a suitable rotate amount.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getSOImmValRotate - Try to handle Imm with an immediate shifter operand,
|
||||
/// computing the rotate amount to use. If this immediate value cannot be
|
||||
/// handled with a single shifter-op, determine a good rotate amount that will
|
||||
@ -197,7 +179,7 @@ namespace ARM_AM {
|
||||
// of zero.
|
||||
if ((Arg & ~255U) == 0) return Arg;
|
||||
|
||||
unsigned RotAmt = getSOImmValOneRotate(Arg);
|
||||
unsigned RotAmt = getSOImmValRotate(Arg);
|
||||
|
||||
// If this cannot be handled with a single shifter_op, bail out.
|
||||
if (rotr32(~255U, RotAmt) & Arg)
|
||||
|
@ -1464,29 +1464,6 @@ class AVConv5I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops,
|
||||
// ARM NEON Instruction templates.
|
||||
//
|
||||
|
||||
// NSFormat specifies further details of a NEON instruction. This is used by
|
||||
// the disassembler to classify NEONFrm instructions for disassembly purpose.
|
||||
class NSFormat<bits<5> val> {
|
||||
bits<5> Value = val;
|
||||
}
|
||||
def NSFormatNone : NSFormat<0>;
|
||||
def VLDSTLaneFrm : NSFormat<1>;
|
||||
def VLDSTLaneDblFrm : NSFormat<2>;
|
||||
def VLDSTRQFrm : NSFormat<3>;
|
||||
def NVdImmFrm : NSFormat<4>;
|
||||
def NVdVmImmFrm : NSFormat<5>;
|
||||
def NVdVmImmVCVTFrm : NSFormat<6>;
|
||||
def NVdVmImmVDupLaneFrm : NSFormat<7>;
|
||||
def NVdVmImmVSHLLFrm : NSFormat<8>;
|
||||
def NVectorShuffleFrm : NSFormat<9>;
|
||||
def NVectorShiftFrm : NSFormat<10>;
|
||||
def NVectorShift2Frm : NSFormat<11>;
|
||||
def NVdVnVmImmFrm : NSFormat<12>;
|
||||
def NVdVnVmImmVectorShiftFrm : NSFormat<13>;
|
||||
def NVdVnVmImmVectorExtractFrm : NSFormat<14>;
|
||||
def NVdVnVmImmMulScalarFrm : NSFormat<15>;
|
||||
def VTBLFrm : NSFormat<16>;
|
||||
|
||||
class NeonI<dag oops, dag iops, AddrMode am, IndexMode im, InstrItinClass itin,
|
||||
string opc, string dt, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, Size4Bytes, im, NEONFrm, NeonDomain, cstr, itin> {
|
||||
@ -1497,8 +1474,6 @@ class NeonI<dag oops, dag iops, AddrMode am, IndexMode im, InstrItinClass itin,
|
||||
!strconcat("\t", asm));
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [HasNEON];
|
||||
NSFormat NSF = NSFormatNone; // For disassembly.
|
||||
bits<5> NSForm = NSFormatNone.Value; // For disassembly.
|
||||
}
|
||||
|
||||
// Same as NeonI except it does not have a "data type" specifier.
|
||||
@ -1510,8 +1485,6 @@ class NeonXI<dag oops, dag iops, AddrMode am, IndexMode im, InstrItinClass itin,
|
||||
let AsmString = !strconcat(!strconcat(opc, "${p}"), !strconcat("\t", asm));
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [HasNEON];
|
||||
NSFormat NSF = NSFormatNone; // For disassembly.
|
||||
bits<5> NSForm = NSFormatNone.Value; // For disassembly.
|
||||
}
|
||||
|
||||
class NI<dag oops, dag iops, InstrItinClass itin, string opc, string asm,
|
||||
@ -1524,8 +1497,6 @@ class NI4<dag oops, dag iops, InstrItinClass itin, string opc,
|
||||
string asm, list<dag> pattern>
|
||||
: NeonXI<oops, iops, AddrMode4, IndexModeNone, itin, opc, asm, "",
|
||||
pattern> {
|
||||
let NSF = VLDSTRQFrm; // For disassembly.
|
||||
let NSForm = VLDSTRQFrm.Value; // For disassembly.
|
||||
}
|
||||
|
||||
class NLdSt<bit op23, bits<2> op21_20, bits<4> op11_8, bits<4> op7_4,
|
||||
@ -1538,8 +1509,6 @@ class NLdSt<bit op23, bits<2> op21_20, bits<4> op11_8, bits<4> op7_4,
|
||||
let Inst{21-20} = op21_20;
|
||||
let Inst{11-8} = op11_8;
|
||||
let Inst{7-4} = op7_4;
|
||||
let NSF = VLDSTLaneFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneFrm.Value; // For disassembly.
|
||||
}
|
||||
|
||||
class NDataI<dag oops, dag iops, InstrItinClass itin,
|
||||
@ -1569,8 +1538,6 @@ class N1ModImm<bit op23, bits<3> op21_19, bits<4> op11_8, bit op7, bit op6,
|
||||
let Inst{6} = op6;
|
||||
let Inst{5} = op5;
|
||||
let Inst{4} = op4;
|
||||
let NSF = NVdImmFrm; // For disassembly.
|
||||
let NSForm = NVdImmFrm.Value; // For disassembly.
|
||||
}
|
||||
|
||||
// NEON 2 vector register format.
|
||||
@ -1586,8 +1553,6 @@ class N2V<bits<2> op24_23, bits<2> op21_20, bits<2> op19_18, bits<2> op17_16,
|
||||
let Inst{11-7} = op11_7;
|
||||
let Inst{6} = op6;
|
||||
let Inst{4} = op4;
|
||||
let NSF = NVdVmImmFrm; // For disassembly.
|
||||
let NSForm = NVdVmImmFrm.Value; // For disassembly.
|
||||
}
|
||||
|
||||
// Same as N2V except it doesn't have a datatype suffix.
|
||||
@ -1603,8 +1568,6 @@ class N2VX<bits<2> op24_23, bits<2> op21_20, bits<2> op19_18, bits<2> op17_16,
|
||||
let Inst{11-7} = op11_7;
|
||||
let Inst{6} = op6;
|
||||
let Inst{4} = op4;
|
||||
let NSF = NVdVmImmFrm; // For disassembly.
|
||||
let NSForm = NVdVmImmFrm.Value; // For disassembly.
|
||||
}
|
||||
|
||||
// NEON 2 vector register with immediate.
|
||||
@ -1618,8 +1581,6 @@ class N2VImm<bit op24, bit op23, bits<4> op11_8, bit op7, bit op6, bit op4,
|
||||
let Inst{7} = op7;
|
||||
let Inst{6} = op6;
|
||||
let Inst{4} = op4;
|
||||
let NSF = NVdVmImmFrm; // For disassembly.
|
||||
let NSForm = NVdVmImmFrm.Value; // For disassembly.
|
||||
}
|
||||
|
||||
// NEON 3 vector register format.
|
||||
@ -1633,8 +1594,6 @@ class N3V<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op6, bit op4,
|
||||
let Inst{11-8} = op11_8;
|
||||
let Inst{6} = op6;
|
||||
let Inst{4} = op4;
|
||||
let NSF = NVdVnVmImmFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmFrm.Value; // For disassembly.
|
||||
}
|
||||
|
||||
// Same as N3VX except it doesn't have a data type suffix.
|
||||
@ -1648,8 +1607,6 @@ class N3VX<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op6, bit op4
|
||||
let Inst{11-8} = op11_8;
|
||||
let Inst{6} = op6;
|
||||
let Inst{4} = op4;
|
||||
let NSF = NVdVnVmImmFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmFrm.Value; // For disassembly.
|
||||
}
|
||||
|
||||
// NEON VMOVs between scalar and core registers.
|
||||
|
@ -213,10 +213,7 @@ def VLD2q32 : VLD2Q<0b1000, "vld2", "32">;
|
||||
class VLD2Ddbl<bits<4> op7_4, string OpcodeStr, string Dt>
|
||||
: NLdSt<0,0b10,0b1001,op7_4, (outs DPR:$dst1, DPR:$dst2),
|
||||
(ins addrmode6:$addr), IIC_VLD2,
|
||||
OpcodeStr, Dt, "\\{$dst1, $dst2\\}, $addr", "", []> {
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
OpcodeStr, Dt, "\\{$dst1, $dst2\\}, $addr", "", []>;
|
||||
|
||||
def VLD2d8D : VLD2Ddbl<0b0000, "vld2", "8">;
|
||||
def VLD2d16D : VLD2Ddbl<0b0100, "vld2", "16">;
|
||||
@ -231,10 +228,7 @@ class VLD3WB<bits<4> op7_4, string OpcodeStr, string Dt>
|
||||
: NLdSt<0,0b10,0b0101,op7_4, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, GPR:$wb),
|
||||
(ins addrmode6:$addr), IIC_VLD3,
|
||||
OpcodeStr, Dt, "\\{$dst1, $dst2, $dst3\\}, $addr",
|
||||
"$addr.addr = $wb", []> {
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
"$addr.addr = $wb", []>;
|
||||
|
||||
def VLD3d8 : VLD3D<0b0000, "vld3", "8">;
|
||||
def VLD3d16 : VLD3D<0b0100, "vld3", "16">;
|
||||
@ -266,10 +260,7 @@ class VLD4WB<bits<4> op7_4, string OpcodeStr, string Dt>
|
||||
(outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4, GPR:$wb),
|
||||
(ins addrmode6:$addr), IIC_VLD4,
|
||||
OpcodeStr, Dt, "\\{$dst1, $dst2, $dst3, $dst4\\}, $addr",
|
||||
"$addr.addr = $wb", []> {
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
"$addr.addr = $wb", []>;
|
||||
|
||||
def VLD4d8 : VLD4D<0b0000, "vld4", "8">;
|
||||
def VLD4d16 : VLD4D<0b0100, "vld4", "16">;
|
||||
@ -306,28 +297,12 @@ def VLD2LNd16 : VLD2LN<0b0101, "vld2", "16"> { let Inst{5} = 0; }
|
||||
def VLD2LNd32 : VLD2LN<0b1001, "vld2", "32"> { let Inst{6} = 0; }
|
||||
|
||||
// vld2 to double-spaced even registers.
|
||||
def VLD2LNq16a: VLD2LN<0b0101, "vld2", "16"> {
|
||||
let Inst{5} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VLD2LNq32a: VLD2LN<0b1001, "vld2", "32"> {
|
||||
let Inst{6} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VLD2LNq16a: VLD2LN<0b0101, "vld2", "16"> { let Inst{5} = 1; }
|
||||
def VLD2LNq32a: VLD2LN<0b1001, "vld2", "32"> { let Inst{6} = 1; }
|
||||
|
||||
// vld2 to double-spaced odd registers.
|
||||
def VLD2LNq16b: VLD2LN<0b0101, "vld2", "16"> {
|
||||
let Inst{5} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VLD2LNq32b: VLD2LN<0b1001, "vld2", "32"> {
|
||||
let Inst{6} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VLD2LNq16b: VLD2LN<0b0101, "vld2", "16"> { let Inst{5} = 1; }
|
||||
def VLD2LNq32b: VLD2LN<0b1001, "vld2", "32"> { let Inst{6} = 1; }
|
||||
|
||||
// VLD3LN : Vector Load (single 3-element structure to one lane)
|
||||
class VLD3LN<bits<4> op11_8, string OpcodeStr, string Dt>
|
||||
@ -343,11 +318,7 @@ def VLD3LNd16 : VLD3LN<0b0110, "vld3", "16"> { let Inst{5-4} = 0b00; }
|
||||
def VLD3LNd32 : VLD3LN<0b1010, "vld3", "32"> { let Inst{6-4} = 0b000; }
|
||||
|
||||
// vld3 to double-spaced even registers.
|
||||
def VLD3LNq16a: VLD3LN<0b0110, "vld3", "16"> {
|
||||
let Inst{5-4} = 0b10;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VLD3LNq16a: VLD3LN<0b0110, "vld3", "16"> { let Inst{5-4} = 0b10; }
|
||||
def VLD3LNq32a: VLD3LN<0b1010, "vld3", "32"> { let Inst{6-4} = 0b100; }
|
||||
|
||||
// vld3 to double-spaced odd registers.
|
||||
@ -369,28 +340,12 @@ def VLD4LNd16 : VLD4LN<0b0111, "vld4", "16"> { let Inst{5} = 0; }
|
||||
def VLD4LNd32 : VLD4LN<0b1011, "vld4", "32"> { let Inst{6} = 0; }
|
||||
|
||||
// vld4 to double-spaced even registers.
|
||||
def VLD4LNq16a: VLD4LN<0b0111, "vld4", "16"> {
|
||||
let Inst{5} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VLD4LNq32a: VLD4LN<0b1011, "vld4", "32"> {
|
||||
let Inst{6} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VLD4LNq16a: VLD4LN<0b0111, "vld4", "16"> { let Inst{5} = 1; }
|
||||
def VLD4LNq32a: VLD4LN<0b1011, "vld4", "32"> { let Inst{6} = 1; }
|
||||
|
||||
// vld4 to double-spaced odd registers.
|
||||
def VLD4LNq16b: VLD4LN<0b0111, "vld4", "16"> {
|
||||
let Inst{5} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VLD4LNq32b: VLD4LN<0b1011, "vld4", "32"> {
|
||||
let Inst{6} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VLD4LNq16b: VLD4LN<0b0111, "vld4", "16"> { let Inst{5} = 1; }
|
||||
def VLD4LNq32b: VLD4LN<0b1011, "vld4", "32"> { let Inst{6} = 1; }
|
||||
|
||||
// VLD1DUP : Vector Load (single element to all lanes)
|
||||
// VLD2DUP : Vector Load (single 2-element structure to all lanes)
|
||||
@ -478,10 +433,7 @@ def VST2q32 : VST2Q<0b1000, "vst2", "32">;
|
||||
class VST2Ddbl<bits<4> op7_4, string OpcodeStr, string Dt>
|
||||
: NLdSt<0, 0b00, 0b1001, op7_4, (outs),
|
||||
(ins addrmode6:$addr, DPR:$src1, DPR:$src2), IIC_VST,
|
||||
OpcodeStr, Dt, "\\{$src1, $src2\\}, $addr", "", []> {
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
OpcodeStr, Dt, "\\{$src1, $src2\\}, $addr", "", []>;
|
||||
|
||||
def VST2d8D : VST2Ddbl<0b0000, "vst2", "8">;
|
||||
def VST2d16D : VST2Ddbl<0b0100, "vst2", "16">;
|
||||
@ -496,10 +448,7 @@ class VST3WB<bits<4> op7_4, string OpcodeStr, string Dt>
|
||||
: NLdSt<0,0b00,0b0101,op7_4, (outs GPR:$wb),
|
||||
(ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3), IIC_VST,
|
||||
OpcodeStr, Dt, "\\{$src1, $src2, $src3\\}, $addr",
|
||||
"$addr.addr = $wb", []> {
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
"$addr.addr = $wb", []>;
|
||||
|
||||
def VST3d8 : VST3D<0b0000, "vst3", "8">;
|
||||
def VST3d16 : VST3D<0b0100, "vst3", "16">;
|
||||
@ -529,10 +478,7 @@ class VST4WB<bits<4> op7_4, string OpcodeStr, string Dt>
|
||||
: NLdSt<0,0b00,0b0001,op7_4, (outs GPR:$wb),
|
||||
(ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4),
|
||||
IIC_VST, OpcodeStr, Dt, "\\{$src1, $src2, $src3, $src4\\}, $addr",
|
||||
"$addr.addr = $wb", []> {
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
"$addr.addr = $wb", []>;
|
||||
|
||||
def VST4d8 : VST4D<0b0000, "vst4", "8">;
|
||||
def VST4d16 : VST4D<0b0100, "vst4", "16">;
|
||||
@ -569,28 +515,12 @@ def VST2LNd16 : VST2LN<0b0101, "vst2", "16"> { let Inst{5} = 0; }
|
||||
def VST2LNd32 : VST2LN<0b1001, "vst2", "32"> { let Inst{6} = 0; }
|
||||
|
||||
// vst2 to double-spaced even registers.
|
||||
def VST2LNq16a: VST2LN<0b0101, "vst2", "16"> {
|
||||
let Inst{5} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VST2LNq32a: VST2LN<0b1001, "vst2", "32"> {
|
||||
let Inst{6} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VST2LNq16a: VST2LN<0b0101, "vst2", "16"> { let Inst{5} = 1; }
|
||||
def VST2LNq32a: VST2LN<0b1001, "vst2", "32"> { let Inst{6} = 1; }
|
||||
|
||||
// vst2 to double-spaced odd registers.
|
||||
def VST2LNq16b: VST2LN<0b0101, "vst2", "16"> {
|
||||
let Inst{5} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VST2LNq32b: VST2LN<0b1001, "vst2", "32"> {
|
||||
let Inst{6} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VST2LNq16b: VST2LN<0b0101, "vst2", "16"> { let Inst{5} = 1; }
|
||||
def VST2LNq32b: VST2LN<0b1001, "vst2", "32"> { let Inst{6} = 1; }
|
||||
|
||||
// VST3LN : Vector Store (single 3-element structure from one lane)
|
||||
class VST3LN<bits<4> op11_8, string OpcodeStr, string Dt>
|
||||
@ -605,28 +535,12 @@ def VST3LNd16 : VST3LN<0b0110, "vst3", "16"> { let Inst{5-4} = 0b00; }
|
||||
def VST3LNd32 : VST3LN<0b1010, "vst3", "32"> { let Inst{6-4} = 0b000; }
|
||||
|
||||
// vst3 to double-spaced even registers.
|
||||
def VST3LNq16a: VST3LN<0b0110, "vst3", "16"> {
|
||||
let Inst{5-4} = 0b10;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VST3LNq32a: VST3LN<0b1010, "vst3", "32"> {
|
||||
let Inst{6-4} = 0b100;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VST3LNq16a: VST3LN<0b0110, "vst3", "16"> { let Inst{5-4} = 0b10; }
|
||||
def VST3LNq32a: VST3LN<0b1010, "vst3", "32"> { let Inst{6-4} = 0b100; }
|
||||
|
||||
// vst3 to double-spaced odd registers.
|
||||
def VST3LNq16b: VST3LN<0b0110, "vst3", "16"> {
|
||||
let Inst{5-4} = 0b10;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VST3LNq32b: VST3LN<0b1010, "vst3", "32"> {
|
||||
let Inst{6-4} = 0b100;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VST3LNq16b: VST3LN<0b0110, "vst3", "16"> { let Inst{5-4} = 0b10; }
|
||||
def VST3LNq32b: VST3LN<0b1010, "vst3", "32"> { let Inst{6-4} = 0b100; }
|
||||
|
||||
// VST4LN : Vector Store (single 4-element structure from one lane)
|
||||
class VST4LN<bits<4> op11_8, string OpcodeStr, string Dt>
|
||||
@ -642,28 +556,12 @@ def VST4LNd16 : VST4LN<0b0111, "vst4", "16"> { let Inst{5} = 0; }
|
||||
def VST4LNd32 : VST4LN<0b1011, "vst4", "32"> { let Inst{6} = 0; }
|
||||
|
||||
// vst4 to double-spaced even registers.
|
||||
def VST4LNq16a: VST4LN<0b0111, "vst4", "16"> {
|
||||
let Inst{5} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VST4LNq32a: VST4LN<0b1011, "vst4", "32"> {
|
||||
let Inst{6} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VST4LNq16a: VST4LN<0b0111, "vst4", "16"> { let Inst{5} = 1; }
|
||||
def VST4LNq32a: VST4LN<0b1011, "vst4", "32"> { let Inst{6} = 1; }
|
||||
|
||||
// vst4 to double-spaced odd registers.
|
||||
def VST4LNq16b: VST4LN<0b0111, "vst4", "16"> {
|
||||
let Inst{5} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VST4LNq32b: VST4LN<0b1011, "vst4", "32"> {
|
||||
let Inst{6} = 1;
|
||||
let NSF = VLDSTLaneDblFrm; // For disassembly.
|
||||
let NSForm = VLDSTLaneDblFrm.Value; // For disassembly.
|
||||
}
|
||||
def VST4LNq16b: VST4LN<0b0111, "vst4", "16"> { let Inst{5} = 1; }
|
||||
def VST4LNq32b: VST4LN<0b1011, "vst4", "32"> { let Inst{6} = 1; }
|
||||
|
||||
} // mayStore = 1, hasExtraSrcRegAllocReq = 1
|
||||
|
||||
@ -770,18 +668,12 @@ class N2VDShuffle<bits<2> op19_18, bits<5> op11_7, string OpcodeStr, string Dt>
|
||||
: N2V<0b11, 0b11, op19_18, 0b10, op11_7, 0, 0, (outs DPR:$dst1, DPR:$dst2),
|
||||
(ins DPR:$src1, DPR:$src2), IIC_VPERMD,
|
||||
OpcodeStr, Dt, "$dst1, $dst2",
|
||||
"$src1 = $dst1, $src2 = $dst2", []> {
|
||||
let NSF = NVectorShuffleFrm; // For disassembly.
|
||||
let NSForm = NVectorShuffleFrm.Value; // For disassembly.
|
||||
}
|
||||
"$src1 = $dst1, $src2 = $dst2", []>;
|
||||
class N2VQShuffle<bits<2> op19_18, bits<5> op11_7,
|
||||
InstrItinClass itin, string OpcodeStr, string Dt>
|
||||
: N2V<0b11, 0b11, op19_18, 0b10, op11_7, 1, 0, (outs QPR:$dst1, QPR:$dst2),
|
||||
(ins QPR:$src1, QPR:$src2), itin, OpcodeStr, Dt, "$dst1, $dst2",
|
||||
"$src1 = $dst1, $src2 = $dst2", []> {
|
||||
let NSF = NVectorShuffleFrm; // For disassembly.
|
||||
let NSForm = NVectorShuffleFrm.Value; // For disassembly.
|
||||
}
|
||||
"$src1 = $dst1, $src2 = $dst2", []>;
|
||||
|
||||
// Basic 3-register operations: single-, double- and quad-register.
|
||||
class N3VS<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op4,
|
||||
@ -823,8 +715,6 @@ class N3VDSL<bits<2> op21_20, bits<4> op11_8,
|
||||
(Ty (ShOp (Ty DPR:$src1),
|
||||
(Ty (NEONvduplane (Ty DPR_VFP2:$src2), imm:$lane)))))]>{
|
||||
let isCommutable = 0;
|
||||
let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
|
||||
}
|
||||
class N3VDSL16<bits<2> op21_20, bits<4> op11_8,
|
||||
string OpcodeStr, string Dt, ValueType Ty, SDNode ShOp>
|
||||
@ -835,8 +725,6 @@ class N3VDSL16<bits<2> op21_20, bits<4> op11_8,
|
||||
(Ty (ShOp (Ty DPR:$src1),
|
||||
(Ty (NEONvduplane (Ty DPR_8:$src2), imm:$lane)))))]> {
|
||||
let isCommutable = 0;
|
||||
let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
|
||||
}
|
||||
|
||||
class N3VQ<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op4,
|
||||
@ -868,8 +756,6 @@ class N3VQSL<bits<2> op21_20, bits<4> op11_8,
|
||||
(ResTy (NEONvduplane (OpTy DPR_VFP2:$src2),
|
||||
imm:$lane)))))]> {
|
||||
let isCommutable = 0;
|
||||
let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
|
||||
}
|
||||
class N3VQSL16<bits<2> op21_20, bits<4> op11_8, string OpcodeStr, string Dt,
|
||||
ValueType ResTy, ValueType OpTy, SDNode ShOp>
|
||||
@ -881,8 +767,6 @@ class N3VQSL16<bits<2> op21_20, bits<4> op11_8, string OpcodeStr, string Dt,
|
||||
(ResTy (NEONvduplane (OpTy DPR_8:$src2),
|
||||
imm:$lane)))))]> {
|
||||
let isCommutable = 0;
|
||||
let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
|
||||
}
|
||||
|
||||
// Basic 3-register intrinsics, both double- and quad-register.
|
||||
@ -905,8 +789,6 @@ class N3VDIntSL<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
(Ty (NEONvduplane (Ty DPR_VFP2:$src2),
|
||||
imm:$lane)))))]> {
|
||||
let isCommutable = 0;
|
||||
let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
|
||||
}
|
||||
class N3VDIntSL16<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
string OpcodeStr, string Dt, ValueType Ty, Intrinsic IntOp>
|
||||
@ -918,8 +800,6 @@ class N3VDIntSL16<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
(Ty (NEONvduplane (Ty DPR_8:$src2),
|
||||
imm:$lane)))))]> {
|
||||
let isCommutable = 0;
|
||||
let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
|
||||
}
|
||||
|
||||
class N3VQInt<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op4,
|
||||
@ -942,8 +822,6 @@ class N3VQIntSL<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
(ResTy (NEONvduplane (OpTy DPR_VFP2:$src2),
|
||||
imm:$lane)))))]> {
|
||||
let isCommutable = 0;
|
||||
let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
|
||||
}
|
||||
class N3VQIntSL16<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
string OpcodeStr, string Dt,
|
||||
@ -956,8 +834,6 @@ class N3VQIntSL16<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
(ResTy (NEONvduplane (OpTy DPR_8:$src2),
|
||||
imm:$lane)))))]> {
|
||||
let isCommutable = 0;
|
||||
let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
|
||||
}
|
||||
|
||||
// Multiply-Add/Sub operations: single-, double- and quad-register.
|
||||
@ -988,10 +864,7 @@ class N3VDMulOpSL<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
(Ty (ShOp (Ty DPR:$src1),
|
||||
(Ty (MulOp DPR:$src2,
|
||||
(Ty (NEONvduplane (Ty DPR_VFP2:$src3),
|
||||
imm:$lane)))))))]> {
|
||||
let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
|
||||
}
|
||||
imm:$lane)))))))]>;
|
||||
class N3VDMulOpSL16<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
string OpcodeStr, string Dt,
|
||||
ValueType Ty, SDNode MulOp, SDNode ShOp>
|
||||
@ -1003,10 +876,7 @@ class N3VDMulOpSL16<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
(Ty (ShOp (Ty DPR:$src1),
|
||||
(Ty (MulOp DPR:$src2,
|
||||
(Ty (NEONvduplane (Ty DPR_8:$src3),
|
||||
imm:$lane)))))))]> {
|
||||
let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
|
||||
}
|
||||
imm:$lane)))))))]>;
|
||||
|
||||
class N3VQMulOp<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op4,
|
||||
InstrItinClass itin, string OpcodeStr, string Dt, ValueType Ty,
|
||||
@ -1027,10 +897,7 @@ class N3VQMulOpSL<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
(ResTy (ShOp (ResTy QPR:$src1),
|
||||
(ResTy (MulOp QPR:$src2,
|
||||
(ResTy (NEONvduplane (OpTy DPR_VFP2:$src3),
|
||||
imm:$lane)))))))]> {
|
||||
let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
|
||||
}
|
||||
imm:$lane)))))))]>;
|
||||
class N3VQMulOpSL16<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
string OpcodeStr, string Dt,
|
||||
ValueType ResTy, ValueType OpTy,
|
||||
@ -1043,10 +910,7 @@ class N3VQMulOpSL16<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
(ResTy (ShOp (ResTy QPR:$src1),
|
||||
(ResTy (MulOp QPR:$src2,
|
||||
(ResTy (NEONvduplane (OpTy DPR_8:$src3),
|
||||
imm:$lane)))))))]> {
|
||||
let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
|
||||
}
|
||||
imm:$lane)))))))]>;
|
||||
|
||||
// Neon 3-argument intrinsics, both double- and quad-register.
|
||||
// The destination register is also used as the first source operand register.
|
||||
@ -1132,10 +996,7 @@ class N3VLIntSL<bit op24, bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
[(set (ResTy QPR:$dst),
|
||||
(ResTy (IntOp (OpTy DPR:$src1),
|
||||
(OpTy (NEONvduplane (OpTy DPR_VFP2:$src2),
|
||||
imm:$lane)))))]> {
|
||||
let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
|
||||
}
|
||||
imm:$lane)))))]>;
|
||||
class N3VLIntSL16<bit op24, bits<2> op21_20, bits<4> op11_8,
|
||||
InstrItinClass itin, string OpcodeStr, string Dt,
|
||||
ValueType ResTy, ValueType OpTy, Intrinsic IntOp>
|
||||
@ -1145,10 +1006,7 @@ class N3VLIntSL16<bit op24, bits<2> op21_20, bits<4> op11_8,
|
||||
[(set (ResTy QPR:$dst),
|
||||
(ResTy (IntOp (OpTy DPR:$src1),
|
||||
(OpTy (NEONvduplane (OpTy DPR_8:$src2),
|
||||
imm:$lane)))))]> {
|
||||
let NSF = NVdVnVmImmMulScalarFrm; // For disassembly.
|
||||
let NSForm = NVdVnVmImmMulScalarFrm.Value; // For disassembly.
|
||||
}
|
||||
imm:$lane)))))]>;
|
||||
|
||||
// Wide 3-register intrinsics.
|
||||
class N3VWInt<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op4,
|
||||
@ -1197,10 +1055,6 @@ class N2VQPLInt2<bits<2> op24_23, bits<2> op21_20, bits<2> op19_18,
|
||||
OpcodeStr, Dt, "$dst, $src2", "$src1 = $dst",
|
||||
[(set QPR:$dst, (ResTy (IntOp (ResTy QPR:$src1), (OpTy QPR:$src2))))]>;
|
||||
|
||||
// This is a big let * in block to mark these instructions NVectorShiftFrm to
|
||||
// help the disassembler.
|
||||
let NSF = NVectorShiftFrm, NSForm = NVectorShiftFrm.Value in {
|
||||
|
||||
// Shift by immediate,
|
||||
// both double- and quad-register.
|
||||
class N2VDSh<bit op24, bit op23, bits<4> op11_8, bit op7, bit op4,
|
||||
@ -1218,6 +1072,16 @@ class N2VQSh<bit op24, bit op23, bits<4> op11_8, bit op7, bit op4,
|
||||
OpcodeStr, Dt, "$dst, $src, $SIMM", "",
|
||||
[(set QPR:$dst, (Ty (OpNode (Ty QPR:$src), (i32 imm:$SIMM))))]>;
|
||||
|
||||
// Long shift by immediate.
|
||||
class N2VLSh<bit op24, bit op23, bits<4> op11_8, bit op7, bit op6, bit op4,
|
||||
string OpcodeStr, string Dt,
|
||||
ValueType ResTy, ValueType OpTy, SDNode OpNode>
|
||||
: N2VImm<op24, op23, op11_8, op7, op6, op4,
|
||||
(outs QPR:$dst), (ins DPR:$src, i32imm:$SIMM), IIC_VSHLiD,
|
||||
OpcodeStr, Dt, "$dst, $src, $SIMM", "",
|
||||
[(set QPR:$dst, (ResTy (OpNode (OpTy DPR:$src),
|
||||
(i32 imm:$SIMM))))]>;
|
||||
|
||||
// Narrow shift by immediate.
|
||||
class N2VNSh<bit op24, bit op23, bits<4> op11_8, bit op7, bit op6, bit op4,
|
||||
InstrItinClass itin, string OpcodeStr, string Dt,
|
||||
@ -1260,26 +1124,8 @@ class N2VQShIns<bit op24, bit op23, bits<4> op11_8, bit op7, bit op4,
|
||||
OpcodeStr, Dt, "$dst, $src2, $SIMM", "$src1 = $dst",
|
||||
[(set QPR:$dst, (Ty (ShOp QPR:$src1, QPR:$src2, (i32 imm:$SIMM))))]>;
|
||||
|
||||
} // End of "let NSF = NVectorShiftFrm, ..."
|
||||
|
||||
// Long shift by immediate.
|
||||
class N2VLSh<bit op24, bit op23, bits<4> op11_8, bit op7, bit op6, bit op4,
|
||||
string OpcodeStr, string Dt,
|
||||
ValueType ResTy, ValueType OpTy, SDNode OpNode>
|
||||
: N2VImm<op24, op23, op11_8, op7, op6, op4,
|
||||
(outs QPR:$dst), (ins DPR:$src, i32imm:$SIMM), IIC_VSHLiD,
|
||||
OpcodeStr, Dt, "$dst, $src, $SIMM", "",
|
||||
[(set QPR:$dst, (ResTy (OpNode (OpTy DPR:$src),
|
||||
(i32 imm:$SIMM))))]> {
|
||||
// This has a different interpretation of the shift amount encoding than
|
||||
// NVectorShiftFrm.
|
||||
let NSF = NVectorShift2Frm; // For disassembly.
|
||||
let NSForm = NVectorShift2Frm.Value; // For disassembly.
|
||||
}
|
||||
|
||||
// Convert, with fractional bits immediate,
|
||||
// both double- and quad-register.
|
||||
let NSF = NVdVmImmVCVTFrm, NSForm = NVdVmImmVCVTFrm.Value in {
|
||||
class N2VCvtD<bit op24, bit op23, bits<4> op11_8, bit op7, bit op4,
|
||||
string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy,
|
||||
Intrinsic IntOp>
|
||||
@ -1294,7 +1140,6 @@ class N2VCvtQ<bit op24, bit op23, bits<4> op11_8, bit op7, bit op4,
|
||||
(outs QPR:$dst), (ins QPR:$src, i32imm:$SIMM), IIC_VUNAQ,
|
||||
OpcodeStr, Dt, "$dst, $src, $SIMM", "",
|
||||
[(set QPR:$dst, (ResTy (IntOp (OpTy QPR:$src), (i32 imm:$SIMM))))]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Multiclasses
|
||||
@ -1505,60 +1350,6 @@ multiclass N3VInt_QHSD<bit op24, bit op23, bits<4> op11_8, bit op4,
|
||||
v2i64, v2i64, IntOp, Commutable>;
|
||||
}
|
||||
|
||||
// Same as N3VInt_QHSD, except they're for Vector Shift (Register) Instructions.
|
||||
// D:Vd M:Vm N:Vn (notice that M:Vm is the first operand)
|
||||
// This helps the disassembler.
|
||||
let NSF = NVdVnVmImmVectorShiftFrm, NSForm = NVdVnVmImmVectorShiftFrm.Value in {
|
||||
multiclass N3VInt_HS2<bit op24, bit op23, bits<4> op11_8, bit op4,
|
||||
InstrItinClass itinD16, InstrItinClass itinD32,
|
||||
InstrItinClass itinQ16, InstrItinClass itinQ32,
|
||||
string OpcodeStr, string Dt,
|
||||
Intrinsic IntOp, bit Commutable = 0> {
|
||||
// 64-bit vector types.
|
||||
def v4i16 : N3VDInt<op24, op23, 0b01, op11_8, op4, itinD16,
|
||||
OpcodeStr, !strconcat(Dt, "16"),
|
||||
v4i16, v4i16, IntOp, Commutable>;
|
||||
def v2i32 : N3VDInt<op24, op23, 0b10, op11_8, op4, itinD32,
|
||||
OpcodeStr, !strconcat(Dt, "32"),
|
||||
v2i32, v2i32, IntOp, Commutable>;
|
||||
|
||||
// 128-bit vector types.
|
||||
def v8i16 : N3VQInt<op24, op23, 0b01, op11_8, op4, itinQ16,
|
||||
OpcodeStr, !strconcat(Dt, "16"),
|
||||
v8i16, v8i16, IntOp, Commutable>;
|
||||
def v4i32 : N3VQInt<op24, op23, 0b10, op11_8, op4, itinQ32,
|
||||
OpcodeStr, !strconcat(Dt, "32"),
|
||||
v4i32, v4i32, IntOp, Commutable>;
|
||||
}
|
||||
multiclass N3VInt_QHS2<bit op24, bit op23, bits<4> op11_8, bit op4,
|
||||
InstrItinClass itinD16, InstrItinClass itinD32,
|
||||
InstrItinClass itinQ16, InstrItinClass itinQ32,
|
||||
string OpcodeStr, string Dt,
|
||||
Intrinsic IntOp, bit Commutable = 0>
|
||||
: N3VInt_HS2<op24, op23, op11_8, op4, itinD16, itinD32, itinQ16, itinQ32,
|
||||
OpcodeStr, Dt, IntOp, Commutable> {
|
||||
def v8i8 : N3VDInt<op24, op23, 0b00, op11_8, op4, itinD16,
|
||||
OpcodeStr, !strconcat(Dt, "8"),
|
||||
v8i8, v8i8, IntOp, Commutable>;
|
||||
def v16i8 : N3VQInt<op24, op23, 0b00, op11_8, op4, itinQ16,
|
||||
OpcodeStr, !strconcat(Dt, "8"),
|
||||
v16i8, v16i8, IntOp, Commutable>;
|
||||
}
|
||||
multiclass N3VInt_QHSD2<bit op24, bit op23, bits<4> op11_8, bit op4,
|
||||
InstrItinClass itinD16, InstrItinClass itinD32,
|
||||
InstrItinClass itinQ16, InstrItinClass itinQ32,
|
||||
string OpcodeStr, string Dt,
|
||||
Intrinsic IntOp, bit Commutable = 0>
|
||||
: N3VInt_QHS2<op24, op23, op11_8, op4, itinD16, itinD32, itinQ16, itinQ32,
|
||||
OpcodeStr, Dt, IntOp, Commutable> {
|
||||
def v1i64 : N3VDInt<op24, op23, 0b11, op11_8, op4, itinD32,
|
||||
OpcodeStr, !strconcat(Dt, "64"),
|
||||
v1i64, v1i64, IntOp, Commutable>;
|
||||
def v2i64 : N3VQInt<op24, op23, 0b11, op11_8, op4, itinQ32,
|
||||
OpcodeStr, !strconcat(Dt, "64"),
|
||||
v2i64, v2i64, IntOp, Commutable>;
|
||||
}
|
||||
}
|
||||
|
||||
// Neon Narrowing 3-register vector intrinsics,
|
||||
// source operand element sizes of 16, 32 and 64 bits:
|
||||
@ -1828,47 +1619,6 @@ multiclass N2VSh_QHSD<bit op24, bit op23, bits<4> op11_8, bit op4,
|
||||
// imm6 = xxxxxx
|
||||
}
|
||||
|
||||
// Same as N2VSh_QHSD, except the instructions have a differnt interpretation of
|
||||
// the shift amount. This helps the disassembler.
|
||||
let NSF = NVectorShift2Frm, NSForm = NVectorShift2Frm.Value in {
|
||||
multiclass N2VSh_QHSD2<bit op24, bit op23, bits<4> op11_8, bit op4,
|
||||
InstrItinClass itin, string OpcodeStr, string Dt,
|
||||
SDNode OpNode> {
|
||||
// 64-bit vector types.
|
||||
def v8i8 : N2VDSh<op24, op23, op11_8, 0, op4, itin,
|
||||
OpcodeStr, !strconcat(Dt, "8"), v8i8, OpNode> {
|
||||
let Inst{21-19} = 0b001; // imm6 = 001xxx
|
||||
}
|
||||
def v4i16 : N2VDSh<op24, op23, op11_8, 0, op4, itin,
|
||||
OpcodeStr, !strconcat(Dt, "16"), v4i16, OpNode> {
|
||||
let Inst{21-20} = 0b01; // imm6 = 01xxxx
|
||||
}
|
||||
def v2i32 : N2VDSh<op24, op23, op11_8, 0, op4, itin,
|
||||
OpcodeStr, !strconcat(Dt, "32"), v2i32, OpNode> {
|
||||
let Inst{21} = 0b1; // imm6 = 1xxxxx
|
||||
}
|
||||
def v1i64 : N2VDSh<op24, op23, op11_8, 1, op4, itin,
|
||||
OpcodeStr, !strconcat(Dt, "64"), v1i64, OpNode>;
|
||||
// imm6 = xxxxxx
|
||||
|
||||
// 128-bit vector types.
|
||||
def v16i8 : N2VQSh<op24, op23, op11_8, 0, op4, itin,
|
||||
OpcodeStr, !strconcat(Dt, "8"), v16i8, OpNode> {
|
||||
let Inst{21-19} = 0b001; // imm6 = 001xxx
|
||||
}
|
||||
def v8i16 : N2VQSh<op24, op23, op11_8, 0, op4, itin,
|
||||
OpcodeStr, !strconcat(Dt, "16"), v8i16, OpNode> {
|
||||
let Inst{21-20} = 0b01; // imm6 = 01xxxx
|
||||
}
|
||||
def v4i32 : N2VQSh<op24, op23, op11_8, 0, op4, itin,
|
||||
OpcodeStr, !strconcat(Dt, "32"), v4i32, OpNode> {
|
||||
let Inst{21} = 0b1; // imm6 = 1xxxxx
|
||||
}
|
||||
def v2i64 : N2VQSh<op24, op23, op11_8, 1, op4, itin,
|
||||
OpcodeStr, !strconcat(Dt, "64"), v2i64, OpNode>;
|
||||
// imm6 = xxxxxx
|
||||
}
|
||||
}
|
||||
|
||||
// Neon Shift-Accumulate vector operations,
|
||||
// element sizes of 8, 16, 32 and 64 bits:
|
||||
@ -1949,47 +1699,6 @@ multiclass N2VShIns_QHSD<bit op24, bit op23, bits<4> op11_8, bit op4,
|
||||
// imm6 = xxxxxx
|
||||
}
|
||||
|
||||
// Same as N2VShIns_QHSD, except the instructions have a differnt interpretation
|
||||
// of the shift amount. This helps the disassembler.
|
||||
let NSF = NVectorShift2Frm, NSForm = NVectorShift2Frm.Value in {
|
||||
multiclass N2VShIns_QHSD2<bit op24, bit op23, bits<4> op11_8, bit op4,
|
||||
string OpcodeStr, SDNode ShOp> {
|
||||
// 64-bit vector types.
|
||||
def v8i8 : N2VDShIns<op24, op23, op11_8, 0, op4,
|
||||
OpcodeStr, "8", v8i8, ShOp> {
|
||||
let Inst{21-19} = 0b001; // imm6 = 001xxx
|
||||
}
|
||||
def v4i16 : N2VDShIns<op24, op23, op11_8, 0, op4,
|
||||
OpcodeStr, "16", v4i16, ShOp> {
|
||||
let Inst{21-20} = 0b01; // imm6 = 01xxxx
|
||||
}
|
||||
def v2i32 : N2VDShIns<op24, op23, op11_8, 0, op4,
|
||||
OpcodeStr, "32", v2i32, ShOp> {
|
||||
let Inst{21} = 0b1; // imm6 = 1xxxxx
|
||||
}
|
||||
def v1i64 : N2VDShIns<op24, op23, op11_8, 1, op4,
|
||||
OpcodeStr, "64", v1i64, ShOp>;
|
||||
// imm6 = xxxxxx
|
||||
|
||||
// 128-bit vector types.
|
||||
def v16i8 : N2VQShIns<op24, op23, op11_8, 0, op4,
|
||||
OpcodeStr, "8", v16i8, ShOp> {
|
||||
let Inst{21-19} = 0b001; // imm6 = 001xxx
|
||||
}
|
||||
def v8i16 : N2VQShIns<op24, op23, op11_8, 0, op4,
|
||||
OpcodeStr, "16", v8i16, ShOp> {
|
||||
let Inst{21-20} = 0b01; // imm6 = 01xxxx
|
||||
}
|
||||
def v4i32 : N2VQShIns<op24, op23, op11_8, 0, op4,
|
||||
OpcodeStr, "32", v4i32, ShOp> {
|
||||
let Inst{21} = 0b1; // imm6 = 1xxxxx
|
||||
}
|
||||
def v2i64 : N2VQShIns<op24, op23, op11_8, 1, op4,
|
||||
OpcodeStr, "64", v2i64, ShOp>;
|
||||
// imm6 = xxxxxx
|
||||
}
|
||||
}
|
||||
|
||||
// Neon Shift Long operations,
|
||||
// element sizes of 8, 16, 32 bits:
|
||||
multiclass N2VLSh_QHS<bit op24, bit op23, bits<4> op11_8, bit op7, bit op6,
|
||||
@ -2620,21 +2329,18 @@ def VRSQRTSfq : N3VQInt<0, 0, 0b10, 0b1111, 1,
|
||||
// Vector Shifts.
|
||||
|
||||
// VSHL : Vector Shift
|
||||
defm VSHLs : N3VInt_QHSD2<0,0, 0b0100, 0, IIC_VSHLiD, IIC_VSHLiD, IIC_VSHLiQ,
|
||||
IIC_VSHLiQ, "vshl", "s", int_arm_neon_vshifts, 0>;
|
||||
defm VSHLu : N3VInt_QHSD2<1,0, 0b0100, 0, IIC_VSHLiD, IIC_VSHLiD, IIC_VSHLiQ,
|
||||
IIC_VSHLiQ, "vshl", "u", int_arm_neon_vshiftu, 0>;
|
||||
defm VSHLs : N3VInt_QHSD<0, 0, 0b0100, 0, IIC_VSHLiD, IIC_VSHLiD, IIC_VSHLiQ,
|
||||
IIC_VSHLiQ, "vshl", "s", int_arm_neon_vshifts, 0>;
|
||||
defm VSHLu : N3VInt_QHSD<1, 0, 0b0100, 0, IIC_VSHLiD, IIC_VSHLiD, IIC_VSHLiQ,
|
||||
IIC_VSHLiQ, "vshl", "u", int_arm_neon_vshiftu, 0>;
|
||||
// VSHL : Vector Shift Left (Immediate)
|
||||
// (disassembly note: this has a different interpretation of the shift amont)
|
||||
defm VSHLi : N2VSh_QHSD2<0, 1, 0b0101, 1, IIC_VSHLiD, "vshl", "i", NEONvshl>;
|
||||
defm VSHLi : N2VSh_QHSD<0, 1, 0b0101, 1, IIC_VSHLiD, "vshl", "i", NEONvshl>;
|
||||
// VSHR : Vector Shift Right (Immediate)
|
||||
defm VSHRs : N2VSh_QHSD<0, 1, 0b0000, 1, IIC_VSHLiD, "vshr", "s", NEONvshrs>;
|
||||
defm VSHRu : N2VSh_QHSD<1, 1, 0b0000, 1, IIC_VSHLiD, "vshr", "u", NEONvshru>;
|
||||
|
||||
// VSHLL : Vector Shift Left Long
|
||||
// (disassembly note: this has a different interpretation of the shift amont)
|
||||
defm VSHLLs : N2VLSh_QHS<0, 1, 0b1010, 0, 0, 1, "vshll", "s", NEONvshlls>;
|
||||
// (disassembly note: this has a different interpretation of the shift amont)
|
||||
defm VSHLLu : N2VLSh_QHS<1, 1, 0b1010, 0, 0, 1, "vshll", "u", NEONvshllu>;
|
||||
|
||||
// VSHLL : Vector Shift Left Long (with maximum shift count)
|
||||
@ -2644,8 +2350,6 @@ class N2VLShMax<bit op24, bit op23, bits<6> op21_16, bits<4> op11_8, bit op7,
|
||||
: N2VLSh<op24, op23, op11_8, op7, op6, op4, OpcodeStr, Dt,
|
||||
ResTy, OpTy, OpNode> {
|
||||
let Inst{21-16} = op21_16;
|
||||
let NSF = NVdVmImmVSHLLFrm; // For disassembly.
|
||||
let NSForm = NVdVmImmVSHLLFrm.Value; // For disassembly.
|
||||
}
|
||||
def VSHLLi8 : N2VLShMax<1, 1, 0b110010, 0b0011, 0, 0, 0, "vshll", "i8",
|
||||
v8i16, v8i8, NEONvshlli>;
|
||||
@ -2659,10 +2363,10 @@ defm VSHRN : N2VNSh_HSD<0,1,0b1000,0,0,1, IIC_VSHLiD, "vshrn", "i",
|
||||
NEONvshrn>;
|
||||
|
||||
// VRSHL : Vector Rounding Shift
|
||||
defm VRSHLs : N3VInt_QHSD2<0,0,0b0101,0,IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
|
||||
IIC_VSHLi4Q,"vrshl", "s", int_arm_neon_vrshifts,0>;
|
||||
defm VRSHLu : N3VInt_QHSD2<1,0,0b0101,0,IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
|
||||
IIC_VSHLi4Q,"vrshl", "u", int_arm_neon_vrshiftu,0>;
|
||||
defm VRSHLs : N3VInt_QHSD<0,0,0b0101,0, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
|
||||
IIC_VSHLi4Q, "vrshl", "s", int_arm_neon_vrshifts,0>;
|
||||
defm VRSHLu : N3VInt_QHSD<1,0,0b0101,0, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
|
||||
IIC_VSHLi4Q, "vrshl", "u", int_arm_neon_vrshiftu,0>;
|
||||
// VRSHR : Vector Rounding Shift Right
|
||||
defm VRSHRs : N2VSh_QHSD<0,1,0b0010,1, IIC_VSHLi4D, "vrshr", "s", NEONvrshrs>;
|
||||
defm VRSHRu : N2VSh_QHSD<1,1,0b0010,1, IIC_VSHLi4D, "vrshr", "u", NEONvrshru>;
|
||||
@ -2672,18 +2376,15 @@ defm VRSHRN : N2VNSh_HSD<0, 1, 0b1000, 0, 1, 1, IIC_VSHLi4D, "vrshrn", "i",
|
||||
NEONvrshrn>;
|
||||
|
||||
// VQSHL : Vector Saturating Shift
|
||||
defm VQSHLs : N3VInt_QHSD2<0,0,0b0100,1,IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
|
||||
IIC_VSHLi4Q, "vqshl", "s", int_arm_neon_vqshifts,0>;
|
||||
defm VQSHLu : N3VInt_QHSD2<1,0,0b0100,1,IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
|
||||
IIC_VSHLi4Q, "vqshl", "u", int_arm_neon_vqshiftu,0>;
|
||||
defm VQSHLs : N3VInt_QHSD<0,0,0b0100,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
|
||||
IIC_VSHLi4Q, "vqshl", "s", int_arm_neon_vqshifts,0>;
|
||||
defm VQSHLu : N3VInt_QHSD<1,0,0b0100,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
|
||||
IIC_VSHLi4Q, "vqshl", "u", int_arm_neon_vqshiftu,0>;
|
||||
// VQSHL : Vector Saturating Shift Left (Immediate)
|
||||
// (disassembly note: this has a different interpretation of the shift amont)
|
||||
defm VQSHLsi : N2VSh_QHSD2<0,1,0b0111,1, IIC_VSHLi4D, "vqshl", "s", NEONvqshls>;
|
||||
// (disassembly note: this has a different interpretation of the shift amont)
|
||||
defm VQSHLui : N2VSh_QHSD2<1,1,0b0111,1, IIC_VSHLi4D, "vqshl", "u", NEONvqshlu>;
|
||||
defm VQSHLsi : N2VSh_QHSD<0,1,0b0111,1, IIC_VSHLi4D, "vqshl", "s", NEONvqshls>;
|
||||
defm VQSHLui : N2VSh_QHSD<1,1,0b0111,1, IIC_VSHLi4D, "vqshl", "u", NEONvqshlu>;
|
||||
// VQSHLU : Vector Saturating Shift Left (Immediate, Unsigned)
|
||||
// (disassembly note: this has a different interpretation of the shift amont)
|
||||
defm VQSHLsu : N2VSh_QHSD2<1,1,0b0110,1, IIC_VSHLi4D, "vqshlu","s",NEONvqshlsu>;
|
||||
defm VQSHLsu : N2VSh_QHSD<1,1,0b0110,1, IIC_VSHLi4D, "vqshlu","s",NEONvqshlsu>;
|
||||
|
||||
// VQSHRN : Vector Saturating Shift Right and Narrow
|
||||
defm VQSHRNs : N2VNSh_HSD<0, 1, 0b1001, 0, 0, 1, IIC_VSHLi4D, "vqshrn", "s",
|
||||
@ -2696,12 +2397,12 @@ defm VQSHRUN : N2VNSh_HSD<1, 1, 0b1000, 0, 0, 1, IIC_VSHLi4D, "vqshrun", "s",
|
||||
NEONvqshrnsu>;
|
||||
|
||||
// VQRSHL : Vector Saturating Rounding Shift
|
||||
defm VQRSHLs : N3VInt_QHSD2<0,0,0b0101,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
|
||||
IIC_VSHLi4Q, "vqrshl", "s",
|
||||
int_arm_neon_vqrshifts, 0>;
|
||||
defm VQRSHLu : N3VInt_QHSD2<1,0,0b0101,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
|
||||
IIC_VSHLi4Q, "vqrshl", "u",
|
||||
int_arm_neon_vqrshiftu, 0>;
|
||||
defm VQRSHLs : N3VInt_QHSD<0,0,0b0101,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
|
||||
IIC_VSHLi4Q, "vqrshl", "s",
|
||||
int_arm_neon_vqrshifts, 0>;
|
||||
defm VQRSHLu : N3VInt_QHSD<1,0,0b0101,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q,
|
||||
IIC_VSHLi4Q, "vqrshl", "u",
|
||||
int_arm_neon_vqrshiftu, 0>;
|
||||
|
||||
// VQRSHRN : Vector Saturating Rounding Shift Right and Narrow
|
||||
defm VQRSHRNs : N2VNSh_HSD<0, 1, 0b1001, 0, 1, 1, IIC_VSHLi4D, "vqrshrn", "s",
|
||||
@ -2721,8 +2422,7 @@ defm VRSRAs : N2VShAdd_QHSD<0, 1, 0b0011, 1, "vrsra", "s", NEONvrshrs>;
|
||||
defm VRSRAu : N2VShAdd_QHSD<1, 1, 0b0011, 1, "vrsra", "u", NEONvrshru>;
|
||||
|
||||
// VSLI : Vector Shift Left and Insert
|
||||
// (disassembly note: this has a different interpretation of the shift amont)
|
||||
defm VSLI : N2VShIns_QHSD2<1, 1, 0b0101, 1, "vsli", NEONvsli>;
|
||||
defm VSLI : N2VShIns_QHSD<1, 1, 0b0101, 1, "vsli", NEONvsli>;
|
||||
// VSRI : Vector Shift Right and Insert
|
||||
defm VSRI : N2VShIns_QHSD<1, 1, 0b0100, 1, "vsri", NEONvsri>;
|
||||
|
||||
@ -2818,13 +2518,10 @@ def VSWPq : N2VX<0b11, 0b11, 0b00, 0b10, 0b00000, 1, 0,
|
||||
|
||||
// VMOV : Vector Move (Register)
|
||||
|
||||
// Mark these instructions as 2-register instructions to help the disassembler.
|
||||
let NSF = NVdVmImmFrm, NSForm = NVdVmImmFrm.Value in {
|
||||
def VMOVDneon: N3VX<0, 0, 0b10, 0b0001, 0, 1, (outs DPR:$dst), (ins DPR:$src),
|
||||
IIC_VMOVD, "vmov", "$dst, $src", "", []>;
|
||||
def VMOVQ : N3VX<0, 0, 0b10, 0b0001, 1, 1, (outs QPR:$dst), (ins QPR:$src),
|
||||
IIC_VMOVD, "vmov", "$dst, $src", "", []>;
|
||||
}
|
||||
|
||||
// VMOV : Vector Move (Immediate)
|
||||
|
||||
@ -3065,7 +2762,6 @@ def VDUPfq : NVDup<0b11101010, 0b1011, 0b00, (outs QPR:$dst), (ins GPR:$src),
|
||||
|
||||
// VDUP : Vector Duplicate Lane (from scalar to all elements)
|
||||
|
||||
let NSF = NVdVmImmVDupLaneFrm, NSForm = NVdVmImmVDupLaneFrm.Value in {
|
||||
class VDUPLND<bits<2> op19_18, bits<2> op17_16,
|
||||
string OpcodeStr, string Dt, ValueType Ty>
|
||||
: N2V<0b11, 0b11, op19_18, op17_16, 0b11000, 0, 0,
|
||||
@ -3079,7 +2775,6 @@ class VDUPLNQ<bits<2> op19_18, bits<2> op17_16, string OpcodeStr, string Dt,
|
||||
(outs QPR:$dst), (ins DPR:$src, nohash_imm:$lane), IIC_VMOVD,
|
||||
OpcodeStr, Dt, "$dst, $src[$lane]", "",
|
||||
[(set QPR:$dst, (ResTy (NEONvduplane (OpTy DPR:$src), imm:$lane)))]>;
|
||||
}
|
||||
|
||||
// Inst{19-16} is partially specified depending on the element size.
|
||||
|
||||
@ -3148,37 +2843,24 @@ defm VMOVLu : N2VLInt_QHS<0b11,0b10100,0,1, "vmovl", "u",
|
||||
|
||||
// Vector Conversions.
|
||||
|
||||
let NSF = NVdVmImmVCVTFrm, NSForm = NVdVmImmVCVTFrm.Value in {
|
||||
class N2VDX<bits<2> op24_23, bits<2> op21_20, bits<2> op19_18,
|
||||
bits<2> op17_16, bits<5> op11_7, bit op4, string OpcodeStr,
|
||||
string Dt, ValueType ResTy, ValueType OpTy, SDNode OpNode>
|
||||
: N2VD<op24_23, op21_20, op19_18, op17_16, op11_7, op4, OpcodeStr, Dt,
|
||||
ResTy, OpTy, OpNode>;
|
||||
class N2VQX<bits<2> op24_23, bits<2> op21_20, bits<2> op19_18,
|
||||
bits<2> op17_16, bits<5> op11_7, bit op4, string OpcodeStr,
|
||||
string Dt, ValueType ResTy, ValueType OpTy, SDNode OpNode>
|
||||
: N2VQ<op24_23, op21_20, op19_18, op17_16, op11_7, op4, OpcodeStr, Dt,
|
||||
ResTy, OpTy, OpNode>;
|
||||
}
|
||||
|
||||
// VCVT : Vector Convert Between Floating-Point and Integers
|
||||
def VCVTf2sd : N2VDX<0b11, 0b11, 0b10, 0b11, 0b01110, 0, "vcvt", "s32.f32",
|
||||
v2i32, v2f32, fp_to_sint>;
|
||||
def VCVTf2ud : N2VDX<0b11, 0b11, 0b10, 0b11, 0b01111, 0, "vcvt", "u32.f32",
|
||||
v2i32, v2f32, fp_to_uint>;
|
||||
def VCVTs2fd : N2VDX<0b11, 0b11, 0b10, 0b11, 0b01100, 0, "vcvt", "f32.s32",
|
||||
v2f32, v2i32, sint_to_fp>;
|
||||
def VCVTu2fd : N2VDX<0b11, 0b11, 0b10, 0b11, 0b01101, 0, "vcvt", "f32.u32",
|
||||
v2f32, v2i32, uint_to_fp>;
|
||||
def VCVTf2sd : N2VD<0b11, 0b11, 0b10, 0b11, 0b01110, 0, "vcvt", "s32.f32",
|
||||
v2i32, v2f32, fp_to_sint>;
|
||||
def VCVTf2ud : N2VD<0b11, 0b11, 0b10, 0b11, 0b01111, 0, "vcvt", "u32.f32",
|
||||
v2i32, v2f32, fp_to_uint>;
|
||||
def VCVTs2fd : N2VD<0b11, 0b11, 0b10, 0b11, 0b01100, 0, "vcvt", "f32.s32",
|
||||
v2f32, v2i32, sint_to_fp>;
|
||||
def VCVTu2fd : N2VD<0b11, 0b11, 0b10, 0b11, 0b01101, 0, "vcvt", "f32.u32",
|
||||
v2f32, v2i32, uint_to_fp>;
|
||||
|
||||
def VCVTf2sq : N2VQX<0b11, 0b11, 0b10, 0b11, 0b01110, 0, "vcvt", "s32.f32",
|
||||
v4i32, v4f32, fp_to_sint>;
|
||||
def VCVTf2uq : N2VQX<0b11, 0b11, 0b10, 0b11, 0b01111, 0, "vcvt", "u32.f32",
|
||||
v4i32, v4f32, fp_to_uint>;
|
||||
def VCVTs2fq : N2VQX<0b11, 0b11, 0b10, 0b11, 0b01100, 0, "vcvt", "f32.s32",
|
||||
v4f32, v4i32, sint_to_fp>;
|
||||
def VCVTu2fq : N2VQX<0b11, 0b11, 0b10, 0b11, 0b01101, 0, "vcvt", "f32.u32",
|
||||
v4f32, v4i32, uint_to_fp>;
|
||||
def VCVTf2sq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01110, 0, "vcvt", "s32.f32",
|
||||
v4i32, v4f32, fp_to_sint>;
|
||||
def VCVTf2uq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01111, 0, "vcvt", "u32.f32",
|
||||
v4i32, v4f32, fp_to_uint>;
|
||||
def VCVTs2fq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01100, 0, "vcvt", "f32.s32",
|
||||
v4f32, v4i32, sint_to_fp>;
|
||||
def VCVTu2fq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01101, 0, "vcvt", "f32.u32",
|
||||
v4f32, v4i32, uint_to_fp>;
|
||||
|
||||
// VCVT : Vector Convert Between Floating-Point and Fixed-Point.
|
||||
def VCVTf2xsd : N2VCvtD<0, 1, 0b1111, 0, 1, "vcvt", "s32.f32",
|
||||
@ -3263,8 +2945,6 @@ def VREV16q8 : VREV16Q<0b00, "vrev16", "8", v16i8>;
|
||||
|
||||
// VEXT : Vector Extract
|
||||
|
||||
let NSF = NVdVnVmImmVectorExtractFrm,
|
||||
NSForm = NVdVnVmImmVectorExtractFrm.Value in {
|
||||
class VEXTd<string OpcodeStr, string Dt, ValueType Ty>
|
||||
: N3V<0,1,0b11,{?,?,?,?},0,0, (outs DPR:$dst),
|
||||
(ins DPR:$lhs, DPR:$rhs, i32imm:$index), IIC_VEXTD,
|
||||
@ -3278,7 +2958,6 @@ class VEXTq<string OpcodeStr, string Dt, ValueType Ty>
|
||||
OpcodeStr, Dt, "$dst, $lhs, $rhs, $index", "",
|
||||
[(set QPR:$dst, (Ty (NEONvext (Ty QPR:$lhs),
|
||||
(Ty QPR:$rhs), imm:$index)))]>;
|
||||
}
|
||||
|
||||
def VEXTd8 : VEXTd<"vext", "8", v8i8>;
|
||||
def VEXTd16 : VEXTd<"vext", "16", v4i16>;
|
||||
@ -3322,8 +3001,6 @@ def VZIPq32 : N2VQShuffle<0b10, 0b00011, IIC_VPERMQ3, "vzip", "32">;
|
||||
|
||||
// Vector Table Lookup and Table Extension.
|
||||
|
||||
let NSF = VTBLFrm, NSForm = VTBLFrm.Value in {
|
||||
|
||||
// VTBL : Vector Table Lookup
|
||||
def VTBL1
|
||||
: N3V<1,1,0b11,0b1000,0,0, (outs DPR:$dst),
|
||||
@ -3380,8 +3057,6 @@ def VTBX4
|
||||
DPR:$tbl2, DPR:$tbl3, DPR:$tbl4, DPR:$src)))]>;
|
||||
} // hasExtraSrcRegAllocReq = 1
|
||||
|
||||
} // End of "let NSF = VTBLFrm, ..."
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// NEON instructions for single-precision FP math
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -120,7 +120,7 @@ namespace {
|
||||
void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum);
|
||||
void printT2AddrModeImm8s4Operand(const MachineInstr *MI, int OpNum);
|
||||
void printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, int OpNum);
|
||||
void printT2AddrModeImm8s4OffsetOperand(const MachineInstr *MI, int OpNum);
|
||||
void printT2AddrModeImm8s4OffsetOperand(const MachineInstr *MI, int OpNum) {}
|
||||
void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum);
|
||||
|
||||
void printCPSOptionOperand(const MachineInstr *MI, int OpNum) {}
|
||||
@ -431,16 +431,16 @@ void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) {
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
|
||||
if (!MO2.getReg()) {
|
||||
if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
|
||||
if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
|
||||
O << ", #"
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
|
||||
<< (char)ARM_AM::getAM2Op(MO3.getImm())
|
||||
<< ARM_AM::getAM2Offset(MO3.getImm());
|
||||
O << "]";
|
||||
return;
|
||||
}
|
||||
|
||||
O << ", "
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
|
||||
<< (char)ARM_AM::getAM2Op(MO3.getImm())
|
||||
<< getRegisterName(MO2.getReg());
|
||||
|
||||
if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
|
||||
@ -458,12 +458,12 @@ void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){
|
||||
unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
|
||||
assert(ImmOffs && "Malformed indexed load / store!");
|
||||
O << "#"
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
|
||||
<< (char)ARM_AM::getAM2Op(MO2.getImm())
|
||||
<< ImmOffs;
|
||||
return;
|
||||
}
|
||||
|
||||
O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
|
||||
O << (char)ARM_AM::getAM2Op(MO2.getImm())
|
||||
<< getRegisterName(MO1.getReg());
|
||||
|
||||
if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
|
||||
@ -490,7 +490,7 @@ void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op) {
|
||||
|
||||
if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
|
||||
O << ", #"
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
|
||||
<< (char)ARM_AM::getAM3Op(MO3.getImm())
|
||||
<< ImmOffs;
|
||||
O << "]";
|
||||
}
|
||||
@ -508,7 +508,7 @@ void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){
|
||||
unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
|
||||
assert(ImmOffs && "Malformed indexed load / store!");
|
||||
O << "#"
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
|
||||
<< (char)ARM_AM::getAM3Op(MO2.getImm())
|
||||
<< ImmOffs;
|
||||
}
|
||||
|
||||
@ -558,7 +558,7 @@ void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op,
|
||||
|
||||
if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
|
||||
O << ", #"
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
|
||||
<< (char)ARM_AM::getAM5Op(MO2.getImm())
|
||||
<< ImmOffs*4;
|
||||
}
|
||||
O << "]";
|
||||
@ -594,7 +594,7 @@ void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op,
|
||||
|
||||
const MachineOperand &MO1 = MI->getOperand(Op);
|
||||
assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
|
||||
O << "[pc, " << getRegisterName(MO1.getReg()) << "]";
|
||||
O << "[pc, +" << getRegisterName(MO1.getReg()) << "]";
|
||||
}
|
||||
|
||||
void
|
||||
@ -617,11 +617,10 @@ void
|
||||
ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op) {
|
||||
// (3 - the number of trailing zeros) is the number of then / else.
|
||||
unsigned Mask = MI->getOperand(Op).getImm();
|
||||
unsigned CondBit0 = Mask >> 4 & 1;
|
||||
unsigned NumTZ = CountTrailingZeros_32(Mask);
|
||||
assert(NumTZ <= 3 && "Invalid IT mask!");
|
||||
for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
|
||||
bool T = ((Mask >> Pos) & 1) == CondBit0;
|
||||
bool T = (Mask & (1 << Pos)) == 0;
|
||||
if (T)
|
||||
O << 't';
|
||||
else
|
||||
@ -653,7 +652,7 @@ ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op,
|
||||
if (MO3.getReg())
|
||||
O << ", " << getRegisterName(MO3.getReg());
|
||||
else if (unsigned ImmOffs = MO2.getImm())
|
||||
O << ", #" << ImmOffs * Scale;
|
||||
O << ", #+" << ImmOffs * Scale;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
@ -675,7 +674,7 @@ void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) {
|
||||
const MachineOperand &MO2 = MI->getOperand(Op+1);
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
if (unsigned ImmOffs = MO2.getImm())
|
||||
O << ", #" << ImmOffs*4;
|
||||
O << ", #+" << ImmOffs*4;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
@ -711,7 +710,7 @@ void ARMAsmPrinter::printT2AddrModeImm12Operand(const MachineInstr *MI,
|
||||
|
||||
unsigned OffImm = MO2.getImm();
|
||||
if (OffImm) // Don't print +0.
|
||||
O << ", #" << OffImm;
|
||||
O << ", #+" << OffImm;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
@ -727,7 +726,7 @@ void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI,
|
||||
if (OffImm < 0)
|
||||
O << ", #-" << -OffImm;
|
||||
else if (OffImm > 0)
|
||||
O << ", #" << OffImm;
|
||||
O << ", #+" << OffImm;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
@ -743,7 +742,7 @@ void ARMAsmPrinter::printT2AddrModeImm8s4Operand(const MachineInstr *MI,
|
||||
if (OffImm < 0)
|
||||
O << ", #-" << -OffImm * 4;
|
||||
else if (OffImm > 0)
|
||||
O << ", #" << OffImm * 4;
|
||||
O << ", #+" << OffImm * 4;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
@ -755,18 +754,7 @@ void ARMAsmPrinter::printT2AddrModeImm8OffsetOperand(const MachineInstr *MI,
|
||||
if (OffImm < 0)
|
||||
O << "#-" << -OffImm;
|
||||
else if (OffImm > 0)
|
||||
O << "#" << OffImm;
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::printT2AddrModeImm8s4OffsetOperand(const MachineInstr *MI,
|
||||
int OpNum) {
|
||||
const MachineOperand &MO1 = MI->getOperand(OpNum);
|
||||
int32_t OffImm = (int32_t)MO1.getImm() / 4;
|
||||
// Don't print +0.
|
||||
if (OffImm < 0)
|
||||
O << "#-" << -OffImm * 4;
|
||||
else if (OffImm > 0)
|
||||
O << "#" << OffImm * 4;
|
||||
O << "#+" << OffImm;
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI,
|
||||
|
@ -28,165 +28,7 @@ using namespace llvm;
|
||||
#undef MachineInstr
|
||||
#undef ARMAsmPrinter
|
||||
|
||||
static unsigned NextReg(unsigned Reg) {
|
||||
switch (Reg) {
|
||||
case ARM::D0:
|
||||
return ARM::D1;
|
||||
case ARM::D1:
|
||||
return ARM::D2;
|
||||
case ARM::D2:
|
||||
return ARM::D3;
|
||||
case ARM::D3:
|
||||
return ARM::D4;
|
||||
case ARM::D4:
|
||||
return ARM::D5;
|
||||
case ARM::D5:
|
||||
return ARM::D6;
|
||||
case ARM::D6:
|
||||
return ARM::D7;
|
||||
case ARM::D7:
|
||||
return ARM::D8;
|
||||
case ARM::D8:
|
||||
return ARM::D9;
|
||||
case ARM::D9:
|
||||
return ARM::D10;
|
||||
case ARM::D10:
|
||||
return ARM::D11;
|
||||
case ARM::D11:
|
||||
return ARM::D12;
|
||||
case ARM::D12:
|
||||
return ARM::D13;
|
||||
case ARM::D13:
|
||||
return ARM::D14;
|
||||
case ARM::D14:
|
||||
return ARM::D15;
|
||||
case ARM::D15:
|
||||
return ARM::D16;
|
||||
case ARM::D16:
|
||||
return ARM::D17;
|
||||
case ARM::D17:
|
||||
return ARM::D18;
|
||||
case ARM::D18:
|
||||
return ARM::D19;
|
||||
case ARM::D19:
|
||||
return ARM::D20;
|
||||
case ARM::D20:
|
||||
return ARM::D21;
|
||||
case ARM::D21:
|
||||
return ARM::D22;
|
||||
case ARM::D22:
|
||||
return ARM::D23;
|
||||
case ARM::D23:
|
||||
return ARM::D24;
|
||||
case ARM::D24:
|
||||
return ARM::D25;
|
||||
case ARM::D25:
|
||||
return ARM::D26;
|
||||
case ARM::D26:
|
||||
return ARM::D27;
|
||||
case ARM::D27:
|
||||
return ARM::D28;
|
||||
case ARM::D28:
|
||||
return ARM::D29;
|
||||
case ARM::D29:
|
||||
return ARM::D30;
|
||||
case ARM::D30:
|
||||
return ARM::D31;
|
||||
|
||||
default:
|
||||
assert(0 && "Unexpected register enum");
|
||||
}
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printInst(const MCInst *MI) {
|
||||
// Check for MOVs and print canonical forms, instead.
|
||||
if (MI->getOpcode() == ARM::MOVs) {
|
||||
const MCOperand &Dst = MI->getOperand(0);
|
||||
const MCOperand &MO1 = MI->getOperand(1);
|
||||
const MCOperand &MO2 = MI->getOperand(2);
|
||||
const MCOperand &MO3 = MI->getOperand(3);
|
||||
|
||||
O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
|
||||
printSBitModifierOperand(MI, 6);
|
||||
printPredicateOperand(MI, 4);
|
||||
|
||||
O << '\t' << getRegisterName(Dst.getReg())
|
||||
<< ", " << getRegisterName(MO1.getReg());
|
||||
|
||||
if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx)
|
||||
return;
|
||||
|
||||
O << ", ";
|
||||
|
||||
if (MO2.getReg()) {
|
||||
O << getRegisterName(MO2.getReg());
|
||||
assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
|
||||
} else {
|
||||
O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// A8.6.123 PUSH
|
||||
if ((MI->getOpcode() == ARM::STM || MI->getOpcode() == ARM::t2STM_UPD) &&
|
||||
MI->getOperand(0).getReg() == ARM::SP) {
|
||||
const unsigned IdxOffset = MI->getOpcode() == ARM::STM ? 0 : 1;
|
||||
const MCOperand &MO1 = MI->getOperand(IdxOffset + 1);
|
||||
if (ARM_AM::getAM4WBFlag(MO1.getImm()) &&
|
||||
ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) {
|
||||
O << '\t' << "push";
|
||||
printPredicateOperand(MI, IdxOffset + 2);
|
||||
O << '\t';
|
||||
printRegisterList(MI, IdxOffset + 4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// A8.6.122 POP
|
||||
if ((MI->getOpcode() == ARM::LDM || MI->getOpcode() == ARM::t2LDM_UPD) &&
|
||||
MI->getOperand(0).getReg() == ARM::SP) {
|
||||
const unsigned IdxOffset = MI->getOpcode() == ARM::LDM ? 0 : 1;
|
||||
const MCOperand &MO1 = MI->getOperand(IdxOffset + 1);
|
||||
if (ARM_AM::getAM4WBFlag(MO1.getImm()) &&
|
||||
ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) {
|
||||
O << '\t' << "pop";
|
||||
printPredicateOperand(MI, IdxOffset + 2);
|
||||
O << '\t';
|
||||
printRegisterList(MI, IdxOffset + 4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// A8.6.355 VPUSH
|
||||
if ((MI->getOpcode() == ARM::VSTMS || MI->getOpcode() == ARM::VSTMD) &&
|
||||
MI->getOperand(0).getReg() == ARM::SP) {
|
||||
const MCOperand &MO1 = MI->getOperand(1);
|
||||
if (ARM_AM::getAM5WBFlag(MO1.getImm()) &&
|
||||
ARM_AM::getAM5SubMode(MO1.getImm()) == ARM_AM::db) {
|
||||
O << '\t' << "vpush";
|
||||
printPredicateOperand(MI, 2);
|
||||
O << '\t';
|
||||
printRegisterList(MI, 4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// A8.6.354 VPOP
|
||||
if ((MI->getOpcode() == ARM::VLDMS || MI->getOpcode() == ARM::VLDMD) &&
|
||||
MI->getOperand(0).getReg() == ARM::SP) {
|
||||
const MCOperand &MO1 = MI->getOperand(1);
|
||||
if (ARM_AM::getAM5WBFlag(MO1.getImm()) &&
|
||||
ARM_AM::getAM5SubMode(MO1.getImm()) == ARM_AM::ia) {
|
||||
O << '\t' << "vpop";
|
||||
printPredicateOperand(MI, 2);
|
||||
O << '\t';
|
||||
printRegisterList(MI, 4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printInstruction(MI);
|
||||
}
|
||||
void ARMInstPrinter::printInst(const MCInst *MI) { printInstruction(MI); }
|
||||
|
||||
void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
const char *Modifier) {
|
||||
@ -194,9 +36,6 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
if (Op.isReg()) {
|
||||
unsigned Reg = Op.getReg();
|
||||
if (Modifier && strcmp(Modifier, "dregpair") == 0) {
|
||||
O << '{' << getRegisterName(Reg) << ", "
|
||||
<< getRegisterName(NextReg(Reg)) << '}';
|
||||
#if 0
|
||||
// FIXME: Breaks e.g. ARM/vmul.ll.
|
||||
assert(0);
|
||||
/*
|
||||
@ -205,7 +44,6 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
O << '{'
|
||||
<< getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi)
|
||||
<< '}';*/
|
||||
#endif
|
||||
} else if (Modifier && strcmp(Modifier, "lane") == 0) {
|
||||
assert(0);
|
||||
/*
|
||||
@ -218,9 +56,7 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
O << getRegisterName(Reg);
|
||||
}
|
||||
} else if (Op.isImm()) {
|
||||
bool isCallOp = Modifier && !strcmp(Modifier, "call");
|
||||
assert(isCallOp ||
|
||||
((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"));
|
||||
assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
|
||||
O << '#' << Op.getImm();
|
||||
} else {
|
||||
assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
|
||||
@ -306,17 +142,17 @@ void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op) {
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
|
||||
if (!MO2.getReg()) {
|
||||
if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
|
||||
if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
|
||||
O << ", #"
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
|
||||
<< ARM_AM::getAM2Offset(MO3.getImm());
|
||||
<< (char)ARM_AM::getAM2Op(MO3.getImm())
|
||||
<< ARM_AM::getAM2Offset(MO3.getImm());
|
||||
O << "]";
|
||||
return;
|
||||
}
|
||||
|
||||
O << ", "
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
|
||||
<< getRegisterName(MO2.getReg());
|
||||
<< (char)ARM_AM::getAM2Op(MO3.getImm())
|
||||
<< getRegisterName(MO2.getReg());
|
||||
|
||||
if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
|
||||
O << ", "
|
||||
@ -333,14 +169,11 @@ void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
|
||||
if (!MO1.getReg()) {
|
||||
unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
|
||||
assert(ImmOffs && "Malformed indexed load / store!");
|
||||
O << '#'
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
|
||||
<< ImmOffs;
|
||||
O << '#' << (char)ARM_AM::getAM2Op(MO2.getImm()) << ImmOffs;
|
||||
return;
|
||||
}
|
||||
|
||||
O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
|
||||
<< getRegisterName(MO1.getReg());
|
||||
O << (char)ARM_AM::getAM2Op(MO2.getImm()) << getRegisterName(MO1.getReg());
|
||||
|
||||
if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
|
||||
O << ", "
|
||||
@ -363,8 +196,8 @@ void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum) {
|
||||
|
||||
if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
|
||||
O << ", #"
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
|
||||
<< ImmOffs;
|
||||
<< (char)ARM_AM::getAM3Op(MO3.getImm())
|
||||
<< ImmOffs;
|
||||
O << ']';
|
||||
}
|
||||
|
||||
@ -381,9 +214,9 @@ void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
|
||||
|
||||
unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
|
||||
assert(ImmOffs && "Malformed indexed load / store!");
|
||||
O << '#'
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
|
||||
<< ImmOffs;
|
||||
O << "#"
|
||||
<< (char)ARM_AM::getAM3Op(MO2.getImm())
|
||||
<< ImmOffs;
|
||||
}
|
||||
|
||||
|
||||
@ -431,7 +264,7 @@ void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
|
||||
|
||||
if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
|
||||
O << ", #"
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
|
||||
<< (char)ARM_AM::getAM5Op(MO2.getImm())
|
||||
<< ImmOffs*4;
|
||||
}
|
||||
O << "]";
|
||||
@ -470,56 +303,14 @@ void ARMInstPrinter::printBitfieldInvMaskImmOperand (const MCInst *MI,
|
||||
|
||||
void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum) {
|
||||
O << "{";
|
||||
for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
|
||||
if (i != OpNum) O << ", ";
|
||||
// Always skip the first operand, it's the optional (and implicit writeback).
|
||||
for (unsigned i = OpNum+1, e = MI->getNumOperands(); i != e; ++i) {
|
||||
if (i != OpNum+1) O << ", ";
|
||||
O << getRegisterName(MI->getOperand(i).getReg());
|
||||
}
|
||||
O << "}";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum) {
|
||||
const MCOperand &Op = MI->getOperand(OpNum);
|
||||
unsigned option = Op.getImm();
|
||||
unsigned mode = option & 31;
|
||||
bool changemode = option >> 5 & 1;
|
||||
unsigned AIF = option >> 6 & 7;
|
||||
unsigned imod = option >> 9 & 3;
|
||||
if (imod == 2)
|
||||
O << "ie";
|
||||
else if (imod == 3)
|
||||
O << "id";
|
||||
O << '\t';
|
||||
if (imod > 1) {
|
||||
if (AIF & 4) O << 'a';
|
||||
if (AIF & 2) O << 'i';
|
||||
if (AIF & 1) O << 'f';
|
||||
if (AIF > 0 && changemode) O << ", ";
|
||||
}
|
||||
if (changemode)
|
||||
O << '#' << mode;
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum) {
|
||||
const MCOperand &Op = MI->getOperand(OpNum);
|
||||
unsigned Mask = Op.getImm();
|
||||
if (Mask) {
|
||||
O << '_';
|
||||
if (Mask & 8) O << 'f';
|
||||
if (Mask & 4) O << 's';
|
||||
if (Mask & 2) O << 'x';
|
||||
if (Mask & 1) O << 'c';
|
||||
}
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum){
|
||||
const MCOperand &Op = MI->getOperand(OpNum);
|
||||
O << '#';
|
||||
if (Op.getImm() < 0)
|
||||
O << '-' << (-Op.getImm() - 1);
|
||||
else
|
||||
O << Op.getImm();
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum) {
|
||||
ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
|
||||
if (CC != ARMCC::AL)
|
||||
@ -561,191 +352,3 @@ void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum) {
|
||||
void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum) {
|
||||
O << "#" << MI->getOperand(OpNum).getImm() * 4;
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum) {
|
||||
// (3 - the number of trailing zeros) is the number of then / else.
|
||||
unsigned Mask = MI->getOperand(OpNum).getImm();
|
||||
unsigned CondBit0 = Mask >> 4 & 1;
|
||||
unsigned NumTZ = CountTrailingZeros_32(Mask);
|
||||
assert(NumTZ <= 3 && "Invalid IT mask!");
|
||||
for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
|
||||
bool T = ((Mask >> Pos) & 1) == CondBit0;
|
||||
if (T)
|
||||
O << 't';
|
||||
else
|
||||
O << 'e';
|
||||
}
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op)
|
||||
{
|
||||
const MCOperand &MO1 = MI->getOperand(Op);
|
||||
const MCOperand &MO2 = MI->getOperand(Op+1);
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
O << ", " << getRegisterName(MO2.getReg()) << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op,
|
||||
unsigned Scale) {
|
||||
const MCOperand &MO1 = MI->getOperand(Op);
|
||||
const MCOperand &MO2 = MI->getOperand(Op+1);
|
||||
const MCOperand &MO3 = MI->getOperand(Op+2);
|
||||
|
||||
if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
|
||||
printOperand(MI, Op);
|
||||
return;
|
||||
}
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
if (MO3.getReg())
|
||||
O << ", " << getRegisterName(MO3.getReg());
|
||||
else if (unsigned ImmOffs = MO2.getImm())
|
||||
O << ", #" << ImmOffs * Scale;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op)
|
||||
{
|
||||
printThumbAddrModeRI5Operand(MI, Op, 1);
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op)
|
||||
{
|
||||
printThumbAddrModeRI5Operand(MI, Op, 2);
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op)
|
||||
{
|
||||
printThumbAddrModeRI5Operand(MI, Op, 4);
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI,unsigned Op) {
|
||||
const MCOperand &MO1 = MI->getOperand(Op);
|
||||
const MCOperand &MO2 = MI->getOperand(Op+1);
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
if (unsigned ImmOffs = MO2.getImm())
|
||||
O << ", #" << ImmOffs*4;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum) {
|
||||
O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg());
|
||||
if (MI->getOpcode() == ARM::t2TBH)
|
||||
O << ", lsl #1";
|
||||
O << ']';
|
||||
}
|
||||
|
||||
// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
|
||||
// register with shift forms.
|
||||
// REG 0 0 - e.g. R5
|
||||
// REG IMM, SH_OPC - e.g. R5, LSL #3
|
||||
void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
|
||||
unsigned Reg = MO1.getReg();
|
||||
O << getRegisterName(Reg);
|
||||
|
||||
// Print the shift opc.
|
||||
O << ", "
|
||||
<< ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()))
|
||||
<< " ";
|
||||
|
||||
assert(MO2.isImm() && "Not a valid t2_so_reg value!");
|
||||
O << "#" << ARM_AM::getSORegOffset(MO2.getImm());
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printT2AddrModeImm12Operand(const MCInst *MI,
|
||||
unsigned OpNum) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
|
||||
unsigned OffImm = MO2.getImm();
|
||||
if (OffImm) // Don't print +0.
|
||||
O << ", #" << OffImm;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
|
||||
unsigned OpNum) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
|
||||
int32_t OffImm = (int32_t)MO2.getImm();
|
||||
// Don't print +0.
|
||||
if (OffImm < 0)
|
||||
O << ", #-" << -OffImm;
|
||||
else if (OffImm > 0)
|
||||
O << ", #" << OffImm;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
|
||||
unsigned OpNum) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
|
||||
int32_t OffImm = (int32_t)MO2.getImm() / 4;
|
||||
// Don't print +0.
|
||||
if (OffImm < 0)
|
||||
O << ", #-" << -OffImm * 4;
|
||||
else if (OffImm > 0)
|
||||
O << ", #" << OffImm * 4;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
|
||||
unsigned OpNum) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
int32_t OffImm = (int32_t)MO1.getImm();
|
||||
// Don't print +0.
|
||||
if (OffImm < 0)
|
||||
O << "#-" << -OffImm;
|
||||
else if (OffImm > 0)
|
||||
O << "#" << OffImm;
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
|
||||
unsigned OpNum) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
int32_t OffImm = (int32_t)MO1.getImm() / 4;
|
||||
// Don't print +0.
|
||||
if (OffImm < 0)
|
||||
O << "#-" << -OffImm * 4;
|
||||
else if (OffImm > 0)
|
||||
O << "#" << OffImm * 4;
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
|
||||
unsigned OpNum) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
const MCOperand &MO3 = MI->getOperand(OpNum+2);
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
|
||||
assert(MO2.getReg() && "Invalid so_reg load / store address!");
|
||||
O << ", " << getRegisterName(MO2.getReg());
|
||||
|
||||
unsigned ShAmt = MO3.getImm();
|
||||
if (ShAmt) {
|
||||
assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
|
||||
O << ", lsl #" << ShAmt;
|
||||
}
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum) {
|
||||
O << '#' << MI->getOperand(OpNum).getImm();
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum) {
|
||||
O << '#' << MI->getOperand(OpNum).getImm();
|
||||
}
|
||||
|
||||
|
@ -54,26 +54,26 @@ public:
|
||||
void printBitfieldInvMaskImmOperand(const MCInst *MI, unsigned OpNum);
|
||||
|
||||
void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printThumbITMask(const MCInst *MI, unsigned OpNum);
|
||||
void printThumbAddrModeRROperand(const MCInst *MI, unsigned OpNum);
|
||||
void printThumbITMask(const MCInst *MI, unsigned OpNum) {}
|
||||
void printThumbAddrModeRROperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printThumbAddrModeRI5Operand(const MCInst *MI, unsigned OpNum,
|
||||
unsigned Scale);
|
||||
void printThumbAddrModeS1Operand(const MCInst *MI, unsigned OpNum);
|
||||
void printThumbAddrModeS2Operand(const MCInst *MI, unsigned OpNum);
|
||||
void printThumbAddrModeS4Operand(const MCInst *MI, unsigned OpNum);
|
||||
void printThumbAddrModeSPOperand(const MCInst *MI, unsigned OpNum);
|
||||
unsigned Scale) {}
|
||||
void printThumbAddrModeS1Operand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printThumbAddrModeS2Operand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printThumbAddrModeS4Operand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printThumbAddrModeSPOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
|
||||
void printT2SOOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printT2AddrModeImm12Operand(const MCInst *MI, unsigned OpNum);
|
||||
void printT2AddrModeImm8Operand(const MCInst *MI, unsigned OpNum);
|
||||
void printT2AddrModeImm8s4Operand(const MCInst *MI, unsigned OpNum);
|
||||
void printT2AddrModeImm8OffsetOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printT2AddrModeSoRegOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printT2SOOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printT2AddrModeImm12Operand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printT2AddrModeImm8Operand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printT2AddrModeImm8s4Operand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printT2AddrModeImm8OffsetOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printT2AddrModeSoRegOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
|
||||
void printCPSOptionOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printMSRMaskOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printNegZeroOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printCPSOptionOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printMSRMaskOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printNegZeroOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printPredicateOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printMandatoryPredicateOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printSBitModifierOperand(const MCInst *MI, unsigned OpNum);
|
||||
@ -82,10 +82,10 @@ public:
|
||||
const char *Modifier);
|
||||
void printJTBlockOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printJT2BlockOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printTBAddrMode(const MCInst *MI, unsigned OpNum);
|
||||
void printTBAddrMode(const MCInst *MI, unsigned OpNum) {}
|
||||
void printNoHashImmediate(const MCInst *MI, unsigned OpNum);
|
||||
void printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printVFPf32ImmOperand(const MCInst *MI, int OpNum) {}
|
||||
void printVFPf64ImmOperand(const MCInst *MI, int OpNum) {}
|
||||
void printHex8ImmOperand(const MCInst *MI, int OpNum) {}
|
||||
void printHex16ImmOperand(const MCInst *MI, int OpNum) {}
|
||||
void printHex32ImmOperand(const MCInst *MI, int OpNum) {}
|
||||
|
@ -1,513 +0,0 @@
|
||||
//===- ARMDisassembler.cpp - Disassembler for ARM/Thumb ISA ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is part of the ARM Disassembler.
|
||||
// It contains code to translate the data produced by the decoder into MCInsts.
|
||||
// Documentation for the disassembler can be found in ARMDisassembler.h.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "arm-disassembler"
|
||||
|
||||
#include "ARMDisassembler.h"
|
||||
#include "ARMDisassemblerCore.h"
|
||||
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/Target/TargetRegistry.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/MemoryObject.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
/// ARMDisassemblerTables.inc - ARMDisassemblerTables.inc is tblgen'ed from
|
||||
/// RISCDisassemblerEmitter.cpp TableGen backend. It contains:
|
||||
///
|
||||
/// o Mappings from opcode to ARM/Thumb instruction format
|
||||
///
|
||||
/// o static uint16_t decodeInstruction(uint32_t insn) - the decoding function
|
||||
/// for an ARM instruction.
|
||||
///
|
||||
/// o static uint16_t decodeThumbInstruction(field_t insn) - the decoding
|
||||
/// function for a Thumb instruction.
|
||||
///
|
||||
#include "../ARMGenDisassemblerTables.inc"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace ARMDisassembler {
|
||||
|
||||
/// showBitVector - Use the raw_ostream to log a diagnostic message describing
|
||||
/// the inidividual bits of the instruction. This is a sample output:
|
||||
///
|
||||
/// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
/// -------------------------------------------------------------------------------------------------
|
||||
/// | 1: 0: 1: 0| 1: 0: 1: 0| 1: 0: 1: 0| 1: 0: 1: 0| 1: 0: 1: 0| 1: 0: 1: 0| 1: 0: 1: 0| 1: 0: 1: 0|
|
||||
/// -------------------------------------------------------------------------------------------------
|
||||
///
|
||||
static inline void showBitVector(raw_ostream &os, const uint32_t &insn) {
|
||||
os << " 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 \n";
|
||||
os << "-------------------------------------------------------------------------------------------------\n";
|
||||
os << '|';
|
||||
for (unsigned i = 32; i != 0; --i) {
|
||||
if (insn >> (i - 1) & 0x01)
|
||||
os << " 1";
|
||||
else
|
||||
os << " 0";
|
||||
os << (i%4 == 1 ? '|' : ':');
|
||||
}
|
||||
os << '\n';
|
||||
os << "-------------------------------------------------------------------------------------------------\n";
|
||||
os << '\n';
|
||||
}
|
||||
|
||||
/// decodeARMInstruction is a decorator function which tries special cases of
|
||||
/// instruction matching before calling the auto-generated decoder function.
|
||||
static unsigned decodeARMInstruction(uint32_t &insn) {
|
||||
if (slice(insn, 31, 28) == 15)
|
||||
goto AutoGenedDecoder;
|
||||
|
||||
// Special case processing, if any, goes here....
|
||||
|
||||
// LLVM combines the offset mode of A8.6.197 & A8.6.198 into STRB.
|
||||
// The insufficient encoding information of the combined instruction confuses
|
||||
// the decoder wrt BFC/BFI. Therefore, we try to recover here.
|
||||
// For BFC, Inst{27-21} = 0b0111110 & Inst{6-0} = 0b0011111.
|
||||
// For BFI, Inst{27-21} = 0b0111110 & Inst{6-4} = 0b001 & Inst{3-0} =! 0b1111.
|
||||
if (slice(insn, 27, 21) == 0x3e && slice(insn, 6, 4) == 1) {
|
||||
if (slice(insn, 3, 0) == 15)
|
||||
return ARM::BFC;
|
||||
else
|
||||
return ARM::BFI;
|
||||
}
|
||||
|
||||
// Ditto for ADDSrs, which is a super-instruction for A8.6.7 & A8.6.8.
|
||||
// As a result, the decoder fails to decode UMULL properly.
|
||||
if (slice(insn, 27, 21) == 0x04 && slice(insn, 7, 4) == 9) {
|
||||
return ARM::UMULL;
|
||||
}
|
||||
|
||||
// Ditto for STR_PRE, which is a super-instruction for A8.6.194 & A8.6.195.
|
||||
// As a result, the decoder fails to decode SBFX properly.
|
||||
if (slice(insn, 27, 21) == 0x3d && slice(insn, 6, 4) == 5)
|
||||
return ARM::SBFX;
|
||||
|
||||
// And STRB_PRE, which is a super-instruction for A8.6.197 & A8.6.198.
|
||||
// As a result, the decoder fails to decode UBFX properly.
|
||||
if (slice(insn, 27, 21) == 0x3f && slice(insn, 6, 4) == 5)
|
||||
return ARM::UBFX;
|
||||
|
||||
// Ditto for STRT, which is a super-instruction for A8.6.210 Encoding A1 & A2.
|
||||
// As a result, the decoder fails to deocode SSAT properly.
|
||||
if (slice(insn, 27, 21) == 0x35 && slice(insn, 5, 4) == 1)
|
||||
return slice(insn, 6, 6) == 0 ? ARM::SSATlsl : ARM::SSATasr;
|
||||
|
||||
// Ditto for RSCrs, which is a super-instruction for A8.6.146 & A8.6.147.
|
||||
// As a result, the decoder fails to decode STRHT/LDRHT/LDRSHT/LDRSBT.
|
||||
if (slice(insn, 27, 24) == 0) {
|
||||
switch (slice(insn, 21, 20)) {
|
||||
case 2:
|
||||
switch (slice(insn, 7, 4)) {
|
||||
case 11:
|
||||
return ARM::STRHT;
|
||||
default:
|
||||
break; // fallthrough
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
switch (slice(insn, 7, 4)) {
|
||||
case 11:
|
||||
return ARM::LDRHT;
|
||||
case 13:
|
||||
return ARM::LDRSBT;
|
||||
case 15:
|
||||
return ARM::LDRSHT;
|
||||
default:
|
||||
break; // fallthrough
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break; // fallthrough
|
||||
}
|
||||
}
|
||||
|
||||
// Ditto for SBCrs, which is a super-instruction for A8.6.152 & A8.6.153.
|
||||
// As a result, the decoder fails to decode STRH_Post/LDRD_POST/STRD_POST
|
||||
// properly.
|
||||
if (slice(insn, 27, 25) == 0 && slice(insn, 20, 20) == 0) {
|
||||
unsigned PW = slice(insn, 24, 24) << 1 | slice(insn, 21, 21);
|
||||
switch (slice(insn, 7, 4)) {
|
||||
case 11:
|
||||
switch (PW) {
|
||||
case 2: // Offset
|
||||
return ARM::STRH;
|
||||
case 3: // Pre-indexed
|
||||
return ARM::STRH_PRE;
|
||||
case 0: // Post-indexed
|
||||
return ARM::STRH_POST;
|
||||
default:
|
||||
break; // fallthrough
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
switch (PW) {
|
||||
case 2: // Offset
|
||||
return ARM::LDRD;
|
||||
case 3: // Pre-indexed
|
||||
return ARM::LDRD_PRE;
|
||||
case 0: // Post-indexed
|
||||
return ARM::LDRD_POST;
|
||||
default:
|
||||
break; // fallthrough
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
switch (PW) {
|
||||
case 2: // Offset
|
||||
return ARM::STRD;
|
||||
case 3: // Pre-indexed
|
||||
return ARM::STRD_PRE;
|
||||
case 0: // Post-indexed
|
||||
return ARM::STRD_POST;
|
||||
default:
|
||||
break; // fallthrough
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break; // fallthrough
|
||||
}
|
||||
}
|
||||
|
||||
// Ditto for SBCSSrs, which is a super-instruction for A8.6.152 & A8.6.153.
|
||||
// As a result, the decoder fails to decode LDRH_POST/LDRSB_POST/LDRSH_POST
|
||||
// properly.
|
||||
if (slice(insn, 27, 25) == 0 && slice(insn, 20, 20) == 1) {
|
||||
unsigned PW = slice(insn, 24, 24) << 1 | slice(insn, 21, 21);
|
||||
switch (slice(insn, 7, 4)) {
|
||||
case 11:
|
||||
switch (PW) {
|
||||
case 2: // Offset
|
||||
return ARM::LDRH;
|
||||
case 3: // Pre-indexed
|
||||
return ARM::LDRH_PRE;
|
||||
case 0: // Post-indexed
|
||||
return ARM::LDRH_POST;
|
||||
default:
|
||||
break; // fallthrough
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
switch (PW) {
|
||||
case 2: // Offset
|
||||
return ARM::LDRSB;
|
||||
case 3: // Pre-indexed
|
||||
return ARM::LDRSB_PRE;
|
||||
case 0: // Post-indexed
|
||||
return ARM::LDRSB_POST;
|
||||
default:
|
||||
break; // fallthrough
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
switch (PW) {
|
||||
case 2: // Offset
|
||||
return ARM::LDRSH;
|
||||
case 3: // Pre-indexed
|
||||
return ARM::LDRSH_PRE;
|
||||
case 0: // Post-indexed
|
||||
return ARM::LDRSH_POST;
|
||||
default:
|
||||
break; // fallthrough
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break; // fallthrough
|
||||
}
|
||||
}
|
||||
|
||||
AutoGenedDecoder:
|
||||
// Calling the auto-generated decoder function.
|
||||
return decodeInstruction(insn);
|
||||
}
|
||||
|
||||
// Helper function for special case handling of LDR (literal) and friends.
|
||||
// See, for example, A6.3.7 Load word: Table A6-18 Load word.
|
||||
// See A8.6.57 T3, T4 & A8.6.60 T2 and friends for why we morphed the opcode
|
||||
// before passing it on.
|
||||
static unsigned T2Morph2LoadLiteral(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
default:
|
||||
return Opcode; // Return unmorphed opcode.
|
||||
|
||||
case ARM::t2LDRDi8:
|
||||
return ARM::t2LDRDpci;
|
||||
|
||||
case ARM::t2LDR_POST: case ARM::t2LDR_PRE:
|
||||
case ARM::t2LDRi12: case ARM::t2LDRi8:
|
||||
case ARM::t2LDRs:
|
||||
return ARM::t2LDRpci;
|
||||
|
||||
case ARM::t2LDRB_POST: case ARM::t2LDRB_PRE:
|
||||
case ARM::t2LDRBi12: case ARM::t2LDRBi8:
|
||||
case ARM::t2LDRBs:
|
||||
return ARM::t2LDRBpci;
|
||||
|
||||
case ARM::t2LDRH_POST: case ARM::t2LDRH_PRE:
|
||||
case ARM::t2LDRHi12: case ARM::t2LDRHi8:
|
||||
case ARM::t2LDRHs:
|
||||
return ARM::t2LDRHpci;
|
||||
|
||||
case ARM::t2LDRSB_POST: case ARM::t2LDRSB_PRE:
|
||||
case ARM::t2LDRSBi12: case ARM::t2LDRSBi8:
|
||||
case ARM::t2LDRSBs:
|
||||
return ARM::t2LDRSBpci;
|
||||
|
||||
case ARM::t2LDRSH_POST: case ARM::t2LDRSH_PRE:
|
||||
case ARM::t2LDRSHi12: case ARM::t2LDRSHi8:
|
||||
case ARM::t2LDRSHs:
|
||||
return ARM::t2LDRSHpci;
|
||||
}
|
||||
}
|
||||
|
||||
/// decodeThumbSideEffect is a decorator function which can potentially twiddle
|
||||
/// the instruction or morph the returned opcode under Thumb2.
|
||||
///
|
||||
/// First it checks whether the insn is a NEON or VFP instr; if true, bit
|
||||
/// twiddling could be performed on insn to turn it into an ARM NEON/VFP
|
||||
/// equivalent instruction and decodeInstruction is called with the transformed
|
||||
/// insn.
|
||||
///
|
||||
/// Next, there is special handling for Load byte/halfword/word instruction by
|
||||
/// checking whether Rn=0b1111 and call T2Morph2LoadLiteral() on the decoded
|
||||
/// Thumb2 instruction. See comments below for further details.
|
||||
///
|
||||
/// Finally, one last check is made to see whether the insn is a NEON/VFP and
|
||||
/// decodeInstruction(insn) is invoked on the original insn.
|
||||
///
|
||||
/// Otherwise, decodeThumbInstruction is called with the original insn.
|
||||
static unsigned decodeThumbSideEffect(bool IsThumb2, uint32_t &insn) {
|
||||
if (IsThumb2) {
|
||||
uint16_t op1 = slice(insn, 28, 27);
|
||||
uint16_t op2 = slice(insn, 26, 20);
|
||||
|
||||
// A6.3 32-bit Thumb instruction encoding
|
||||
// Table A6-9 32-bit Thumb instruction encoding
|
||||
|
||||
// The coprocessor instructions of interest are transformed to their ARM
|
||||
// equivalents.
|
||||
|
||||
// --------- Transform Begin Marker ---------
|
||||
if ((op1 == 1 || op1 == 3) && slice(op2, 6, 4) == 7) {
|
||||
// A7.4 Advanced SIMD data-processing instructions
|
||||
// U bit of Thumb corresponds to Inst{24} of ARM.
|
||||
uint16_t U = slice(op1, 1, 1);
|
||||
|
||||
// Inst{28-24} of ARM = {1,0,0,1,U};
|
||||
uint16_t bits28_24 = 9 << 1 | U;
|
||||
DEBUG(showBitVector(errs(), insn));
|
||||
setSlice(insn, 28, 24, bits28_24);
|
||||
return decodeInstruction(insn);
|
||||
}
|
||||
|
||||
if (op1 == 3 && slice(op2, 6, 4) == 1 && slice(op2, 0, 0) == 0) {
|
||||
// A7.7 Advanced SIMD element or structure load/store instructions
|
||||
// Inst{27-24} of Thumb = 0b1001
|
||||
// Inst{27-24} of ARM = 0b0100
|
||||
DEBUG(showBitVector(errs(), insn));
|
||||
setSlice(insn, 27, 24, 4);
|
||||
return decodeInstruction(insn);
|
||||
}
|
||||
// --------- Transform End Marker ---------
|
||||
|
||||
// See, for example, A6.3.7 Load word: Table A6-18 Load word.
|
||||
// See A8.6.57 T3, T4 & A8.6.60 T2 and friends for why we morphed the opcode
|
||||
// before passing it on to our delegate.
|
||||
if (op1 == 3 && slice(op2, 6, 5) == 0 && slice(op2, 0, 0) == 1
|
||||
&& slice(insn, 19, 16) == 15)
|
||||
return T2Morph2LoadLiteral(decodeThumbInstruction(insn));
|
||||
|
||||
// One last check for NEON/VFP instructions.
|
||||
if ((op1 == 1 || op1 == 3) && slice(op2, 6, 6) == 1)
|
||||
return decodeInstruction(insn);
|
||||
|
||||
// Fall through.
|
||||
}
|
||||
|
||||
return decodeThumbInstruction(insn);
|
||||
}
|
||||
|
||||
static inline bool Thumb2PreloadOpcodeNoPCI(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
default:
|
||||
return false;
|
||||
case ARM::t2PLDi12: case ARM::t2PLDi8:
|
||||
case ARM::t2PLDr: case ARM::t2PLDs:
|
||||
case ARM::t2PLDWi12: case ARM::t2PLDWi8:
|
||||
case ARM::t2PLDWr: case ARM::t2PLDWs:
|
||||
case ARM::t2PLIi12: case ARM::t2PLIi8:
|
||||
case ARM::t2PLIr: case ARM::t2PLIs:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned T2Morph2Preload2PCI(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
default:
|
||||
return 0;
|
||||
case ARM::t2PLDi12: case ARM::t2PLDi8:
|
||||
case ARM::t2PLDr: case ARM::t2PLDs:
|
||||
return ARM::t2PLDpci;
|
||||
case ARM::t2PLDWi12: case ARM::t2PLDWi8:
|
||||
case ARM::t2PLDWr: case ARM::t2PLDWs:
|
||||
return ARM::t2PLDWpci;
|
||||
case ARM::t2PLIi12: case ARM::t2PLIi8:
|
||||
case ARM::t2PLIr: case ARM::t2PLIs:
|
||||
return ARM::t2PLIpci;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Public interface for the disassembler
|
||||
//
|
||||
|
||||
bool ARMDisassembler::getInstruction(MCInst &MI,
|
||||
uint64_t &Size,
|
||||
const MemoryObject &Region,
|
||||
uint64_t Address,
|
||||
raw_ostream &os) const {
|
||||
// The machine instruction.
|
||||
uint32_t insn;
|
||||
|
||||
// We want to read exactly 4 bytes of data.
|
||||
if (Region.readBytes(Address, 4, (uint8_t*)&insn, NULL) == -1)
|
||||
return false;
|
||||
|
||||
unsigned Opcode = decodeARMInstruction(insn);
|
||||
ARMFormat Format = ARMFormats[Opcode];
|
||||
NSFormat NSF = NSFormats[Opcode];
|
||||
Size = 4;
|
||||
|
||||
DEBUG({
|
||||
errs() << "Opcode=" << Opcode << " Name=" << ARMUtils::OpcodeName(Opcode)
|
||||
<< " Format=" << stringForARMFormat(Format) << " NSFormat="
|
||||
<< stringForNSFormat(NSF) << '\n';
|
||||
showBitVector(errs(), insn);
|
||||
});
|
||||
|
||||
AbstractARMMCBuilder *Builder =
|
||||
ARMMCBuilderFactory::CreateMCBuilder(Opcode, Format, NSF);
|
||||
|
||||
if (!Builder)
|
||||
return false;
|
||||
|
||||
if (!Builder->Build(MI, insn))
|
||||
return false;
|
||||
|
||||
delete Builder;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ThumbDisassembler::getInstruction(MCInst &MI,
|
||||
uint64_t &Size,
|
||||
const MemoryObject &Region,
|
||||
uint64_t Address,
|
||||
raw_ostream &os) const {
|
||||
// The machine instruction.
|
||||
uint32_t insn = 0;
|
||||
uint32_t insn1 = 0;
|
||||
|
||||
// A6.1 Thumb instruction set encoding
|
||||
//
|
||||
// If bits [15:11] of the halfword being decoded take any of the following
|
||||
// values, the halfword is the first halfword of a 32-bit instruction:
|
||||
// o 0b11101
|
||||
// o 0b11110
|
||||
// o 0b11111.
|
||||
//
|
||||
// Otherwise, the halfword is a 16-bit instruction.
|
||||
|
||||
// Read 2 bytes of data first.
|
||||
if (Region.readBytes(Address, 2, (uint8_t*)&insn, NULL) == -1)
|
||||
return false;
|
||||
|
||||
unsigned bits15_11 = slice(insn, 15, 11);
|
||||
bool IsThumb2 = false;
|
||||
|
||||
// 32-bit instructions if the bits [15:11] of the halfword matches
|
||||
// { 0b11101 /* 0x1D */, 0b11110 /* 0x1E */, ob11111 /* 0x1F */ }.
|
||||
if (bits15_11 == 0x1D || bits15_11 == 0x1E || bits15_11 == 0x1F) {
|
||||
IsThumb2 = true;
|
||||
if (Region.readBytes(Address + 2, 2, (uint8_t*)&insn1, NULL) == -1)
|
||||
return false;
|
||||
insn = (insn << 16 | insn1);
|
||||
}
|
||||
|
||||
// The insn could potentially be bit-twiddled in order to be decoded as an ARM
|
||||
// NEON/VFP opcode. In such case, the modified insn is later disassembled as
|
||||
// an ARM NEON/VFP instruction.
|
||||
//
|
||||
// This is a short term solution for lack of encoding bits specified for the
|
||||
// Thumb2 NEON/VFP instructions. The long term solution could be adding some
|
||||
// infrastructure to have each instruction support more than one encodings.
|
||||
// Which encoding is used would be based on which subtarget the compiler/
|
||||
// disassembler is working with at the time. This would allow the sharing of
|
||||
// the NEON patterns between ARM and Thumb2, as well as potential greater
|
||||
// sharing between the regular ARM instructions and the 32-bit wide Thumb2
|
||||
// instructions as well.
|
||||
unsigned Opcode = decodeThumbSideEffect(IsThumb2, insn);
|
||||
|
||||
// A8.6.117/119/120/121.
|
||||
// PLD/PLDW/PLI instructions with Rn==15 is transformed to the pci variant.
|
||||
if (Thumb2PreloadOpcodeNoPCI(Opcode) && slice(insn, 19, 16) == 15)
|
||||
Opcode = T2Morph2Preload2PCI(Opcode);
|
||||
|
||||
ARMFormat Format = ARMFormats[Opcode];
|
||||
NSFormat NSF = NSFormats[Opcode];
|
||||
Size = IsThumb2 ? 4 : 2;
|
||||
|
||||
DEBUG({
|
||||
errs() << "Opcode=" << Opcode << " Name=" << ARMUtils::OpcodeName(Opcode)
|
||||
<< " Format=" << stringForARMFormat(Format) << " NSFormat="
|
||||
<< stringForNSFormat(NSF) << '\n';
|
||||
showBitVector(errs(), insn);
|
||||
});
|
||||
|
||||
AbstractARMMCBuilder *Builder =
|
||||
ARMMCBuilderFactory::CreateMCBuilder(Opcode, Format, NSF);
|
||||
|
||||
if (!Builder)
|
||||
return false;
|
||||
|
||||
if (!Builder->Build(MI, insn))
|
||||
return false;
|
||||
|
||||
delete Builder;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ARM Disassembler
|
||||
|
||||
static const MCDisassembler *createARMDisassembler(const Target &T) {
|
||||
return new ARMDisassembler::ARMDisassembler;
|
||||
}
|
||||
|
||||
static const MCDisassembler *createThumbDisassembler(const Target &T) {
|
||||
return new ARMDisassembler::ThumbDisassembler;
|
||||
}
|
||||
|
||||
extern "C" void LLVMInitializeARMDisassembler() {
|
||||
// Register the disassembler.
|
||||
TargetRegistry::RegisterMCDisassembler(TheARMTarget,
|
||||
createARMDisassembler);
|
||||
TargetRegistry::RegisterMCDisassembler(TheThumbTarget,
|
||||
createThumbDisassembler);
|
||||
}
|
||||
|
||||
} // namespace llvm
|
@ -1,71 +0,0 @@
|
||||
//===- X86Disassembler.h - Disassembler for x86 and x86_64 ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef ARMDISASSEMBLER_H
|
||||
#define ARMDISASSEMBLER_H
|
||||
|
||||
#include "llvm/MC/MCDisassembler.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MCInst;
|
||||
class MemoryObject;
|
||||
class raw_ostream;
|
||||
|
||||
namespace ARMDisassembler {
|
||||
|
||||
/// ARMDisassembler - ARM disassembler for all ARM platforms.
|
||||
class ARMDisassembler : public MCDisassembler {
|
||||
public:
|
||||
/// Constructor - Initializes the disassembler.
|
||||
///
|
||||
ARMDisassembler() :
|
||||
MCDisassembler() {
|
||||
}
|
||||
|
||||
~ARMDisassembler() {
|
||||
}
|
||||
|
||||
/// getInstruction - See MCDisassembler.
|
||||
bool getInstruction(MCInst &instr,
|
||||
uint64_t &size,
|
||||
const MemoryObject ®ion,
|
||||
uint64_t address,
|
||||
raw_ostream &vStream) const;
|
||||
private:
|
||||
};
|
||||
|
||||
/// ThumbDisassembler - Thumb disassembler for all ARM platforms.
|
||||
class ThumbDisassembler : public MCDisassembler {
|
||||
public:
|
||||
/// Constructor - Initializes the disassembler.
|
||||
///
|
||||
ThumbDisassembler() :
|
||||
MCDisassembler() {
|
||||
}
|
||||
|
||||
~ThumbDisassembler() {
|
||||
}
|
||||
|
||||
/// getInstruction - See MCDisassembler.
|
||||
bool getInstruction(MCInst &instr,
|
||||
uint64_t &size,
|
||||
const MemoryObject ®ion,
|
||||
uint64_t address,
|
||||
raw_ostream &vStream) const;
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace ARMDisassembler
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,301 +0,0 @@
|
||||
//===- ARMDisassemblerCore.h - ARM disassembler helpers ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is part of the ARM Disassembler.
|
||||
//
|
||||
// The first part defines the enumeration type of ARM instruction format, which
|
||||
// specifies the encoding used by the instruction, as well as a helper function
|
||||
// to convert the enums to printable char strings.
|
||||
//
|
||||
// It also contains code to represent the concepts of Builder, Builder Factory,
|
||||
// as well as the Algorithm to solve the problem of disassembling an ARM instr.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef ARMDISASSEMBLERCORE_H
|
||||
#define ARMDISASSEMBLERCORE_H
|
||||
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "ARMInstrInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class ARMUtils {
|
||||
public:
|
||||
static const char *OpcodeName(unsigned Opcode);
|
||||
};
|
||||
|
||||
#define ARM_FORMATS \
|
||||
ENTRY(ARM_FORMAT_PSEUDO, 0) \
|
||||
ENTRY(ARM_FORMAT_MULFRM, 1) \
|
||||
ENTRY(ARM_FORMAT_BRFRM, 2) \
|
||||
ENTRY(ARM_FORMAT_BRMISCFRM, 3) \
|
||||
ENTRY(ARM_FORMAT_DPFRM, 4) \
|
||||
ENTRY(ARM_FORMAT_DPSOREGFRM, 5) \
|
||||
ENTRY(ARM_FORMAT_LDFRM, 6) \
|
||||
ENTRY(ARM_FORMAT_STFRM, 7) \
|
||||
ENTRY(ARM_FORMAT_LDMISCFRM, 8) \
|
||||
ENTRY(ARM_FORMAT_STMISCFRM, 9) \
|
||||
ENTRY(ARM_FORMAT_LDSTMULFRM, 10) \
|
||||
ENTRY(ARM_FORMAT_ARITHMISCFRM, 11) \
|
||||
ENTRY(ARM_FORMAT_EXTFRM, 12) \
|
||||
ENTRY(ARM_FORMAT_VFPUNARYFRM, 13) \
|
||||
ENTRY(ARM_FORMAT_VFPBINARYFRM, 14) \
|
||||
ENTRY(ARM_FORMAT_VFPCONV1FRM, 15) \
|
||||
ENTRY(ARM_FORMAT_VFPCONV2FRM, 16) \
|
||||
ENTRY(ARM_FORMAT_VFPCONV3FRM, 17) \
|
||||
ENTRY(ARM_FORMAT_VFPCONV4FRM, 18) \
|
||||
ENTRY(ARM_FORMAT_VFPCONV5FRM, 19) \
|
||||
ENTRY(ARM_FORMAT_VFPLDSTFRM, 20) \
|
||||
ENTRY(ARM_FORMAT_VFPLDSTMULFRM, 21) \
|
||||
ENTRY(ARM_FORMAT_VFPMISCFRM, 22) \
|
||||
ENTRY(ARM_FORMAT_THUMBFRM, 23) \
|
||||
ENTRY(ARM_FORMAT_NEONFRM, 24) \
|
||||
ENTRY(ARM_FORMAT_NEONGETLNFRM, 25) \
|
||||
ENTRY(ARM_FORMAT_NEONSETLNFRM, 26) \
|
||||
ENTRY(ARM_FORMAT_NEONDUPFRM, 27) \
|
||||
ENTRY(ARM_FORMAT_LDSTEXFRM, 28) \
|
||||
ENTRY(ARM_FORMAT_MISCFRM, 29) \
|
||||
ENTRY(ARM_FORMAT_THUMBMISCFRM, 30)
|
||||
|
||||
// ARM instruction format specifies the encoding used by the instruction.
|
||||
#define ENTRY(n, v) n = v,
|
||||
typedef enum {
|
||||
ARM_FORMATS
|
||||
ARM_FORMAT_NA
|
||||
} ARMFormat;
|
||||
#undef ENTRY
|
||||
|
||||
// Converts enum to const char*.
|
||||
static const inline char *stringForARMFormat(ARMFormat form) {
|
||||
#define ENTRY(n, v) case n: return #n;
|
||||
switch(form) {
|
||||
ARM_FORMATS
|
||||
case ARM_FORMAT_NA:
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
#undef ENTRY
|
||||
}
|
||||
|
||||
#define NS_FORMATS \
|
||||
ENTRY(NS_FORMAT_NONE, 0) \
|
||||
ENTRY(NS_FORMAT_VLDSTLane, 1) \
|
||||
ENTRY(NS_FORMAT_VLDSTLaneDbl, 2) \
|
||||
ENTRY(NS_FORMAT_VLDSTRQ, 3) \
|
||||
ENTRY(NS_FORMAT_NVdImm, 4) \
|
||||
ENTRY(NS_FORMAT_NVdVmImm, 5) \
|
||||
ENTRY(NS_FORMAT_NVdVmImmVCVT, 6) \
|
||||
ENTRY(NS_FORMAT_NVdVmImmVDupLane, 7) \
|
||||
ENTRY(NS_FORMAT_NVdVmImmVSHLL, 8) \
|
||||
ENTRY(NS_FORMAT_NVectorShuffle, 9) \
|
||||
ENTRY(NS_FORMAT_NVectorShift, 10) \
|
||||
ENTRY(NS_FORMAT_NVectorShift2, 11) \
|
||||
ENTRY(NS_FORMAT_NVdVnVmImm, 12) \
|
||||
ENTRY(NS_FORMAT_NVdVnVmImmVectorShift, 13) \
|
||||
ENTRY(NS_FORMAT_NVdVnVmImmVectorExtract, 14) \
|
||||
ENTRY(NS_FORMAT_NVdVnVmImmMulScalar, 15) \
|
||||
ENTRY(NS_FORMAT_VTBL, 16)
|
||||
|
||||
// NEON instruction sub-format further classify the NEONFrm instruction.
|
||||
#define ENTRY(n, v) n = v,
|
||||
typedef enum {
|
||||
NS_FORMATS
|
||||
NS_FORMAT_NA
|
||||
} NSFormat;
|
||||
#undef ENTRY
|
||||
|
||||
// Converts enum to const char*.
|
||||
static const inline char *stringForNSFormat(NSFormat form) {
|
||||
#define ENTRY(n, v) case n: return #n;
|
||||
switch(form) {
|
||||
NS_FORMATS
|
||||
case NS_FORMAT_NA:
|
||||
return "NA";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
#undef ENTRY
|
||||
}
|
||||
|
||||
/// Expands on the enum definitions from ARMBaseInstrInfo.h.
|
||||
/// They are being used by the disassembler implementation.
|
||||
namespace ARMII {
|
||||
enum {
|
||||
NEONRegMask = 15,
|
||||
GPRRegMask = 15,
|
||||
NEON_RegRdShift = 12,
|
||||
NEON_D_BitShift = 22,
|
||||
NEON_RegRnShift = 16,
|
||||
NEON_N_BitShift = 7,
|
||||
NEON_RegRmShift = 0,
|
||||
NEON_M_BitShift = 5
|
||||
};
|
||||
}
|
||||
|
||||
/// Utility function for extracting [From, To] bits from a uint32_t.
|
||||
static inline unsigned slice(uint32_t Bits, unsigned From, unsigned To) {
|
||||
assert(From < 32 && To < 32 && From >= To);
|
||||
return (Bits >> To) & ((1 << (From - To + 1)) - 1);
|
||||
}
|
||||
|
||||
/// Utility function for setting [From, To] bits to Val for a uint32_t.
|
||||
static inline void setSlice(uint32_t &Bits, unsigned From, unsigned To,
|
||||
uint32_t Val) {
|
||||
assert(From < 32 && To < 32 && From >= To);
|
||||
uint32_t Mask = ((1 << (From - To + 1)) - 1);
|
||||
Bits &= ~(Mask << To);
|
||||
Bits |= (Val & Mask) << To;
|
||||
}
|
||||
|
||||
/// Various utilities for checking the target specific flags.
|
||||
|
||||
/// A unary data processing instruction doesn't have an Rn operand.
|
||||
static inline bool isUnaryDP(unsigned TSFlags) {
|
||||
return (TSFlags & ARMII::UnaryDP);
|
||||
}
|
||||
|
||||
/// This four-bit field describes the addressing mode used.
|
||||
/// See also ARMBaseInstrInfo.h.
|
||||
static inline unsigned getAddrMode(unsigned TSFlags) {
|
||||
return (TSFlags & ARMII::AddrModeMask);
|
||||
}
|
||||
|
||||
/// {IndexModePre, IndexModePost}
|
||||
/// Only valid for load and store ops.
|
||||
/// See also ARMBaseInstrInfo.h.
|
||||
static inline unsigned getIndexMode(unsigned TSFlags) {
|
||||
return (TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
|
||||
}
|
||||
|
||||
/// Pre-/post-indexed operations define an extra $base_wb in the OutOperandList.
|
||||
static inline bool isPrePostLdSt(unsigned TSFlags) {
|
||||
return (TSFlags & ARMII::IndexModeMask) != 0;
|
||||
}
|
||||
|
||||
/// AbstractARMMCBuilder - AbstractARMMCBuilder represents an interface of ARM
|
||||
/// MCInst builder that knows how to build up the MCOperand list.
|
||||
class AbstractARMMCBuilder {
|
||||
public:
|
||||
/// Build - Build the MCInst fully and return true. Return false if any
|
||||
/// failure occurs.
|
||||
virtual bool Build(MCInst &MI, uint32_t insn) { return false; }
|
||||
};
|
||||
|
||||
/// ARMDisassemblyAlgorithm - ARMDisassemblyAlgorithm represents an interface of
|
||||
/// ARM disassembly algorithm that relies on the entries of target operand info,
|
||||
/// among other things, to solve the problem of disassembling an ARM machine
|
||||
/// instruction.
|
||||
class ARMDisassemblyAlgorithm {
|
||||
public:
|
||||
/// Return true if this algorithm successfully disassembles the instruction.
|
||||
/// NumOpsAdded is updated to reflect the number of operands added by the
|
||||
/// algorithm. NumOpsAdded may be less than NumOps, in which case, there are
|
||||
/// operands unaccounted for which need to be dealt with by the API client.
|
||||
virtual bool Solve(MCInst& MI, unsigned Opcode, uint32_t insn,
|
||||
unsigned short NumOps, unsigned &NumOpsAdded) const
|
||||
= 0;
|
||||
};
|
||||
|
||||
/// ARMBasicMCBuilder - ARMBasicMCBuilder represents a concrete subclass of
|
||||
/// ARMAbstractMCBuilder.
|
||||
class ARMBasicMCBuilder : public AbstractARMMCBuilder {
|
||||
unsigned Opcode;
|
||||
ARMFormat Format;
|
||||
NSFormat NSF;
|
||||
unsigned short NumOps;
|
||||
const ARMDisassemblyAlgorithm &Algo;
|
||||
static unsigned ITCounter; // Possible values: 0, 1, 2, 3, 4.
|
||||
static unsigned ITState; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially.
|
||||
|
||||
public:
|
||||
ARMBasicMCBuilder(ARMBasicMCBuilder &MCB) : AbstractARMMCBuilder(),
|
||||
Opcode(MCB.Opcode), Format(MCB.Format), NSF(MCB.NSF), NumOps(MCB.NumOps),
|
||||
Algo(MCB.Algo) {}
|
||||
|
||||
/// Opcode, Format, NSF, NumOperands, and Algo make an ARM Basic MCBuilder.
|
||||
ARMBasicMCBuilder(unsigned opc, ARMFormat format, NSFormat NSF,
|
||||
unsigned short num, const ARMDisassemblyAlgorithm &algo)
|
||||
: AbstractARMMCBuilder(), Opcode(opc), Format(format), NumOps(num),
|
||||
Algo(algo) {}
|
||||
|
||||
/// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process
|
||||
/// the possible Predicate and SBitModifier, to build the remaining MCOperand
|
||||
/// constituents.
|
||||
static bool TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
|
||||
uint32_t insn, unsigned short NumOpsRemaning);
|
||||
|
||||
/// InITBlock - InITBlock returns true if we are inside an IT block.
|
||||
static bool InITBlock() {
|
||||
return ITCounter > 0;
|
||||
}
|
||||
|
||||
/// Build - Build delegates to BuildIt to perform the heavy liftling. After
|
||||
/// that, it invokes RunBuildAfterHook where some housekeepings can be done.
|
||||
virtual bool Build(MCInst &MI, uint32_t insn) {
|
||||
bool Status = BuildIt(MI, insn);
|
||||
return RunBuildAfterHook(Status, MI, insn);
|
||||
}
|
||||
|
||||
/// BuildIt - BuildIt performs the build step for this ARM Basic MC Builder.
|
||||
/// The general idea is to set the Opcode for the MCInst, followed by adding
|
||||
/// the appropriate MCOperands to the MCInst. ARM Basic MC Builder delegates
|
||||
/// to the Algo (ARM Disassemble Algorithm) object to perform Format-specific
|
||||
/// disassembly, followed by class method TryPredicateAndSBitModifier() to do
|
||||
/// PredicateOperand and OptionalDefOperand which follow the Dst/Src Operands.
|
||||
virtual bool BuildIt(MCInst &MI, uint32_t insn);
|
||||
|
||||
/// RunBuildAfterHook - RunBuildAfterHook performs operations deemed necessary
|
||||
/// after BuildIt is finished.
|
||||
virtual bool RunBuildAfterHook(bool Status, MCInst &MI, uint32_t insn);
|
||||
|
||||
private:
|
||||
/// Get condition of the current IT instruction.
|
||||
static unsigned GetITCond() {
|
||||
return slice(ITState, 7, 4);
|
||||
}
|
||||
|
||||
/// Init ITState.
|
||||
static void InitITState(unsigned short bits7_0) {
|
||||
ITState = bits7_0;
|
||||
}
|
||||
|
||||
/// Update ITState if necessary.
|
||||
static void UpdateITState() {
|
||||
assert(ITCounter);
|
||||
--ITCounter;
|
||||
if (ITCounter == 0)
|
||||
ITState = 0;
|
||||
else {
|
||||
unsigned short NewITState4_0 = slice(ITState, 4, 0) << 1;
|
||||
setSlice(ITState, 4, 0, NewITState4_0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// ARMMCBuilderFactory - ARMMCBuilderFactory represents the factory class that
|
||||
/// vends out ARMAbstractMCBuilder instances through its class method.
|
||||
class ARMMCBuilderFactory {
|
||||
private:
|
||||
ARMMCBuilderFactory(); // DO NOT IMPLEMENT.
|
||||
|
||||
public:
|
||||
/// CreateMCBuilder - Return an AbstractARMMCBuilder that can build up the MC
|
||||
/// infrastructure of an MCInst given the Opcode and Format of the instr.
|
||||
/// Return NULL if it fails to create/return a proper builder. API clients
|
||||
/// are responsible for freeing up of the allocated memory. Cacheing can be
|
||||
/// performed by the API clients to improve performance.
|
||||
static AbstractARMMCBuilder *CreateMCBuilder(unsigned Opcode,
|
||||
ARMFormat Format, NSFormat NSF);
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
@ -1,17 +0,0 @@
|
||||
##===- lib/Target/ARM/Disassembler/Makefile ----------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL = ../../../..
|
||||
LIBRARYNAME = LLVMARMDisassembler
|
||||
CXXFLAGS = -fno-rtti
|
||||
|
||||
# Hack: we need to include 'main' arm target directory to grab private headers
|
||||
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
File diff suppressed because it is too large
Load Diff
@ -16,9 +16,8 @@ BUILT_SOURCES = ARMGenRegisterInfo.h.inc ARMGenRegisterNames.inc \
|
||||
ARMGenRegisterInfo.inc ARMGenInstrNames.inc \
|
||||
ARMGenInstrInfo.inc ARMGenAsmWriter.inc \
|
||||
ARMGenDAGISel.inc ARMGenSubtarget.inc \
|
||||
ARMGenCodeEmitter.inc ARMGenCallingConv.inc \
|
||||
ARMGenDisassemblerTables.inc
|
||||
ARMGenCodeEmitter.inc ARMGenCallingConv.inc
|
||||
|
||||
DIRS = AsmPrinter AsmParser Disassembler TargetInfo
|
||||
DIRS = AsmPrinter AsmParser TargetInfo
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
@ -78,16 +78,14 @@ bool Thumb2ITBlockPass::InsertITBlocks(MachineBasicBlock &MBB) {
|
||||
DebugLoc ndl = NMI->getDebugLoc();
|
||||
unsigned NPredReg = 0;
|
||||
ARMCC::CondCodes NCC = getPredicate(NMI, NPredReg);
|
||||
if (NCC == CC || NCC == OCC)
|
||||
Mask |= (NCC & 1) << Pos;
|
||||
else
|
||||
if (NCC == OCC) {
|
||||
Mask |= (1 << Pos);
|
||||
} else if (NCC != CC)
|
||||
break;
|
||||
--Pos;
|
||||
++MBBI;
|
||||
}
|
||||
Mask |= (1 << Pos);
|
||||
// Tag along (firstcond[0] << 4) with the mask.
|
||||
Mask |= (CC & 1) << 4;
|
||||
MIB.addImm(Mask);
|
||||
Modified = true;
|
||||
++NumITs;
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
define arm_aapcscc void @g() {
|
||||
entry:
|
||||
;CHECK: [sp, #8]
|
||||
;CHECK: [sp, #12]
|
||||
;CHECK: [sp, #+8]
|
||||
;CHECK: [sp, #+12]
|
||||
;CHECK: [sp]
|
||||
tail call arm_aapcscc void (i8*, ...)* @f(i8* getelementptr ([1 x i8]* @.str, i32 0, i32 0), i32 1, double 2.000000e+00, i32 3, double 4.000000e+00)
|
||||
ret void
|
||||
|
@ -6,7 +6,7 @@ define void @f(i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, ...) {
|
||||
entry:
|
||||
;CHECK: sub sp, sp, #4
|
||||
;CHECK: add r{{[0-9]+}}, sp, #8
|
||||
;CHECK: str r{{[0-9]+}}, [sp], #4
|
||||
;CHECK: str r{{[0-9]+}}, [sp], #+4
|
||||
;CHECK: bx lr
|
||||
%ap = alloca i8*, align 4
|
||||
%ap1 = bitcast i8** %ap to i8*
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
define void @test(i32* %P, i32 %A, i32 %i) nounwind {
|
||||
entry:
|
||||
; CHECK: str r1, [{{r.*}}, {{r.*}}, lsl #2]
|
||||
; CHECK: str r1, [{{r.*}}, +{{r.*}}, lsl #2]
|
||||
icmp eq i32 %i, 0 ; <i1>:0 [#uses=1]
|
||||
br i1 %0, label %return, label %bb
|
||||
|
||||
|
@ -41,7 +41,7 @@ define i32 @test1() {
|
||||
; DarwinPIC: _test1:
|
||||
; DarwinPIC: ldr r0, LCPI1_0
|
||||
; DarwinPIC: LPC1_0:
|
||||
; DarwinPIC: ldr r0, [pc, r0]
|
||||
; DarwinPIC: ldr r0, [pc, +r0]
|
||||
; DarwinPIC: ldr r0, [r0]
|
||||
; DarwinPIC: bx lr
|
||||
|
||||
@ -63,7 +63,7 @@ define i32 @test1() {
|
||||
|
||||
; LinuxPIC: .LPC1_0:
|
||||
; LinuxPIC: add r0, pc, r0
|
||||
; LinuxPIC: ldr r0, [r1, r0]
|
||||
; LinuxPIC: ldr r0, [r1, +r0]
|
||||
; LinuxPIC: ldr r0, [r0]
|
||||
; LinuxPIC: bx lr
|
||||
|
||||
|
@ -10,10 +10,10 @@ entry:
|
||||
;V6: ldrd r2, [r2]
|
||||
|
||||
;V5: ldr r3, [r2]
|
||||
;V5: ldr r2, [r2, #4]
|
||||
;V5: ldr r2, [r2, #+4]
|
||||
|
||||
;EABI: ldr r3, [r2]
|
||||
;EABI: ldr r2, [r2, #4]
|
||||
;EABI: ldr r2, [r2, #+4]
|
||||
|
||||
%0 = load i64** @b, align 4
|
||||
%1 = load i64* %0, align 4
|
||||
|
@ -1,5 +1,5 @@
|
||||
; RUN: llc < %s -mtriple=arm-linux-gnu | grep {str.*\\!}
|
||||
; RUN: llc < %s -mtriple=arm-linux-gnu | grep {ldr.*\\\[.*\], #4}
|
||||
; RUN: llc < %s -mtriple=arm-linux-gnu | grep {ldr.*\\\[.*\], #+4}
|
||||
|
||||
@b = external global i64*
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
define i32 @f() {
|
||||
; CHECK-NONPIC: f:
|
||||
; CHECK-NONPIC: ldr {{r.}}, [pc, {{r.}}]
|
||||
; CHECK-NONPIC: ldr {{r.}}, [pc, +{{r.}}]
|
||||
; CHECK-NONPIC: i(gottpoff)
|
||||
; CHECK-PIC: f:
|
||||
; CHECK-PIC: __tls_get_addr
|
||||
@ -18,7 +18,7 @@ entry:
|
||||
|
||||
define i32* @g() {
|
||||
; CHECK-NONPIC: g:
|
||||
; CHECK-NONPIC: ldr {{r.}}, [pc, {{r.}}]
|
||||
; CHECK-NONPIC: ldr {{r.}}, [pc, +{{r.}}]
|
||||
; CHECK-NONPIC: i(gottpoff)
|
||||
; CHECK-PIC: g:
|
||||
; CHECK-PIC: __tls_get_addr
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
define arm_apcscc %union.rec* @Manifest(%union.rec* %x, %union.rec* %env, %struct.STYLE* %style, %union.rec** %bthr, %union.rec** %fthr, %union.rec** %target, %union.rec** %crs, i32 %ok, i32 %need_expand, %union.rec** %enclose, i32 %fcr) nounwind {
|
||||
entry:
|
||||
; CHECK: ldr.w r9, [r7, #28]
|
||||
; CHECK: ldr.w r9, [r7, #+28]
|
||||
%xgaps.i = alloca [32 x %union.rec*], align 4 ; <[32 x %union.rec*]*> [#uses=0]
|
||||
%ycomp.i = alloca [32 x %union.rec*], align 4 ; <[32 x %union.rec*]*> [#uses=0]
|
||||
br i1 false, label %bb, label %bb20
|
||||
@ -50,9 +50,9 @@ bb119: ; preds = %bb20, %bb20
|
||||
bb420: ; preds = %bb20, %bb20
|
||||
; CHECK: bb420
|
||||
; CHECK: str r{{[0-7]}}, [sp]
|
||||
; CHECK: str r{{[0-7]}}, [sp, #4]
|
||||
; CHECK: str r{{[0-7]}}, [sp, #8]
|
||||
; CHECK: str{{(.w)?}} r{{[0-9]+}}, [sp, #24]
|
||||
; CHECK: str r{{[0-7]}}, [sp, #+4]
|
||||
; CHECK: str r{{[0-7]}}, [sp, #+8]
|
||||
; CHECK: str{{(.w)?}} r{{[0-9]+}}, [sp, #+24]
|
||||
store %union.rec* null, %union.rec** @zz_hold, align 4
|
||||
store %union.rec* null, %union.rec** @zz_res, align 4
|
||||
store %union.rec* %x, %union.rec** @zz_hold, align 4
|
||||
|
@ -11,7 +11,7 @@ entry:
|
||||
define i32 @f2(i32* %v) {
|
||||
entry:
|
||||
; CHECK: f2:
|
||||
; CHECK: ldr.w r0, [r0, #4092]
|
||||
; CHECK: ldr.w r0, [r0, #+4092]
|
||||
%tmp2 = getelementptr i32* %v, i32 1023
|
||||
%tmp = load i32* %tmp2
|
||||
ret i32 %tmp
|
||||
|
@ -11,7 +11,7 @@ entry:
|
||||
define i16 @f2(i16* %v) {
|
||||
entry:
|
||||
; CHECK: f2:
|
||||
; CHECK: ldrh.w r0, [r0, #2046]
|
||||
; CHECK: ldrh.w r0, [r0, #+2046]
|
||||
%tmp2 = getelementptr i16* %v, i16 1023
|
||||
%tmp = load i16* %tmp2
|
||||
ret i16 %tmp
|
||||
|
@ -9,7 +9,7 @@ define i32 @f1(i32 %a, i32* %v) {
|
||||
|
||||
define i32 @f2(i32 %a, i32* %v) {
|
||||
; CHECK: f2:
|
||||
; CHECK: str.w r0, [r1, #4092]
|
||||
; CHECK: str.w r0, [r1, #+4092]
|
||||
%tmp2 = getelementptr i32* %v, i32 1023
|
||||
store i32 %a, i32* %tmp2
|
||||
ret i32 %a
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
define void @test1(i32* %X, i32* %A, i32** %dest) {
|
||||
; CHECK: test1
|
||||
; CHECK: str r1, [r0, #16]!
|
||||
; CHECK: str r1, [r0, #+16]!
|
||||
%B = load i32* %A ; <i32> [#uses=1]
|
||||
%Y = getelementptr i32* %X, i32 4 ; <i32*> [#uses=2]
|
||||
store i32 %B, i32* %Y
|
||||
@ -12,7 +12,7 @@ define void @test1(i32* %X, i32* %A, i32** %dest) {
|
||||
|
||||
define i16* @test2(i16* %X, i32* %A) {
|
||||
; CHECK: test2
|
||||
; CHECK: strh r1, [r0, #8]!
|
||||
; CHECK: strh r1, [r0, #+8]!
|
||||
%B = load i32* %A ; <i32> [#uses=1]
|
||||
%Y = getelementptr i16* %X, i32 4 ; <i16*> [#uses=2]
|
||||
%tmp = trunc i32 %B to i16 ; <i16> [#uses=1]
|
||||
|
@ -9,7 +9,7 @@ define i8 @f1(i8 %a, i8* %v) {
|
||||
|
||||
define i8 @f2(i8 %a, i8* %v) {
|
||||
; CHECK: f2:
|
||||
; CHECK: strb.w r0, [r1, #4092]
|
||||
; CHECK: strb.w r0, [r1, #+4092]
|
||||
%tmp2 = getelementptr i8* %v, i32 4092
|
||||
store i8 %a, i8* %tmp2
|
||||
ret i8 %a
|
||||
|
@ -9,7 +9,7 @@ define i16 @f1(i16 %a, i16* %v) {
|
||||
|
||||
define i16 @f2(i16 %a, i16* %v) {
|
||||
; CHECK: f2:
|
||||
; CHECK: strh.w r0, [r1, #4092]
|
||||
; CHECK: strh.w r0, [r1, #+4092]
|
||||
%tmp2 = getelementptr i16* %v, i32 2046
|
||||
store i16 %a, i16* %tmp2
|
||||
ret i16 %a
|
||||
|
@ -12,8 +12,6 @@
|
||||
#include "Record.h"
|
||||
#include "X86DisassemblerTables.h"
|
||||
#include "X86RecognizableInstr.h"
|
||||
#include "RISCDisassemblerEmitter.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::X86Disassembler;
|
||||
|
||||
@ -126,12 +124,6 @@ void DisassemblerEmitter::run(raw_ostream &OS) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fixed-instruction-length targets use a common disassembler.
|
||||
if (Target.getName() == "ARM") {
|
||||
RISCDisassemblerEmitter(Records).run(OS);
|
||||
return;
|
||||
}
|
||||
|
||||
throw TGError(Target.getTargetRecord()->getLoc(),
|
||||
"Unable to generate disassembler for this target");
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,48 +0,0 @@
|
||||
//===- RISCDisassemblerEmitter.h - Disassembler Generator -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// FIXME: document
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef RISCDISASSEMBLEREMITTER_H
|
||||
#define RISCDISASSEMBLEREMITTER_H
|
||||
|
||||
#include "TableGenBackend.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class RISCDisassemblerEmitter : public TableGenBackend {
|
||||
RecordKeeper &Records;
|
||||
public:
|
||||
RISCDisassemblerEmitter(RecordKeeper &R) : Records(R) {
|
||||
initBackend();
|
||||
}
|
||||
|
||||
~RISCDisassemblerEmitter() {
|
||||
shutdownBackend();
|
||||
}
|
||||
|
||||
// run - Output the code emitter
|
||||
void run(raw_ostream &o);
|
||||
|
||||
private:
|
||||
class RISCDEBackend;
|
||||
|
||||
RISCDEBackend *Backend;
|
||||
|
||||
void initBackend();
|
||||
void shutdownBackend();
|
||||
};
|
||||
|
||||
} // end llvm namespace
|
||||
|
||||
#endif
|
@ -31,7 +31,6 @@
|
||||
#include "OptParserEmitter.h"
|
||||
#include "Record.h"
|
||||
#include "RegisterInfoEmitter.h"
|
||||
#include "RISCDisassemblerEmitter.h"
|
||||
#include "SubtargetEmitter.h"
|
||||
#include "TGParser.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
@ -49,7 +48,6 @@ enum ActionType {
|
||||
GenEmitter,
|
||||
GenRegisterEnums, GenRegister, GenRegisterHeader,
|
||||
GenInstrEnums, GenInstrs, GenAsmWriter, GenAsmMatcher,
|
||||
GenRISCDisassembler,
|
||||
GenDisassembler,
|
||||
GenCallingConv,
|
||||
GenClangDiagsDefs,
|
||||
@ -86,9 +84,6 @@ namespace {
|
||||
"Generate calling convention descriptions"),
|
||||
clEnumValN(GenAsmWriter, "gen-asm-writer",
|
||||
"Generate assembly writer"),
|
||||
clEnumValN(GenRISCDisassembler, "gen-risc-disassembler",
|
||||
"Generate disassembler for fixed instruction"
|
||||
" length"),
|
||||
clEnumValN(GenDisassembler, "gen-disassembler",
|
||||
"Generate disassembler"),
|
||||
clEnumValN(GenAsmMatcher, "gen-asm-matcher",
|
||||
@ -234,9 +229,6 @@ int main(int argc, char **argv) {
|
||||
case GenAsmWriter:
|
||||
AsmWriterEmitter(Records).run(*Out);
|
||||
break;
|
||||
case GenRISCDisassembler:
|
||||
RISCDisassemblerEmitter(Records).run(*Out);
|
||||
break;
|
||||
case GenAsmMatcher:
|
||||
AsmMatcherEmitter(Records).run(*Out);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user