Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1101,22 +1101,38 @@ } // for } // if load/store - if (inMicroMipsMode() && (Inst.getOpcode() == Mips::ADDIUS5_MM || - Inst.getOpcode() == Mips::ADDIUSP_MM)) { - if (Inst.getOpcode() == Mips::ADDIUS5_MM) { - MCOperand Opnd = Inst.getOperand(2); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - int Imm = Opnd.getImm(); - if (Imm < -8 || Imm > 7) - return Error(IDLoc, "immediate operand value out of range"); - } else { - MCOperand Opnd = Inst.getOperand(0); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - int Imm = Opnd.getImm(); - if (Imm < -258 || Imm > 257 || (Imm < 2 && Imm > -3)) - return Error(IDLoc, "unexpected immediate operand value"); + if (inMicroMipsMode()) { + MCOperand Opnd; + int Imm; + + switch (Inst.getOpcode()) { + default: + break; + case Mips::ADDIUS5_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < -8 || Imm > 7) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::ADDIUSP_MM: + Opnd = Inst.getOperand(0); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < -258 || Imm > 257 || (Imm < 2 && Imm > -3)) + return Error(IDLoc, "unexpected immediate operand value"); + break; + case Mips::SLL16_MM: + case Mips::SRL16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 1 || Imm > 7) + 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 @@ -163,6 +163,10 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned getEncodedShiftImm(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 @@ -699,4 +699,13 @@ return 0; } +unsigned +MipsMCCodeEmitter::getEncodedShiftImm(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + assert(MI.getOperand(OpNo).isImm()); + const MCOperand &MO = MI.getOperand(OpNo); + return MO.getImm() % 8; +} + #include "MipsGenMCCodeEmitter.inc" Index: lib/Target/Mips/MicroMipsInstrFormats.td =================================================================== --- lib/Target/Mips/MicroMipsInstrFormats.td +++ lib/Target/Mips/MicroMipsInstrFormats.td @@ -67,6 +67,20 @@ let Inst{2-0} = rs; } +class SHIFT_FM_MM funct> { + bits<3> rd; + bits<3> rt; + bits<3> shamt; + + bits<16> Inst; + + let Inst{15-10} = 0x09; + let Inst{9-7} = rd; + let Inst{6-4} = rt; + let Inst{3-1} = shamt; + let Inst{0} = funct; +} + class ADDIUS5_FM_MM16 { bits<5> rd; bits<4> imm; Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -16,6 +16,12 @@ let EncoderMethod = "getAddiuspValue"; } +def shift_imm3 : Operand { + let EncoderMethod = "getEncodedShiftImm"; +} + +def shift_immZExt3 : ImmLeaf= 0 && Imm <= 8;}]>; + def mem_mm_12 : Operand { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops GPR32, simm12); @@ -118,6 +124,14 @@ let isCommutable = 0; } +class ShiftIMM16 : + MicroMipsInst16<(outs RO:$rd), (ins RO:$rt, ImmOpnd:$shamt), + !strconcat(opstr, "\t$rd, $rt, $shamt"), + [(set RO:$rd, (OpNode RO:$rt, PF:$shamt))], Itin, FrmR>; + class AddImmUS5 : MicroMipsInst16<(outs RO:$dst), (ins RO:$rd, addius5_imm:$imm), !strconcat(opstr, "\t$rd, $imm"), [], NoItinerary, FrmR> { @@ -219,6 +233,10 @@ def XOR16_MM : LogicRMM16<"xor16", GPRMM16Opnd, II_XOR, xor>, LOGIC_FM_MM16<0x1>; def NOT16_MM : NotMM16<"not16", GPRMM16Opnd>, LOGIC_FM_MM16<0x0>; +def SLL16_MM : ShiftIMM16<"sll16", shift_imm3, GPRMM16Opnd, shl, + shift_immZExt3, II_SLL>, SHIFT_FM_MM<0>; +def SRL16_MM : ShiftIMM16<"srl16", shift_imm3, GPRMM16Opnd, srl, + shift_immZExt3, II_SRL>, SHIFT_FM_MM<1>; def ADDIUS5_MM : AddImmUS5<"addius5", GPR32Opnd>, ADDIUS5_FM_MM16; def ADDIUSP_MM : AddImmUSP<"addiusp">, ADDIUSP_FM_MM16; def MFHI16_MM : MoveFromHILOMM<"mfhi", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x10>; Index: lib/Target/Mips/MipsCodeEmitter.cpp =================================================================== --- lib/Target/Mips/MipsCodeEmitter.cpp +++ lib/Target/Mips/MipsCodeEmitter.cpp @@ -128,6 +128,7 @@ unsigned getLSAImmEncoding(const MachineInstr &MI, unsigned OpNo) const; unsigned getSimm19Lsl2Encoding(const MachineInstr &MI, unsigned OpNo) const; unsigned getSimm18Lsl3Encoding(const MachineInstr &MI, unsigned OpNo) const; + unsigned getEncodedShiftImm(const MachineInstr &MI, unsigned OpNo) const; /// Expand pseudo instructions with accumulator register operands. void expandACCInstr(MachineBasicBlock::instr_iterator MI, @@ -311,6 +312,12 @@ return 0; } +unsigned MipsCodeEmitter::getEncodedShiftImm(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 @@ -15,6 +15,8 @@ # CHECK-EL: not16 $17, $3 # encoding: [0x0b,0x44] # CHECK-EL: or16 $16, $4 # encoding: [0xc4,0x44] # CHECK-EL: xor16 $17, $5 # encoding: [0x4d,0x44] +# CHECK-EL: sll16 $3, $16, 5 # encoding: [0x8a,0x25] +# CHECK-EL: srl16 $4, $17, 6 # encoding: [0x1d,0x26] # CHECK-EL: addius5 $7, -2 # encoding: [0xfc,0x4c] # CHECK-EL: addiusp -255 # encoding: [0x03,0x4e] # CHECK-EL: mfhi $9 # encoding: [0x09,0x46] @@ -38,6 +40,8 @@ # CHECK-EB: not16 $17, $3 # encoding: [0x44,0x0b] # CHECK-EB: or16 $16, $4 # encoding: [0x44,0xc4] # CHECK-EB: xor16 $17, $5 # encoding: [0x44,0x4d] +# CHECK-EB: sll16 $3, $16, 5 # encoding: [0x25,0x8a] +# CHECK-EB: srl16 $4, $17, 6 # encoding: [0x26,0x1d] # CHECK-EB: addius5 $7, -2 # encoding: [0x4c,0xfc] # CHECK-EB: addiusp -255 # encoding: [0x4e,0x03] # CHECK-EB: mfhi $9 # encoding: [0x46,0x09] @@ -59,6 +63,8 @@ not16 $17, $3 or16 $16, $4 xor16 $17, $5 + sll16 $3, $16, 5 + srl16 $4, $17, 6 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 @@ -7,3 +7,7 @@ not16 $18, $9 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction or16 $16, $10 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction xor16 $15, $5 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + sll16 $1, $16, 5 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + 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