aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2010-11-17 04:32:08 +0000
committerBill Wendling <isanbard@gmail.com>2010-11-17 04:32:08 +0000
commit0f6307561359fac4425a0b9e512931cf96c1ec5b (patch)
tree03e2b707d388830e52030c7176de2374fd0c9350
parentff10341183adf74760e6118a55cbd1debf50f90f (diff)
downloadexternal_llvm-0f6307561359fac4425a0b9e512931cf96c1ec5b.zip
external_llvm-0f6307561359fac4425a0b9e512931cf96c1ec5b.tar.gz
external_llvm-0f6307561359fac4425a0b9e512931cf96c1ec5b.tar.bz2
Proper encoding for VLDM and VSTM instructions. The register lists for these
instructions have to distinguish between lists of single- and double-precision registers in order for the ASM matcher to do a proper job. In all other respects, a list of single- or double-precision registers are the same as a list of GPR registers. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119460 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td22
-rw-r--r--lib/Target/ARM/ARMInstrVFP.td16
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp30
-rw-r--r--test/MC/ARM/simple-fp-encoding.s10
-rw-r--r--utils/TableGen/EDEmitter.cpp4
5 files changed, 71 insertions, 11 deletions
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index c06208e..6032e21 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -290,12 +290,34 @@ def RegListAsmOperand : AsmOperandClass {
let SuperClasses = [];
}
+def DPRRegListAsmOperand : AsmOperandClass {
+ let Name = "DPRRegList";
+ let SuperClasses = [];
+}
+
+def SPRRegListAsmOperand : AsmOperandClass {
+ let Name = "SPRRegList";
+ let SuperClasses = [];
+}
+
def reglist : Operand<i32> {
let EncoderMethod = "getRegisterListOpValue";
let ParserMatchClass = RegListAsmOperand;
let PrintMethod = "printRegisterList";
}
+def dpr_reglist : Operand<i32> {
+ let EncoderMethod = "getRegisterListOpValue";
+ let ParserMatchClass = DPRRegListAsmOperand;
+ let PrintMethod = "printRegisterList";
+}
+
+def spr_reglist : Operand<i32> {
+ let EncoderMethod = "getRegisterListOpValue";
+ let ParserMatchClass = SPRRegListAsmOperand;
+ let PrintMethod = "printRegisterList";
+}
+
// An operand for the CONSTPOOL_ENTRY pseudo-instruction.
def cpinst_operand : Operand<i32> {
let PrintMethod = "printCPInstOperand";
diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td
index 7ca3b39..d622169 100644
--- a/lib/Target/ARM/ARMInstrVFP.td
+++ b/lib/Target/ARM/ARMInstrVFP.td
@@ -78,7 +78,7 @@ multiclass vfp_ldst_mult<string asm, bit L_bit,
InstrItinClass itin, InstrItinClass itin_upd> {
// Double Precision
def DIA :
- AXDI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
+ AXDI4<(outs), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops),
IndexModeNone, itin,
!strconcat(asm, "ia${p}\t$Rn, $regs"), "", []> {
let Inst{24-23} = 0b01; // Increment After
@@ -86,7 +86,7 @@ multiclass vfp_ldst_mult<string asm, bit L_bit,
let Inst{20} = L_bit;
}
def DIA_UPD :
- AXDI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
+ AXDI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops),
IndexModeUpd, itin_upd,
!strconcat(asm, "ia${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
let Inst{24-23} = 0b01; // Increment After
@@ -94,7 +94,7 @@ multiclass vfp_ldst_mult<string asm, bit L_bit,
let Inst{20} = L_bit;
}
def DDB :
- AXDI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
+ AXDI4<(outs), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops),
IndexModeNone, itin,
!strconcat(asm, "db${p}\t$Rn, $regs"), "", []> {
let Inst{24-23} = 0b10; // Decrement Before
@@ -102,7 +102,7 @@ multiclass vfp_ldst_mult<string asm, bit L_bit,
let Inst{20} = L_bit;
}
def DDB_UPD :
- AXDI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
+ AXDI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops),
IndexModeUpd, itin_upd,
!strconcat(asm, "db${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
let Inst{24-23} = 0b10; // Decrement Before
@@ -112,7 +112,7 @@ multiclass vfp_ldst_mult<string asm, bit L_bit,
// Single Precision
def SIA :
- AXSI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
+ AXSI4<(outs), (ins GPR:$Rn, pred:$p, spr_reglist:$regs, variable_ops),
IndexModeNone, itin,
!strconcat(asm, "ia${p}\t$Rn, $regs"), "", []> {
let Inst{24-23} = 0b01; // Increment After
@@ -120,7 +120,7 @@ multiclass vfp_ldst_mult<string asm, bit L_bit,
let Inst{20} = L_bit;
}
def SIA_UPD :
- AXSI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
+ AXSI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, spr_reglist:$regs, variable_ops),
IndexModeUpd, itin_upd,
!strconcat(asm, "ia${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
let Inst{24-23} = 0b01; // Increment After
@@ -128,7 +128,7 @@ multiclass vfp_ldst_mult<string asm, bit L_bit,
let Inst{20} = L_bit;
}
def SDB :
- AXSI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
+ AXSI4<(outs), (ins GPR:$Rn, pred:$p, spr_reglist:$regs, variable_ops),
IndexModeNone, itin,
!strconcat(asm, "db${p}\t$Rn, $regs"), "", []> {
let Inst{24-23} = 0b10; // Decrement Before
@@ -136,7 +136,7 @@ multiclass vfp_ldst_mult<string asm, bit L_bit,
let Inst{20} = L_bit;
}
def SDB_UPD :
- AXSI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
+ AXSI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, spr_reglist:$regs, variable_ops),
IndexModeUpd, itin_upd,
!strconcat(asm, "db${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
let Inst{24-23} = 0b10; // Decrement Before
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index e00ced2..b07fb64 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -107,6 +107,8 @@ class ARMOperand : public MCParsedAsmOperand {
Memory,
Register,
RegisterList,
+ DPRRegisterList,
+ SPRRegisterList,
Token
} Kind;
@@ -168,6 +170,8 @@ public:
Reg = o.Reg;
break;
case RegisterList:
+ case DPRRegisterList:
+ case SPRRegisterList:
RegList = o.RegList;
break;
case Immediate:
@@ -204,7 +208,8 @@ public:
}
const SmallVectorImpl<unsigned> &getRegList() const {
- assert(Kind == RegisterList && "Invalid access!");
+ assert((Kind == RegisterList || Kind == DPRRegisterList ||
+ Kind == SPRRegisterList) && "Invalid access!");
return *RegList.Registers;
}
@@ -217,6 +222,8 @@ public:
bool isImm() const { return Kind == Immediate; }
bool isReg() const { return Kind == Register; }
bool isRegList() const { return Kind == RegisterList; }
+ bool isDPRRegList() const { return Kind == DPRRegisterList; }
+ bool isSPRRegList() const { return Kind == SPRRegisterList; }
bool isToken() const { return Kind == Token; }
bool isMemory() const { return Kind == Memory; }
bool isMemMode5() const {
@@ -264,6 +271,14 @@ public:
Inst.addOperand(MCOperand::CreateReg(*I));
}
+ void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
+ addRegListOperands(Inst, N);
+ }
+
+ void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
+ addRegListOperands(Inst, N);
+ }
+
void addImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
addExpr(Inst, getImm());
@@ -327,7 +342,14 @@ public:
static ARMOperand *
CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
SMLoc StartLoc, SMLoc EndLoc) {
- ARMOperand *Op = new ARMOperand(RegisterList);
+ KindTy Kind = RegisterList;
+
+ if (ARM::DPRRegClass.contains(Regs.front().first))
+ Kind = DPRRegisterList;
+ else if (ARM::SPRRegClass.contains(Regs.front().first))
+ Kind = SPRRegisterList;
+
+ ARMOperand *Op = new ARMOperand(Kind);
Op->RegList.Registers = new SmallVector<unsigned, 32>();
for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
I = Regs.begin(), E = Regs.end(); I != E; ++I)
@@ -387,7 +409,9 @@ void ARMOperand::dump(raw_ostream &OS) const {
case Register:
OS << "<register " << getReg() << (!Reg.Writeback ? ">" : "!>");
break;
- case RegisterList: {
+ case RegisterList:
+ case DPRRegisterList:
+ case SPRRegisterList: {
OS << "<register_list ";
const SmallVectorImpl<unsigned> &RegList = getRegList();
diff --git a/test/MC/ARM/simple-fp-encoding.s b/test/MC/ARM/simple-fp-encoding.s
index 9120fcf..f699b21 100644
--- a/test/MC/ARM/simple-fp-encoding.s
+++ b/test/MC/ARM/simple-fp-encoding.s
@@ -207,3 +207,13 @@
vstr.32 s4, [r1]
vstr.32 s4, [r1, #24]
vstr.32 s4, [r1, #-24]
+
+@ CHECK: vldmia r1, {d2, d3, d4, d5, d6, d7} @ encoding: [0x0c,0x2b,0x91,0xec]
+@ CHECK: vldmia r1, {s2, s3, s4, s5, s6, s7} @ encoding: [0x06,0x1a,0x91,0xec]
+ vldmia r1, {d2,d3-d6,d7}
+ vldmia r1, {s2,s3-s6,s7}
+
+@ CHECK: vstmia r1, {d2, d3, d4, d5, d6, d7} @ encoding: [0x0c,0x2b,0x81,0xec]
+@ CHECK: vstmia r1, {s2, s3, s4, s5, s6, s7} @ encoding: [0x06,0x1a,0x81,0xec]
+ vstmia r1, {d2,d3-d6,d7}
+ vstmia r1, {s2,s3-s6,s7}
diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp
index 78d3510..dd09174 100644
--- a/utils/TableGen/EDEmitter.cpp
+++ b/utils/TableGen/EDEmitter.cpp
@@ -607,6 +607,8 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
MISC("am6offset", "kOperandTypeARMAddrMode6Offset"); // R, I, I
MISC("addrmodepc", "kOperandTypeARMAddrModePC"); // R, I
MISC("reglist", "kOperandTypeARMRegisterList"); // I, R, ...
+ MISC("dpr_reglist", "kOperandTypeARMDPRRegisterList"); // I, R, ...
+ MISC("spr_reglist", "kOperandTypeARMSPRRegisterList"); // I, R, ...
MISC("it_mask", "kOperandTypeThumbITMask"); // I
MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8"); // R, I
MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I
@@ -823,6 +825,8 @@ static void emitCommonEnums(raw_ostream &o, unsigned int &i) {
operandTypes.addEntry("kOperandTypeARMAddrMode6Offset");
operandTypes.addEntry("kOperandTypeARMAddrModePC");
operandTypes.addEntry("kOperandTypeARMRegisterList");
+ operandTypes.addEntry("kOperandTypeARMDPRRegisterList");
+ operandTypes.addEntry("kOperandTypeARMSPRRegisterList");
operandTypes.addEntry("kOperandTypeARMTBAddrMode");
operandTypes.addEntry("kOperandTypeThumbITMask");
operandTypes.addEntry("kOperandTypeThumbAddrModeS1");