mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-05 02:07:16 +00:00
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
This commit is contained in:
parent
ff10341183
commit
0f63075613
@ -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";
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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}
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user