forked from OSchip/llvm-project
RFE encoding should also specify the "should be" encoding bits.
rdar://problem/9229922 ARM disassembler discrepancy: erroneously accepting RFE Also LDC/STC instructions are predicated while LDC2/STC2 instructions are not, fixed while doing regression testings. llvm-svn: 128859
This commit is contained in:
parent
378819342e
commit
a6129b4a7f
|
@ -1604,6 +1604,7 @@ def RFEW : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, GPR:$base),
|
||||||
[/* For disassembly only; pattern left blank */]> {
|
[/* For disassembly only; pattern left blank */]> {
|
||||||
let Inst{31-28} = 0b1111;
|
let Inst{31-28} = 0b1111;
|
||||||
let Inst{22-20} = 0b011; // W = 1
|
let Inst{22-20} = 0b011; // W = 1
|
||||||
|
let Inst{15-0} = 0x0a00;
|
||||||
}
|
}
|
||||||
|
|
||||||
def RFE : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, GPR:$base),
|
def RFE : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, GPR:$base),
|
||||||
|
@ -1611,6 +1612,7 @@ def RFE : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, GPR:$base),
|
||||||
[/* For disassembly only; pattern left blank */]> {
|
[/* For disassembly only; pattern left blank */]> {
|
||||||
let Inst{31-28} = 0b1111;
|
let Inst{31-28} = 0b1111;
|
||||||
let Inst{22-20} = 0b001; // W = 0
|
let Inst{22-20} = 0b001; // W = 0
|
||||||
|
let Inst{15-0} = 0x0a00;
|
||||||
}
|
}
|
||||||
} // isCodeGenOnly = 1
|
} // isCodeGenOnly = 1
|
||||||
|
|
||||||
|
@ -3434,16 +3436,16 @@ def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1,
|
||||||
|
|
||||||
class ACI<dag oops, dag iops, string opc, string asm,
|
class ACI<dag oops, dag iops, string opc, string asm,
|
||||||
IndexMode im = IndexModeNone>
|
IndexMode im = IndexModeNone>
|
||||||
: I<oops, iops, AddrModeNone, Size4Bytes, im, BrFrm, NoItinerary,
|
: InoP<oops, iops, AddrModeNone, Size4Bytes, im, BrFrm, NoItinerary,
|
||||||
opc, asm, "", [/* For disassembly only; pattern left blank */]> {
|
opc, asm, "", [/* For disassembly only; pattern left blank */]> {
|
||||||
let Inst{27-25} = 0b110;
|
let Inst{27-25} = 0b110;
|
||||||
}
|
}
|
||||||
|
|
||||||
multiclass LdStCop<bits<4> op31_28, bit load, string opc> {
|
multiclass LdStCop<bits<4> op31_28, bit load, dag ops, string opc, string cond>{
|
||||||
|
|
||||||
def _OFFSET : ACI<(outs),
|
def _OFFSET : ACI<(outs),
|
||||||
(ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
|
!con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
|
||||||
opc, "\tp$cop, cr$CRd, $addr"> {
|
!strconcat(opc, cond), "\tp$cop, cr$CRd, $addr"> {
|
||||||
let Inst{31-28} = op31_28;
|
let Inst{31-28} = op31_28;
|
||||||
let Inst{24} = 1; // P = 1
|
let Inst{24} = 1; // P = 1
|
||||||
let Inst{21} = 0; // W = 0
|
let Inst{21} = 0; // W = 0
|
||||||
|
@ -3452,8 +3454,8 @@ multiclass LdStCop<bits<4> op31_28, bit load, string opc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
def _PRE : ACI<(outs),
|
def _PRE : ACI<(outs),
|
||||||
(ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
|
!con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
|
||||||
opc, "\tp$cop, cr$CRd, $addr!", IndexModePre> {
|
!strconcat(opc, cond), "\tp$cop, cr$CRd, $addr!", IndexModePre> {
|
||||||
let Inst{31-28} = op31_28;
|
let Inst{31-28} = op31_28;
|
||||||
let Inst{24} = 1; // P = 1
|
let Inst{24} = 1; // P = 1
|
||||||
let Inst{21} = 1; // W = 1
|
let Inst{21} = 1; // W = 1
|
||||||
|
@ -3462,8 +3464,8 @@ multiclass LdStCop<bits<4> op31_28, bit load, string opc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
def _POST : ACI<(outs),
|
def _POST : ACI<(outs),
|
||||||
(ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
|
!con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
|
||||||
opc, "\tp$cop, cr$CRd, $addr", IndexModePost> {
|
!strconcat(opc, cond), "\tp$cop, cr$CRd, $addr", IndexModePost> {
|
||||||
let Inst{31-28} = op31_28;
|
let Inst{31-28} = op31_28;
|
||||||
let Inst{24} = 0; // P = 0
|
let Inst{24} = 0; // P = 0
|
||||||
let Inst{21} = 1; // W = 1
|
let Inst{21} = 1; // W = 1
|
||||||
|
@ -3472,8 +3474,9 @@ multiclass LdStCop<bits<4> op31_28, bit load, string opc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
def _OPTION : ACI<(outs),
|
def _OPTION : ACI<(outs),
|
||||||
(ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, nohash_imm:$option),
|
!con((ins nohash_imm:$cop,nohash_imm:$CRd,GPR:$base, nohash_imm:$option),
|
||||||
opc, "\tp$cop, cr$CRd, [$base], \\{$option\\}"> {
|
ops),
|
||||||
|
!strconcat(opc, cond), "\tp$cop, cr$CRd, [$base], \\{$option\\}"> {
|
||||||
let Inst{31-28} = op31_28;
|
let Inst{31-28} = op31_28;
|
||||||
let Inst{24} = 0; // P = 0
|
let Inst{24} = 0; // P = 0
|
||||||
let Inst{23} = 1; // U = 1
|
let Inst{23} = 1; // U = 1
|
||||||
|
@ -3483,8 +3486,8 @@ multiclass LdStCop<bits<4> op31_28, bit load, string opc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
def L_OFFSET : ACI<(outs),
|
def L_OFFSET : ACI<(outs),
|
||||||
(ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
|
!con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
|
||||||
!strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr"> {
|
!strconcat(!strconcat(opc, "l"), cond), "\tp$cop, cr$CRd, $addr"> {
|
||||||
let Inst{31-28} = op31_28;
|
let Inst{31-28} = op31_28;
|
||||||
let Inst{24} = 1; // P = 1
|
let Inst{24} = 1; // P = 1
|
||||||
let Inst{21} = 0; // W = 0
|
let Inst{21} = 0; // W = 0
|
||||||
|
@ -3493,8 +3496,9 @@ multiclass LdStCop<bits<4> op31_28, bit load, string opc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
def L_PRE : ACI<(outs),
|
def L_PRE : ACI<(outs),
|
||||||
(ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
|
!con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
|
||||||
!strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr!", IndexModePre> {
|
!strconcat(!strconcat(opc, "l"), cond), "\tp$cop, cr$CRd, $addr!",
|
||||||
|
IndexModePre> {
|
||||||
let Inst{31-28} = op31_28;
|
let Inst{31-28} = op31_28;
|
||||||
let Inst{24} = 1; // P = 1
|
let Inst{24} = 1; // P = 1
|
||||||
let Inst{21} = 1; // W = 1
|
let Inst{21} = 1; // W = 1
|
||||||
|
@ -3503,8 +3507,9 @@ multiclass LdStCop<bits<4> op31_28, bit load, string opc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
def L_POST : ACI<(outs),
|
def L_POST : ACI<(outs),
|
||||||
(ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr),
|
!con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
|
||||||
!strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr", IndexModePost> {
|
!strconcat(!strconcat(opc, "l"), cond), "\tp$cop, cr$CRd, $addr",
|
||||||
|
IndexModePost> {
|
||||||
let Inst{31-28} = op31_28;
|
let Inst{31-28} = op31_28;
|
||||||
let Inst{24} = 0; // P = 0
|
let Inst{24} = 0; // P = 0
|
||||||
let Inst{21} = 1; // W = 1
|
let Inst{21} = 1; // W = 1
|
||||||
|
@ -3513,8 +3518,10 @@ multiclass LdStCop<bits<4> op31_28, bit load, string opc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
def L_OPTION : ACI<(outs),
|
def L_OPTION : ACI<(outs),
|
||||||
(ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, nohash_imm:$option),
|
!con((ins nohash_imm:$cop, nohash_imm:$CRd,GPR:$base,nohash_imm:$option),
|
||||||
!strconcat(opc, "l"), "\tp$cop, cr$CRd, [$base], \\{$option\\}"> {
|
ops),
|
||||||
|
!strconcat(!strconcat(opc, "l"), cond),
|
||||||
|
"\tp$cop, cr$CRd, [$base], \\{$option\\}"> {
|
||||||
let Inst{31-28} = op31_28;
|
let Inst{31-28} = op31_28;
|
||||||
let Inst{24} = 0; // P = 0
|
let Inst{24} = 0; // P = 0
|
||||||
let Inst{23} = 1; // U = 1
|
let Inst{23} = 1; // U = 1
|
||||||
|
@ -3524,10 +3531,10 @@ multiclass LdStCop<bits<4> op31_28, bit load, string opc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defm LDC : LdStCop<{?,?,?,?}, 1, "ldc">;
|
defm LDC : LdStCop<{?,?,?,?}, 1, (ins pred:$p), "ldc", "${p}">;
|
||||||
defm LDC2 : LdStCop<0b1111, 1, "ldc2">;
|
defm LDC2 : LdStCop<0b1111, 1, (ins), "ldc2", "">;
|
||||||
defm STC : LdStCop<{?,?,?,?}, 0, "stc">;
|
defm STC : LdStCop<{?,?,?,?}, 0, (ins pred:$p), "stc", "${p}">;
|
||||||
defm STC2 : LdStCop<0b1111, 0, "stc2">;
|
defm STC2 : LdStCop<0b1111, 0, (ins), "stc2", "">;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Move between coprocessor and ARM core register -- for disassembly only
|
// Move between coprocessor and ARM core register -- for disassembly only
|
||||||
|
|
|
@ -618,7 +618,7 @@ static inline unsigned GetCopOpc(uint32_t insn) {
|
||||||
static bool DisassembleCoprocessor(MCInst &MI, unsigned Opcode, uint32_t insn,
|
static bool DisassembleCoprocessor(MCInst &MI, unsigned Opcode, uint32_t insn,
|
||||||
unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
|
unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
|
||||||
|
|
||||||
assert(NumOps >= 5 && "Num of operands >= 5 for coprocessor instr");
|
assert(NumOps >= 4 && "Num of operands >= 4 for coprocessor instr");
|
||||||
|
|
||||||
unsigned &OpIdx = NumOpsAdded;
|
unsigned &OpIdx = NumOpsAdded;
|
||||||
bool OneCopOpc = (Opcode == ARM::MCRR || Opcode == ARM::MCRR2 ||
|
bool OneCopOpc = (Opcode == ARM::MCRR || Opcode == ARM::MCRR2 ||
|
||||||
|
@ -1296,8 +1296,10 @@ static bool DisassembleLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
|
||||||
MI.addOperand(MCOperand::CreateReg(Base));
|
MI.addOperand(MCOperand::CreateReg(Base));
|
||||||
|
|
||||||
// Handling the two predicate operands before the reglist.
|
// Handling the two predicate operands before the reglist.
|
||||||
int64_t CondVal = insn >> ARMII::CondShift;
|
int64_t CondVal = getCondField(insn);
|
||||||
MI.addOperand(MCOperand::CreateImm(CondVal == 0xF ? 0xE : CondVal));
|
if (CondVal == 0xF)
|
||||||
|
return false;
|
||||||
|
MI.addOperand(MCOperand::CreateImm(CondVal));
|
||||||
MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
|
MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
|
||||||
|
|
||||||
NumOpsAdded += 3;
|
NumOpsAdded += 3;
|
||||||
|
@ -1863,8 +1865,10 @@ static bool DisassembleVFPLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
|
||||||
MI.addOperand(MCOperand::CreateReg(Base));
|
MI.addOperand(MCOperand::CreateReg(Base));
|
||||||
|
|
||||||
// Handling the two predicate operands before the reglist.
|
// Handling the two predicate operands before the reglist.
|
||||||
int64_t CondVal = insn >> ARMII::CondShift;
|
int64_t CondVal = getCondField(insn);
|
||||||
MI.addOperand(MCOperand::CreateImm(CondVal == 0xF ? 0xE : CondVal));
|
if (CondVal == 0xF)
|
||||||
|
return false;
|
||||||
|
MI.addOperand(MCOperand::CreateImm(CondVal));
|
||||||
MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
|
MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
|
||||||
|
|
||||||
OpIdx += 3;
|
OpIdx += 3;
|
||||||
|
@ -3357,6 +3361,7 @@ bool ARMBasicMCBuilder::TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
|
||||||
const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
|
const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
|
||||||
const std::string &Name = ARMInsts[Opcode].Name;
|
const std::string &Name = ARMInsts[Opcode].Name;
|
||||||
unsigned Idx = MI.getNumOperands();
|
unsigned Idx = MI.getNumOperands();
|
||||||
|
uint64_t TSFlags = ARMInsts[Opcode].TSFlags;
|
||||||
|
|
||||||
// First, we check whether this instr specifies the PredicateOperand through
|
// First, we check whether this instr specifies the PredicateOperand through
|
||||||
// a pair of TargetOperandInfos with isPredicate() property.
|
// a pair of TargetOperandInfos with isPredicate() property.
|
||||||
|
@ -3384,6 +3389,9 @@ bool ARMBasicMCBuilder::TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
|
||||||
MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
||||||
} else {
|
} else {
|
||||||
// ARM instructions get their condition field from Inst{31-28}.
|
// ARM instructions get their condition field from Inst{31-28}.
|
||||||
|
// We should reject Inst{31-28} = 0b1111 as invalid encoding.
|
||||||
|
if (!isNEONDomain(TSFlags) && getCondField(insn) == 0xF)
|
||||||
|
return false;
|
||||||
MI.addOperand(MCOperand::CreateImm(CondCode(getCondField(insn))));
|
MI.addOperand(MCOperand::CreateImm(CondCode(getCondField(insn))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,6 +141,12 @@ static inline bool isUnaryDP(uint64_t TSFlags) {
|
||||||
return (TSFlags & ARMII::UnaryDP);
|
return (TSFlags & ARMII::UnaryDP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A NEON Domain instruction has cond field (Inst{31-28}) as 0b1111.
|
||||||
|
static inline bool isNEONDomain(uint64_t TSFlags) {
|
||||||
|
return (TSFlags & ARMII::DomainNEON) ||
|
||||||
|
(TSFlags & ARMII::DomainNEONA8);
|
||||||
|
}
|
||||||
|
|
||||||
/// This four-bit field describes the addressing mode used.
|
/// This four-bit field describes the addressing mode used.
|
||||||
/// See also ARMBaseInstrInfo.h.
|
/// See also ARMBaseInstrInfo.h.
|
||||||
static inline unsigned getAddrMode(uint64_t TSFlags) {
|
static inline unsigned getAddrMode(uint64_t TSFlags) {
|
||||||
|
|
Loading…
Reference in New Issue