Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1080,6 +1080,11 @@ return isConstantImm() && isShiftedUInt(getConstantImm()); } + template + bool isScaledSImm() const { + return isConstantImm() && + isShiftedInt(getConstantImm()); + } bool isRegList16() const { if (!isRegList()) return false; @@ -3767,6 +3772,12 @@ case Match_UImm7_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 7-bit unsigned immediate"); + case Match_UImm7_N1: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected immediate in range -1 .. 126"); + case Match_SImm7_Lsl2: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected both 9-bit signed immediate and multiple of 4"); case Match_UImm8_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 8-bit unsigned immediate"); Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -362,7 +362,12 @@ uint64_t Address, const void *Decoder); -static DecodeStatus DecodeLiSimm7(MCInst &Inst, +static DecodeStatus DecodeUImm6Lsl2(MCInst &Inst, + unsigned Value, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeLi16Imm(MCInst &Inst, unsigned Value, uint64_t Address, const void *Decoder); @@ -390,9 +395,10 @@ Decoder); } -template -static DecodeStatus DecodeSImmWithOffset(MCInst &Inst, unsigned Value, - uint64_t Address, const void *Decoder); +template +static DecodeStatus DecodeSImmWithOffsetAndScale(MCInst &Inst, unsigned Value, + uint64_t Address, + const void *Decoder); static DecodeStatus DecodeInsSize(MCInst &Inst, unsigned Insn, @@ -1897,7 +1903,7 @@ return MCDisassembler::Success; } -static DecodeStatus DecodeLiSimm7(MCInst &Inst, +static DecodeStatus DecodeLi16Imm(MCInst &Inst, unsigned Value, uint64_t Address, const void *Decoder) { @@ -1934,11 +1940,11 @@ return MCDisassembler::Success; } -template -static DecodeStatus DecodeSImmWithOffset(MCInst &Inst, unsigned Value, - uint64_t Address, - const void *Decoder) { - int32_t Imm = SignExtend32(Value); +template +static DecodeStatus DecodeSImmWithOffsetAndScale(MCInst &Inst, unsigned Value, + uint64_t Address, + const void *Decoder) { + int32_t Imm = SignExtend32(Value) * ScaleBy; Inst.addOperand(MCOperand::createImm(Imm + Offset)); return MCDisassembler::Success; } Index: lib/Target/Mips/MicroMips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrInfo.td +++ lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -821,7 +821,7 @@ MMR6Arch<"srl16">; class BREAK16_MMR6_DESC : BrkSdbbp16MM<"break16">, MMR6Arch<"srl16">, MicroMipsR6Inst16; -class LI16_MMR6_DESC : LoadImmMM16<"li16", li_simm7, GPRMM16Opnd>, +class LI16_MMR6_DESC : LoadImmMM16<"li16", li16_imm, GPRMM16Opnd>, MMR6Arch<"srl16">, MicroMipsR6Inst16, IsAsCheapAsAMove; class MOVE16_MMR6_DESC : MoveMM16<"move16", GPR32Opnd>, MMR6Arch<"srl16">, MicroMipsR6Inst16; Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -1,11 +1,6 @@ def addrimm12 : ComplexPattern; def addrimm4lsl2 : ComplexPattern; -def simm7 : Operand; -def li_simm7 : Operand { - let DecoderMethod = "DecodeLiSimm7"; -} - def simm12 : Operand { let DecoderMethod = "DecodeSimm12"; } @@ -88,7 +83,7 @@ def mem_mm_gp_imm7_lsl2 : Operand { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops GPRMM16:$base, simm7:$offset); + let MIOperandInfo = (ops GPRMM16:$base, simm7_lsl2:$offset); let OperandType = "OPERAND_MEMORY"; let EncoderMethod = "getMemEncodingMMGPImm7Lsl2"; } @@ -621,7 +616,7 @@ def MFLO16_MM : MoveFromHILOMM<"mflo", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x12>; def MOVE16_MM : MoveMM16<"move", GPR32Opnd>, MOVE_FM_MM16<0x03>; def MOVEP_MM : MovePMM16<"movep", GPRMM16OpndMoveP>, MOVEP_FM_MM16; -def LI16_MM : LoadImmMM16<"li16", li_simm7, GPRMM16Opnd>, LI_FM_MM16, +def LI16_MM : LoadImmMM16<"li16", li16_imm, GPRMM16Opnd>, LI_FM_MM16, IsAsCheapAsAMove; def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>, ISA_MICROMIPS32_NOT_MIPS32R6; Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -457,10 +457,23 @@ : UImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]>; def ConstantUImm10AsmOperandClass : ConstantUImmAsmOperandClass<10, [UImm16AsmOperandClass]>; +def ConstantSImm7Lsl2AsmOperandClass : AsmOperandClass { + let Name = "SImm7Lsl2"; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isScaledSImm<7, 2>"; + let SuperClasses = [ConstantUImm10AsmOperandClass]; + let DiagnosticType = "SImm7_Lsl2"; +} def ConstantUImm8AsmOperandClass - : ConstantUImmAsmOperandClass<8, [ConstantUImm10AsmOperandClass]>; + : ConstantUImmAsmOperandClass<8, [ConstantSImm7Lsl2AsmOperandClass]>; +def ConstantUImm7Sub1AsmOperandClass + : ConstantUImmAsmOperandClass<7, [ConstantUImm8AsmOperandClass], -1> { + // Specify the names since the -1 offset causes invalid identifiers otherwise. + let Name = "UImm7_N1"; + let DiagnosticType = "UImm7_N1"; +} def ConstantUImm7AsmOperandClass - : ConstantUImmAsmOperandClass<7, [ConstantUImm8AsmOperandClass]>; + : ConstantUImmAsmOperandClass<7, [ConstantUImm7Sub1AsmOperandClass]>; def ConstantUImm6Lsl2AsmOperandClass : AsmOperandClass { let Name = "UImm6Lsl2"; let RenderMethod = "addImmOperands"; @@ -724,11 +737,23 @@ // Signed operands foreach I = {4, 5} in def simm # I : Operand { - let DecoderMethod = "DecodeSImmWithOffset<" # I # ">"; + let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">"; let ParserMatchClass = !cast("ConstantSImm" # I # "AsmOperandClass"); } +def simm7_lsl2 : Operand { + let EncoderMethod = "getSImm7Lsl2Encoding"; + let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ", 0, 4>"; + let ParserMatchClass = ConstantSImm7Lsl2AsmOperandClass; +} + +// This is almost the same as a uimm7 but 0x7f is interpreted as -1. +def li16_imm : Operand { + let DecoderMethod = "DecodeLi16Imm"; + let ParserMatchClass = ConstantUImm7Sub1AsmOperandClass; +} + def pcrel16 : Operand { } Index: test/MC/Mips/micromips-invalid.s =================================================================== --- test/MC/Mips/micromips-invalid.s +++ test/MC/Mips/micromips-invalid.s @@ -17,8 +17,6 @@ srl16 $4, $9, 6 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction sll16 $3, $16, 9 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range srl16 $4, $5, 15 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range - li16 $8, -1 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction - li16 $4, -2 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range addiur2 $9, $7, -1 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction addiur2 $6, $7, 10 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range lwm16 $5, $6, $ra, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: $16 or $31 expected Index: test/MC/Mips/micromips/invalid.s =================================================================== --- test/MC/Mips/micromips/invalid.s +++ test/MC/Mips/micromips/invalid.s @@ -27,6 +27,8 @@ jraddiusp -4 # CHECK: :[[@LINE]]:13: error: expected both 7-bit unsigned immediate and multiple of 4 jraddiusp 125 # CHECK: :[[@LINE]]:13: error: expected both 7-bit unsigned immediate and multiple of 4 jraddiusp 128 # CHECK: :[[@LINE]]:13: error: expected both 7-bit unsigned immediate and multiple of 4 + li16 $4, -2 # CHECK: :[[@LINE]]:12: error: expected immediate in range -1 .. 126 + li16 $4, 127 # CHECK: :[[@LINE]]:12: error: expected immediate in range -1 .. 126 pref -1, 255($7) # CHECK: :[[@LINE]]:8: error: expected 5-bit unsigned immediate pref 32, 255($7) # CHECK: :[[@LINE]]:8: error: expected 5-bit unsigned immediate rotr $2, $3, 32 # CHECK: :[[@LINE]]:16: error: expected 5-bit unsigned immediate Index: test/MC/Mips/micromips32r6/invalid.s =================================================================== --- test/MC/Mips/micromips32r6/invalid.s +++ test/MC/Mips/micromips32r6/invalid.s @@ -45,6 +45,8 @@ lhu16 $3, 64($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range lhu16 $3, 64($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range lhu16 $16, 4($9) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + li16 $4, -2 # CHECK: :[[@LINE]]:12: error: expected immediate in range -1 .. 126 + li16 $4, 127 # CHECK: :[[@LINE]]:12: error: expected immediate in range -1 .. 126 lsa $4, $2, $3, 0 # CHECK: :[[@LINE]]:21: error: expected immediate in range 1 .. 4 lsa $4, $2, $3, 5 # CHECK: :[[@LINE]]:21: error: expected immediate in range 1 .. 4 lw16 $9, 8($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction Index: test/MC/Mips/micromips32r6/valid.s =================================================================== --- test/MC/Mips/micromips32r6/valid.s +++ test/MC/Mips/micromips32r6/valid.s @@ -188,7 +188,11 @@ sqrt.d $f2, $f4 # CHECK: sqrt.d $f2, $f4 # encoding: [0x54,0x44,0x4a,0x3b] rsqrt.s $f3, $f5 # CHECK: rsqrt.s $f3, $f5 # encoding: [0x54,0x65,0x02,0x3b] rsqrt.d $f2, $f4 # CHECK: rsqrt.d $f2, $f4 # encoding: [0x54,0x44,0x42,0x3b] + lw $3, -260($gp) # CHECK: lw $3, -260($gp) # encoding: [0xfc,0x7c,0xfe,0xfc] + lw $3, -256($gp) # CHECK: lw $3, -256($gp) # encoding: [0x65,0xc0] lw $3, 32($gp) # CHECK: lw $3, 32($gp) # encoding: [0x65,0x88] + lw $3, 252($gp) # CHECK: lw $3, 252($gp) # encoding: [0x65,0xbf] + lw $3, 256($gp) # CHECK: lw $3, 256($gp) # encoding: [0xfc,0x7c,0x01,0x00] lw $3, 24($sp) # CHECK: lw $3, 24($sp) # encoding: [0x48,0x66] lw $3, 124($sp) # CHECK: lw $3, 124($sp) # encoding: [0x48,0x7f] lw $3, 128($sp) # CHECK: lw $3, 128($sp) # encoding: [0xfc,0x7d,0x00,0x80] Index: test/MC/Mips/micromips64r6/invalid.s =================================================================== --- test/MC/Mips/micromips64r6/invalid.s +++ test/MC/Mips/micromips64r6/invalid.s @@ -62,6 +62,8 @@ lhu16 $3, 64($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range lhu16 $3, 64($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range lhu16 $16, 4($9) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + li16 $4, -2 # CHECK: :[[@LINE]]:12: error: expected immediate in range -1 .. 126 + li16 $4, 127 # CHECK: :[[@LINE]]:12: error: expected immediate in range -1 .. 126 lsa $4, $2, $3, 0 # CHECK: :[[@LINE]]:21: error: expected immediate in range 1 .. 4 lsa $4, $2, $3, 5 # CHECK: :[[@LINE]]:21: error: expected immediate in range 1 .. 4 lw16 $9, 8($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction