summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp12
-rw-r--r--llvm/lib/Target/Mips/MipsInstrInfo.td28
-rw-r--r--llvm/test/MC/Mips/macro-li-bad.s4
-rw-r--r--llvm/test/MC/Mips/macro-li.s8
4 files changed, 44 insertions, 8 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 58562f99d5f..e4b2a40fba6 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -995,7 +995,7 @@ public:
void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
uint64_t Imm = getConstantImm() - Offset;
- Imm &= (1 << Bits) - 1;
+ Imm &= (1ULL << Bits) - 1;
Imm += Offset;
Imm += AdjustOffset;
Inst.addOperand(MCOperand::createImm(Imm));
@@ -1093,7 +1093,8 @@ public:
bool isRegIdx() const { return Kind == k_RegisterIndex; }
bool isImm() const override { return Kind == k_Immediate; }
bool isConstantImm() const {
- return isImm() && isa<MCConstantExpr>(getImm());
+ int64_t Res;
+ return isImm() && getImm()->evaluateAsAbsolute(Res);
}
bool isConstantImmz() const {
return isConstantImm() && getConstantImm() == 0;
@@ -1264,7 +1265,9 @@ public:
int64_t getConstantImm() const {
const MCExpr *Val = getImm();
- return static_cast<const MCConstantExpr *>(Val)->getValue();
+ int64_t Value = 0;
+ (void)Val->evaluateAsAbsolute(Value);
+ return Value;
}
MipsOperand *getMemBase() const {
@@ -4051,6 +4054,9 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_SImm32_Relaxed:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 32-bit signed immediate");
+ case Match_UImm32_Coerced:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 32-bit immediate");
case Match_MemSImm9:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected memory with 9-bit signed offset");
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td
index 51fe46953b2..3f3885443f7 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.td
@@ -467,6 +467,16 @@ class UImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []>
let DiagnosticType = "UImm" # Bits;
}
+// Generic case - only to support certain assembly pseudo instructions.
+class UImmAnyAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []>
+ : AsmOperandClass {
+ let Name = "ImmAny";
+ let RenderMethod = "addConstantUImmOperands<32>";
+ let PredicateMethod = "isSImm<" # Bits # ">";
+ let SuperClasses = Supers;
+ let DiagnosticType = "ImmAny";
+}
+
// AsmOperandClasses require a strict ordering which is difficult to manage
// as a hierarchy. Instead, we use a linear ordering and impose an order that
// is in some places arbitrary.
@@ -490,8 +500,13 @@ class UImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []>
// uimm5 < uimm5_64, and uimm5 < vsplat_uimm5
// This is entirely arbitrary. We need an ordering and what we pick is
// unimportant since only one is possible for a given mnemonic.
+
+def UImm32CoercedAsmOperandClass : UImmAnyAsmOperandClass<33, []> {
+ let Name = "UImm32_Coerced";
+ let DiagnosticType = "UImm32_Coerced";
+}
def SImm32RelaxedAsmOperandClass
- : SImmAsmOperandClass<32, []> {
+ : SImmAsmOperandClass<32, [UImm32CoercedAsmOperandClass]> {
let Name = "SImm32_Relaxed";
let PredicateMethod = "isAnyImm<32>";
let DiagnosticType = "SImm32_Relaxed";
@@ -515,6 +530,8 @@ def UImm16RelaxedAsmOperandClass
let PredicateMethod = "isAnyImm<16>";
let DiagnosticType = "UImm16_Relaxed";
}
+// FIXME: One of these should probably have UImm16AsmOperandClass as the
+// superclass instead of UImm16RelaxedasmOPerandClass.
def UImm16AsmOperandClass
: UImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]>;
def SImm16RelaxedAsmOperandClass
@@ -872,6 +889,10 @@ def simm16_64 : Operand<i64> {
let ParserMatchClass = !cast<AsmOperandClass>("SImm16AsmOperandClass");
}
+// like simm32 but coerces simm32 to uimm32.
+def uimm32_coerced : Operand<i32> {
+ let ParserMatchClass = !cast<AsmOperandClass>("UImm32CoercedAsmOperandClass");
+}
// Like simm32 but coerces uimm32 to simm32.
def simm32_relaxed : Operand<i32> {
let DecoderMethod = "DecodeSImmWithOffsetAndScale<32>";
@@ -2387,11 +2408,12 @@ def : MipsInstAlias<"sync",
// Assembler Pseudo Instructions
//===----------------------------------------------------------------------===//
-// We use i32imm on li/la to defer range checking to the assembler.
+// We use uimm32_coerced to accept a 33 bit signed number that is rendered into
+// a 32 bit number.
class LoadImmediate32<string instr_asm, Operand Od, RegisterOperand RO> :
MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32),
!strconcat(instr_asm, "\t$rt, $imm32")> ;
-def LoadImm32 : LoadImmediate32<"li", i32imm, GPR32Opnd>;
+def LoadImm32 : LoadImmediate32<"li", uimm32_coerced, GPR32Opnd>;
class LoadAddressFromReg32<string instr_asm, Operand MemOpnd,
RegisterOperand RO> :
diff --git a/llvm/test/MC/Mips/macro-li-bad.s b/llvm/test/MC/Mips/macro-li-bad.s
index 8fe622066e9..29eedce713a 100644
--- a/llvm/test/MC/Mips/macro-li-bad.s
+++ b/llvm/test/MC/Mips/macro-li-bad.s
@@ -7,5 +7,5 @@
.text
li $5, 0x100000000
- # 32-BIT: :[[@LINE-1]]:3: error: instruction requires a 32-bit immediate
- # 64-BIT: :[[@LINE-2]]:3: error: instruction requires a 32-bit immediate
+ # 32-BIT: :[[@LINE-1]]:10: error: expected 32-bit immediate
+ # 64-BIT: :[[@LINE-2]]:10: error: expected 32-bit immediate
diff --git a/llvm/test/MC/Mips/macro-li.s b/llvm/test/MC/Mips/macro-li.s
index 88e013a854e..6cdc11d70d2 100644
--- a/llvm/test/MC/Mips/macro-li.s
+++ b/llvm/test/MC/Mips/macro-li.s
@@ -65,3 +65,11 @@ li $5, 0xc0008000 # CHECK: lui $5, 49152 # encoding: [0x3c,0x05,0xc0,0x00
# CHECK: ori $5, $5, 32768 # encoding: [0x34,0xa5,0x80,0x00]
li $5, 0x80008000 # CHECK: lui $5, 32768 # encoding: [0x3c,0x05,0x80,0x00]
# CHECK: ori $5, $5, 32768 # encoding: [0x34,0xa5,0x80,0x00]
+li $4, ~0xffffffff # CHECK; addiu $4, $zero, 0 # encoding: [0x24,0x04,0x00,0x00]
+li $4, ~0x80000001 # CHECK: lui $4, 32767 # encoding: [0x3c,0x04,0x7f,0xff]
+ # CHECK: ori $4, $4, 65534 # encoding: [0x34,0x84,0xff,0xfe]
+li $4, ~0x80000000 # CHECK: lui $4, 32767 # encoding: [0x3c,0x04,0x7f,0xff]
+ # CHECK: ori $4, $4, 65535 # encoding: [0x34,0x84,0xff,0xff]
+li $4, ~0x7fffffff # CHECK: lui $4, 32768 # encoding: [0x3c,0x04,0x80,0x00]
+li $4, ~0x00000001 # CHECK: addiu $4, $zero, -2 # encoding: [0x24,0x04,0xff,0xfe]
+li $4, ~0x00000000 # CHECK: addiu $4, $zero, -1 # encoding: [0x24,0x04,0xff,0xff]
OpenPOWER on IntegriCloud