Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1146,6 +1146,14 @@ if (UImm > 60) return Error(IDLoc, "immediate operand value out of range"); break; + case Mips::LI16_MM: + Opnd = Inst.getOperand(1); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < -1 || Imm > 126) + return Error(IDLoc, "immediate operand value out of range"); + break; } } Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -169,6 +169,9 @@ unsigned getEncodedShiftImm(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned getLoadImm7Value(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; unsigned getExprOpValue(const MCExpr *Expr, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -722,4 +722,14 @@ return MO.getImm() % 8; } +unsigned +MipsMCCodeEmitter::getLoadImm7Value(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + assert(MI.getOperand(OpNo).isImm()); + const MCOperand &MO = MI.getOperand(OpNo); + int Value = MO.getImm(); + return Value & 0x7f; +} + #include "MipsGenMCCodeEmitter.inc" Index: lib/Target/Mips/MicroMipsInstrFormats.td =================================================================== --- lib/Target/Mips/MicroMipsInstrFormats.td +++ lib/Target/Mips/MicroMipsInstrFormats.td @@ -126,6 +126,17 @@ let Inst{4-0} = rs; } +class LI_FM_MM16 { + bits<3> rd; + bits<7> imm; + + bits<16> Inst; + + let Inst{15-10} = 0x3b; + let Inst{9-7} = rd; + let Inst{6-0} = imm; +} + class JALR_FM_MM16 op> { bits<5> rs; Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -24,6 +24,11 @@ def shift_immZExt3 : ImmLeaf= 0 && Imm <= 8;}]>; +def li_imm7 : Operand { + let EncoderMethod = "getLoadImm7Value"; +} +def li_ImmLeaf : ImmLeaf= -1 && Imm <= 126;}]>; + def mem_mm_4 : Operand { let PrintMethod = "printMemOperand"; let EncoderMethod = "getMemEncodingMMImm4"; @@ -188,6 +193,13 @@ let isReMaterializable = 1; } +class LoadImmMM16 : + MicroMipsInst16<(outs RO:$rd), (ins Od:$imm), + !strconcat(opstr, "\t$rd, $imm"), [], NoItinerary, FrmI> { + let isReMaterializable = 1; +} + // 16-bit Jump and Link (Call) class JumpLinkRegMM16 : MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), @@ -282,6 +294,8 @@ def MFHI16_MM : MoveFromHILOMM<"mfhi", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x10>; def MFLO16_MM : MoveFromHILOMM<"mflo", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x12>; def MOVE16_MM : MoveMM16<"move", GPR32Opnd>, MOVE_FM_MM16<0x03>; +def LI16_MM : LoadImmMM16<"li16", li_imm7, GPRMM16Opnd, li_ImmLeaf>, + LI_FM_MM16, IsAsCheapAsAMove; def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>; def JALRS16_MM : JumpLinkRegSMM16<"jalrs", GPR32Opnd>, JALR_FM_MM16<0x09>; def JRC16_MM : JumpLinkRegCMM16<"jrc", GPR32Opnd>, JALR_FM_MM16<0x0d>; Index: lib/Target/Mips/MipsCodeEmitter.cpp =================================================================== --- lib/Target/Mips/MipsCodeEmitter.cpp +++ lib/Target/Mips/MipsCodeEmitter.cpp @@ -130,6 +130,7 @@ unsigned getSimm19Lsl2Encoding(const MachineInstr &MI, unsigned OpNo) const; unsigned getSimm18Lsl3Encoding(const MachineInstr &MI, unsigned OpNo) const; unsigned getEncodedShiftImm(const MachineInstr &MI, unsigned OpNo) const; + unsigned getLoadImm7Value(const MachineInstr &MI, unsigned OpNo) const; /// Expand pseudo instructions with accumulator register operands. void expandACCInstr(MachineBasicBlock::instr_iterator MI, @@ -325,6 +326,12 @@ return 0; } +unsigned MipsCodeEmitter::getLoadImm7Value(const MachineInstr &MI, + unsigned OpNo) const { + llvm_unreachable("Unimplemented function."); + return 0; +} + /// getMachineOpValue - Return binary encoding of operand. If the machine /// operand requires relocation, record the relocation and return zero. unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI, Index: test/MC/Mips/micromips-16-bit-instructions.s =================================================================== --- test/MC/Mips/micromips-16-bit-instructions.s +++ test/MC/Mips/micromips-16-bit-instructions.s @@ -22,6 +22,8 @@ # CHECK-EL: sb16 $3, 4($16) # encoding: [0x81,0x89] # CHECK-EL: sh16 $4, 8($17) # encoding: [0x12,0xaa] # CHECK-EL: sw16 $4, 4($17) # encoding: [0x11,0xea] +# CHECK-EL: li16 $3, -1 # encoding: [0xff,0xed] +# CHECK-EL: li16 $3, 126 # encoding: [0xfe,0xed] # CHECK-EL: addius5 $7, -2 # encoding: [0xfc,0x4c] # CHECK-EL: addiusp -255 # encoding: [0x03,0x4e] # CHECK-EL: mfhi $9 # encoding: [0x09,0x46] @@ -52,6 +54,8 @@ # CHECK-EB: sb16 $3, 4($16) # encoding: [0x89,0x81] # CHECK-EB: sh16 $4, 8($17) # encoding: [0xaa,0x12] # CHECK-EB: sw16 $4, 4($17) # encoding: [0xea,0x11] +# CHECK-EB: li16 $3, -1 # encoding: [0xed,0xff] +# CHECK-EB: li16 $3, 126 # encoding: [0xed,0xfe] # CHECK-EB: addius5 $7, -2 # encoding: [0x4c,0xfc] # CHECK-EB: addiusp -255 # encoding: [0x4e,0x03] # CHECK-EB: mfhi $9 # encoding: [0x46,0x09] @@ -80,6 +84,8 @@ sb16 $3, 4($16) sh16 $4, 8($17) sw16 $4, 4($17) + li16 $3, -1 + li16 $3, 126 addius5 $7, -2 addiusp -255 mfhi $9 Index: test/MC/Mips/micromips-invalid.s =================================================================== --- test/MC/Mips/micromips-invalid.s +++ test/MC/Mips/micromips-invalid.s @@ -21,3 +21,5 @@ sb16 $3, 64($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range sh16 $4, 68($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range sw16 $4, 64($17) # 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