Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1226,6 +1226,16 @@ if (Imm < 0 || Imm > 255) return Error(IDLoc, "immediate operand value out of range"); break; + case Mips::ANDI16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 || + Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 || + Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535)) + 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 @@ -173,6 +173,9 @@ unsigned getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned getUImm4AndValue(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 @@ -757,4 +757,32 @@ return MO.getImm() % 8; } +unsigned +MipsMCCodeEmitter::getUImm4AndValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + assert(MI.getOperand(OpNo).isImm()); + const MCOperand &MO = MI.getOperand(OpNo); + unsigned Value = MO.getImm(); + switch (Value) { + case 128: return 0x0; + case 1: return 0x1; + case 2: return 0x2; + case 3: return 0x3; + case 4: return 0x4; + case 7: return 0x5; + case 8: return 0x6; + case 15: return 0x7; + case 16: return 0x8; + case 31: return 0x9; + case 32: return 0xa; + case 63: return 0xb; + case 64: return 0xc; + case 255: return 0xd; + case 32768: return 0xe; + case 65535: return 0xf; + default: assert(0 && "Unexpected value"); + } +} + #include "MipsGenMCCodeEmitter.inc" Index: lib/Target/Mips/MicroMipsInstrFormats.td =================================================================== --- lib/Target/Mips/MicroMipsInstrFormats.td +++ lib/Target/Mips/MicroMipsInstrFormats.td @@ -55,6 +55,19 @@ let Inst{0} = funct; } +class ANDI_FM_MM16 funct> { + bits<3> rd; + bits<3> rs; + bits<4> imm; + + bits<16> Inst; + + let Inst{15-10} = funct; + let Inst{9-7} = rd; + let Inst{6-4} = rs; + let Inst{3-0} = imm; +} + class LOGIC_FM_MM16 funct> { bits<3> rt; bits<3> rs; Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -26,6 +26,10 @@ let EncoderMethod = "getUImm3Mod8Encoding"; } +def uimm4_andi : Operand { + let EncoderMethod = "getUImm4AndValue"; +} + def immZExt2Shift : ImmLeaf= 1 && Imm <= 8;}]>; class mem_mm_4_generic : Operand { @@ -131,6 +135,11 @@ let isCommutable = isComm; } +class AndImmMM16 : + MicroMipsInst16<(outs RO:$rd), (ins RO:$rs, uimm4_andi:$imm), + !strconcat(opstr, "\t$rd, $rs, $imm"), [], Itin, FrmI>; + class LogicRMM16 : @@ -269,6 +278,7 @@ ARITH_FM_MM16<0>; def SUBU16_MM : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>, ARITH_FM_MM16<1>; +def ANDI16_MM : AndImmMM16<"andi16", GPRMM16Opnd, II_AND>, ANDI_FM_MM16<0x0b>; def AND16_MM : LogicRMM16<"and16", GPRMM16Opnd, II_AND, and>, LOGIC_FM_MM16<0x2>; def OR16_MM : LogicRMM16<"or16", GPRMM16Opnd, II_OR, or>, 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 @@ -11,6 +11,7 @@ #------------------------------------------------------------------------------ # CHECK-EL: addu16 $6, $17, $4 # encoding: [0x42,0x07] # CHECK-EL: subu16 $5, $16, $3 # encoding: [0xb1,0x06] +# CHECK-EL: andi16 $16, $2, 31 # encoding: [0x29,0x2c] # CHECK-EL: and16 $16, $2 # encoding: [0x82,0x44] # CHECK-EL: not16 $17, $3 # encoding: [0x0b,0x44] # CHECK-EL: or16 $16, $4 # encoding: [0xc4,0x44] @@ -43,6 +44,7 @@ #------------------------------------------------------------------------------ # CHECK-EB: addu16 $6, $17, $4 # encoding: [0x07,0x42] # CHECK-EB: subu16 $5, $16, $3 # encoding: [0x06,0xb1] +# CHECK-EB: andi16 $16, $2, 31 # encoding: [0x2c,0x29] # CHECK-EB: and16 $16, $2 # encoding: [0x44,0x82] # CHECK-EB: not16 $17, $3 # encoding: [0x44,0x0b] # CHECK-EB: or16 $16, $4 # encoding: [0x44,0xc4] @@ -73,6 +75,7 @@ addu16 $6, $17, $4 subu16 $5, $16, $3 + andi16 $16, $2, 31 and16 $16, $2 not16 $17, $3 or16 $16, $4 Index: test/MC/Mips/micromips-invalid.s =================================================================== --- test/MC/Mips/micromips-invalid.s +++ test/MC/Mips/micromips-invalid.s @@ -8,6 +8,8 @@ addiusp 1032 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range addu16 $6, $14, $4 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction subu16 $5, $16, $9 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + andi16 $16, $10, 0x1f # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + andi16 $16, $2, 17 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range and16 $16, $8 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction not16 $18, $9 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction or16 $16, $10 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction