mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
Fix #13241, a bug around shift immediate operand for ARM instruction ADR.
llvm-svn: 161159
This commit is contained in:
parent
44d438eb55
commit
e4c91e239f
@ -416,8 +416,11 @@ def pclabel : Operand<i32> {
|
||||
}
|
||||
|
||||
// ADR instruction labels.
|
||||
def AdrLabelAsmOperand : AsmOperandClass { let Name = "AdrLabel"; }
|
||||
def adrlabel : Operand<i32> {
|
||||
let EncoderMethod = "getAdrLabelOpValue";
|
||||
let ParserMatchClass = AdrLabelAsmOperand;
|
||||
let PrintMethod = "printAdrLabelOperand";
|
||||
}
|
||||
|
||||
def neon_vcvt_imm32 : Operand<i32> {
|
||||
|
@ -172,6 +172,7 @@ def t2ldr_pcrel_imm12 : Operand<i32> {
|
||||
// ADR instruction labels.
|
||||
def t2adrlabel : Operand<i32> {
|
||||
let EncoderMethod = "getT2AdrLabelOpValue";
|
||||
let PrintMethod = "printAdrLabelOperand";
|
||||
}
|
||||
|
||||
|
||||
|
@ -796,6 +796,13 @@ public:
|
||||
int64_t Value = CE->getValue();
|
||||
return Value > 0 && Value <= 32;
|
||||
}
|
||||
bool isAdrLabel() const {
|
||||
// If we have an immediate that's not a constant, treat it as a label
|
||||
// reference needing a fixup. If it is a constant, but it can't fit
|
||||
// into shift immediate encoding, we reject it.
|
||||
if (isImm() && !isa<MCConstantExpr>(getImm())) return true;
|
||||
else return (isARMSOImm() || isARMSOImmNeg());
|
||||
}
|
||||
bool isARMSOImm() const {
|
||||
if (!isImm()) return false;
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
@ -1644,6 +1651,22 @@ public:
|
||||
Inst.addOperand(MCOperand::CreateImm(Imm));
|
||||
}
|
||||
|
||||
void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
assert(isImm() && "Not an immediate!");
|
||||
|
||||
// If we have an immediate that's not a constant, treat it as a label
|
||||
// reference needing a fixup.
|
||||
if (!isa<MCConstantExpr>(getImm())) {
|
||||
Inst.addOperand(MCOperand::CreateExpr(getImm()));
|
||||
return;
|
||||
}
|
||||
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
int Val = CE->getValue();
|
||||
Inst.addOperand(MCOperand::CreateImm(Val));
|
||||
}
|
||||
|
||||
void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 2 && "Invalid number of operands!");
|
||||
Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
|
||||
|
@ -792,6 +792,25 @@ void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
|
||||
llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printAdrLabelOperand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &MO = MI->getOperand(OpNum);
|
||||
|
||||
if (MO.isExpr()) {
|
||||
O << *MO.getExpr();
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t OffImm = (int32_t)MO.getImm();
|
||||
|
||||
if (OffImm == INT32_MIN)
|
||||
O << "#-0";
|
||||
else if (OffImm < 0)
|
||||
O << "#-" << -OffImm;
|
||||
else
|
||||
O << "#" << OffImm;
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
|
||||
raw_ostream &O) {
|
||||
O << "#" << MI->getOperand(OpNum).getImm() * 4;
|
||||
|
@ -73,6 +73,7 @@ public:
|
||||
void printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printPKHASRShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
|
||||
void printAdrLabelOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printThumbSRImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
void printThumbITMask(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||
|
@ -641,8 +641,8 @@ getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
return Val;
|
||||
}
|
||||
|
||||
/// getAdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
|
||||
/// target.
|
||||
/// getAdrLabelOpValue - Return encoding info for 12-bit shifted-immediate
|
||||
/// ADR label target.
|
||||
uint32_t ARMMCCodeEmitter::
|
||||
getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
@ -652,15 +652,23 @@ getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
Fixups);
|
||||
int32_t offset = MO.getImm();
|
||||
uint32_t Val = 0x2000;
|
||||
if (offset < 0) {
|
||||
|
||||
if (offset == INT32_MIN) {
|
||||
Val = 0x1000;
|
||||
offset = 0;
|
||||
} else if (offset < 0) {
|
||||
Val = 0x1000;
|
||||
offset *= -1;
|
||||
}
|
||||
Val |= offset;
|
||||
|
||||
int SoImmVal = ARM_AM::getSOImmVal(offset);
|
||||
assert(SoImmVal != -1 && "Not a valid so_imm value!");
|
||||
|
||||
Val |= SoImmVal;
|
||||
return Val;
|
||||
}
|
||||
|
||||
/// getAdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
|
||||
/// getT2AdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
|
||||
/// target.
|
||||
uint32_t ARMMCCodeEmitter::
|
||||
getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
@ -670,14 +678,16 @@ getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_adr_pcrel_12,
|
||||
Fixups);
|
||||
int32_t Val = MO.getImm();
|
||||
if (Val < 0) {
|
||||
if (Val == INT32_MIN)
|
||||
Val = 0x1000;
|
||||
else if (Val < 0) {
|
||||
Val *= -1;
|
||||
Val |= 0x1000;
|
||||
}
|
||||
return Val;
|
||||
}
|
||||
|
||||
/// getAdrLabelOpValue - Return encoding info for 8-bit immediate ADR label
|
||||
/// getThumbAdrLabelOpValue - Return encoding info for 8-bit immediate ADR label
|
||||
/// target.
|
||||
uint32_t ARMMCCodeEmitter::
|
||||
getThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
|
@ -141,6 +141,14 @@ Lforward:
|
||||
@ CHECK: adr r2, #3 @ encoding: [0x03,0x20,0x8f,0xe2]
|
||||
@ CHECK: adr r2, #-3 @ encoding: [0x03,0x20,0x4f,0xe2]
|
||||
|
||||
adr r1, #-0x0
|
||||
adr r1, #-0x12000000
|
||||
adr r1, #0x12000000
|
||||
|
||||
@ CHECK: adr r1, #-0 @ encoding: [0x00,0x10,0x4f,0xe2]
|
||||
@ CHECK: adr r1, #-301989888 @ encoding: [0x12,0x14,0x4f,0xe2]
|
||||
@ CHECK: adr r1, #301989888 @ encoding: [0x12,0x14,0x8f,0xe2]
|
||||
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
@ ADD
|
||||
|
@ -135,9 +135,11 @@ _func:
|
||||
|
||||
subw r11, pc, #3270
|
||||
adr.w r11, #-826
|
||||
adr.w r1, #-0x0
|
||||
|
||||
@ CHECK: subw r11, pc, #3270 @ encoding: [0xaf,0xf6,0xc6,0x4b]
|
||||
@ CHECK: adr.w r11, #-826 @ encoding: [0xaf,0xf2,0x3a,0x3b]
|
||||
@ CHECK: adr.w r1, #-0 @ encoding: [0xaf,0xf2,0x00,0x01]
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
@ AND (immediate)
|
||||
|
@ -169,9 +169,15 @@
|
||||
#------------------------------------------------------------------------------
|
||||
# CHECK: add r2, pc, #3
|
||||
# CHECK: sub r2, pc, #3
|
||||
# CHECK: sub r1, pc, #0
|
||||
# CHECK: sub r1, pc, #301989888
|
||||
# CHECK: add r1, pc, #301989888
|
||||
|
||||
0x03 0x20 0x8f 0xe2
|
||||
0x03 0x20 0x4f 0xe2
|
||||
0x00 0x10 0x4f 0xe2
|
||||
0x12 0x14 0x4f 0xe2
|
||||
0x12 0x14 0x8f 0xe2
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# AND
|
||||
|
@ -92,9 +92,11 @@
|
||||
#------------------------------------------------------------------------------
|
||||
# CHECK: subw r11, pc, #3270
|
||||
# CHECK: subw r11, pc, #826
|
||||
# CHECK: subw r1, pc, #0
|
||||
|
||||
0xaf 0xf6 0xc6 0x4b
|
||||
0xaf 0xf2 0x3a 0x3b
|
||||
0xaf 0xf2 0x00 0x01
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# AND (immediate)
|
||||
|
Loading…
Reference in New Issue
Block a user