Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -988,7 +988,7 @@ 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)); @@ -1086,7 +1086,8 @@ bool isRegIdx() const { return Kind == k_RegisterIndex; } bool isImm() const override { return Kind == k_Immediate; } bool isConstantImm() const { - return isImm() && isa(getImm()); + int64_t Res; + return isImm() && getImm()->evaluateAsAbsolute(Res); } bool isConstantImmz() const { return isConstantImm() && getConstantImm() == 0; @@ -1251,7 +1252,9 @@ int64_t getConstantImm() const { const MCExpr *Val = getImm(); - return static_cast(Val)->getValue(); + int64_t Value = 0; + (void)Val->evaluateAsAbsolute(Value); + return Value; } MipsOperand *getMemBase() const { @@ -3997,6 +4000,9 @@ 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"); Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -450,6 +450,16 @@ let DiagnosticType = "UImm" # Bits; } +// Generic case - only to support certain assembly pseudo instructions. +class UImmAnyAsmOperandClass 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. @@ -473,8 +483,13 @@ // 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"; @@ -491,6 +506,8 @@ 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 @@ -845,6 +862,10 @@ let ParserMatchClass = !cast("SImm16AsmOperandClass"); } +// like simm32 but coerces simm32 to uimm32. +def uimm32_coerced : Operand { + let ParserMatchClass = !cast("UImm32CoercedAsmOperandClass"); +} // Like simm32 but coerces uimm32 to simm32. def simm32_relaxed : Operand { let DecoderMethod = "DecodeSImmWithOffsetAndScale<32>"; @@ -2364,7 +2385,7 @@ class LoadImmediate32 : 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 : Index: test/MC/Mips/macro-li-bad.s =================================================================== --- test/MC/Mips/macro-li-bad.s +++ 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 Index: test/MC/Mips/macro-li.s =================================================================== --- test/MC/Mips/macro-li.s +++ test/MC/Mips/macro-li.s @@ -65,3 +65,11 @@ # 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]