summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorTim Northover <tnorthover@apple.com>2013-05-31 15:55:51 +0000
committerTim Northover <tnorthover@apple.com>2013-05-31 15:55:51 +0000
commit4173e29a98b4f1be42fef913712277a9cdff87f2 (patch)
tree741aaa8dc154989408bc52c3d9f52ba35b7bae5f /llvm/lib/Target
parentab8128b01dcee66da444817d301373789357a019 (diff)
downloadbcm5719-llvm-4173e29a98b4f1be42fef913712277a9cdff87f2.tar.gz
bcm5719-llvm-4173e29a98b4f1be42fef913712277a9cdff87f2.zip
ARM: add fstmx and fldmx instructions for assembly
These instructions are deprecated oddities, but we still need to be able to disassemble (and reassemble) them if and when they're encountered. Patch by Amaury de la Vieuville. llvm-svn: 183011
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/ARM/ARMInstrFormats.td30
-rw-r--r--llvm/lib/Target/ARM/ARMInstrVFP.td31
-rw-r--r--llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp17
3 files changed, 70 insertions, 8 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td
index 67a6820932f..bd9a212928e 100644
--- a/llvm/lib/Target/ARM/ARMInstrFormats.td
+++ b/llvm/lib/Target/ARM/ARMInstrFormats.td
@@ -1389,7 +1389,6 @@ class ADI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
let Inst{15-12} = Dd{3-0};
let Inst{7-0} = addr{7-0}; // imm8
- // TODO: Mark the instructions with the appropriate subtarget info.
let Inst{27-24} = opcod1;
let Inst{21-20} = opcod2;
let Inst{11-9} = 0b101;
@@ -1415,7 +1414,6 @@ class ASI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
let Inst{15-12} = Sd{4-1};
let Inst{7-0} = addr{7-0}; // imm8
- // TODO: Mark the instructions with the appropriate subtarget info.
let Inst{27-24} = opcod1;
let Inst{21-20} = opcod2;
let Inst{11-9} = 0b101;
@@ -1437,6 +1435,28 @@ class PseudoVFPLdStM<dag oops, dag iops, InstrItinClass itin, string cstr,
}
// Load / store multiple
+
+// Unknown precision
+class AXXI4<dag oops, dag iops, IndexMode im,
+ string asm, string cstr, list<dag> pattern>
+ : VFPXI<oops, iops, AddrMode4, 4, im,
+ VFPLdStFrm, NoItinerary, asm, cstr, pattern> {
+ // Instruction operands.
+ bits<4> Rn;
+ bits<13> regs;
+
+ // Encode instruction operands.
+ let Inst{19-16} = Rn;
+ let Inst{22} = 0;
+ let Inst{15-12} = regs{11-8};
+ let Inst{7-1} = regs{7-1};
+
+ let Inst{27-25} = 0b110;
+ let Inst{11-8} = 0b1011;
+ let Inst{0} = 1;
+}
+
+// Double precision
class AXDI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
: VFPXI<oops, iops, AddrMode4, 4, im,
@@ -1449,14 +1469,15 @@ class AXDI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
let Inst{19-16} = Rn;
let Inst{22} = regs{12};
let Inst{15-12} = regs{11-8};
- let Inst{7-0} = regs{7-0};
+ let Inst{7-1} = regs{7-1};
- // TODO: Mark the instructions with the appropriate subtarget info.
let Inst{27-25} = 0b110;
let Inst{11-9} = 0b101;
let Inst{8} = 1; // Double precision
+ let Inst{0} = 0;
}
+// Single Precision
class AXSI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
: VFPXI<oops, iops, AddrMode4, 4, im,
@@ -1471,7 +1492,6 @@ class AXSI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
let Inst{15-12} = regs{12-9};
let Inst{7-0} = regs{7-0};
- // TODO: Mark the instructions with the appropriate subtarget info.
let Inst{27-25} = 0b110;
let Inst{11-9} = 0b101;
let Inst{8} = 0; // Single precision
diff --git a/llvm/lib/Target/ARM/ARMInstrVFP.td b/llvm/lib/Target/ARM/ARMInstrVFP.td
index b5a896c6998..2380528e130 100644
--- a/llvm/lib/Target/ARM/ARMInstrVFP.td
+++ b/llvm/lib/Target/ARM/ARMInstrVFP.td
@@ -224,7 +224,36 @@ defm : VFPDTAnyInstAlias<"vpop${p}", "$r",
defm : VFPDTAnyInstAlias<"vpop${p}", "$r",
(VLDMDIA_UPD SP, pred:$p, dpr_reglist:$r)>;
-// FLDMX, FSTMX - mixing S/D registers for pre-armv6 cores
+// FLDMX, FSTMX - Load and store multiple unknown precision registers for
+// pre-armv6 cores.
+// These instruction are deprecated so we don't want them to get selected.
+multiclass vfp_ldstx_mult<string asm, bit L_bit> {
+ // Unknown precision
+ def XIA :
+ AXXI4<(outs), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops),
+ IndexModeNone, !strconcat(asm, "iax${p}\t$Rn, $regs"), "", []> {
+ let Inst{24-23} = 0b01; // Increment After
+ let Inst{21} = 0; // No writeback
+ let Inst{20} = L_bit;
+ }
+ def XIA_UPD :
+ AXXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops),
+ IndexModeUpd, !strconcat(asm, "iax${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
+ let Inst{24-23} = 0b01; // Increment After
+ let Inst{21} = 1; // Writeback
+ let Inst{20} = L_bit;
+ }
+ def XDB_UPD :
+ AXXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops),
+ IndexModeUpd, !strconcat(asm, "dbx${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
+ let Inst{24-23} = 0b10; // Decrement Before
+ let Inst{21} = 1;
+ let Inst{20} = L_bit;
+ }
+}
+
+defm FLDM : vfp_ldstx_mult<"fldm", 1>;
+defm FSTM : vfp_ldstx_mult<"fstm", 0>;
//===----------------------------------------------------------------------===//
// FP Binary Operations.
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index 9c13c604638..824ffbf3386 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -1150,6 +1150,13 @@ static DecodeStatus DecodeSPRRegListOperand(MCInst &Inst, unsigned Val,
unsigned Vd = fieldFromInstruction(Val, 8, 5);
unsigned regs = fieldFromInstruction(Val, 0, 8);
+ // In case of unpredictable encoding, tweak the operands.
+ if (regs == 0 || (Vd + regs) > 32) {
+ regs = Vd + regs > 32 ? 32 - Vd : regs;
+ regs = std::max( 1u, regs);
+ S = MCDisassembler::SoftFail;
+ }
+
if (!Check(S, DecodeSPRRegisterClass(Inst, Vd, Address, Decoder)))
return MCDisassembler::Fail;
for (unsigned i = 0; i < (regs - 1); ++i) {
@@ -1165,9 +1172,15 @@ static DecodeStatus DecodeDPRRegListOperand(MCInst &Inst, unsigned Val,
DecodeStatus S = MCDisassembler::Success;
unsigned Vd = fieldFromInstruction(Val, 8, 5);
- unsigned regs = fieldFromInstruction(Val, 0, 8);
+ unsigned regs = fieldFromInstruction(Val, 1, 7);
- regs = regs >> 1;
+ // In case of unpredictable encoding, tweak the operands.
+ if (regs == 0 || regs > 16 || (Vd + regs) > 32) {
+ regs = Vd + regs > 32 ? 32 - Vd : regs;
+ regs = std::max( 1u, regs);
+ regs = std::min(16u, regs);
+ S = MCDisassembler::SoftFail;
+ }
if (!Check(S, DecodeDPRRegisterClass(Inst, Vd, Address, Decoder)))
return MCDisassembler::Fail;
OpenPOWER on IntegriCloud