Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1182,6 +1182,40 @@ if (Imm < 1 || Imm > 8) return Error(IDLoc, "immediate operand value out of range"); break; + case Mips::LBU16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < -1 || Imm > 14) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::SB16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 0 || Imm > 15) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::LHU16_MM: + case Mips::SH16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 0 || Imm > 30 || (Imm % 2 != 0)) + return Error(IDLoc, "immediate operand value out of range"); + break; + case Mips::LW16_MM: + case Mips::SW16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 0 || Imm > 60 || (Imm % 4 != 0)) + 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 @@ -134,6 +134,15 @@ unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, 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 @@ -607,6 +607,48 @@ } unsigned MipsMCCodeEmitter:: +getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. + assert(MI.getOperand(OpNo).isReg()); + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), + Fixups, STI) << 4; + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), + Fixups, STI); + + return (OffBits & 0xF) | RegBits; +} + +unsigned MipsMCCodeEmitter:: +getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. + assert(MI.getOperand(OpNo).isReg()); + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), + Fixups, STI) << 4; + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), + Fixups, STI) >> 1; + + return (OffBits & 0xF) | RegBits; +} + +unsigned MipsMCCodeEmitter:: +getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. + assert(MI.getOperand(OpNo).isReg()); + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), + Fixups, STI) << 4; + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), + Fixups, STI) >> 2; + + return (OffBits & 0xF) | RegBits; +} + +unsigned MipsMCCodeEmitter:: getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { Index: lib/Target/Mips/MicroMipsInstrFormats.td =================================================================== --- lib/Target/Mips/MicroMipsInstrFormats.td +++ lib/Target/Mips/MicroMipsInstrFormats.td @@ -81,6 +81,18 @@ let Inst{0} = funct; } +class LOAD_STORE_FM_MM16 op> { + bits<3> rt; + bits<7> addr; + + bits<16> Inst; + + let Inst{15-10} = op; + let Inst{9-7} = rt; + let Inst{6-4} = addr{6-4}; + let Inst{3-0} = addr{3-0}; +} + 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 @@ -1,3 +1,7 @@ +def addrimm4 : ComplexPattern; +def addrimm5 : ComplexPattern; +def addrimm6 : ComplexPattern; + def addrimm12 : ComplexPattern; def simm4 : Operand; @@ -20,6 +24,24 @@ def immZExt2Shift : ImmLeaf= 1 && Imm <= 8;}]>; +class mem_mm_4_generic : Operand { + let PrintMethod = "printMemOperand"; + let ParserMatchClass = MipsMemAsmOperand; + let OperandType = "OPERAND_MEMORY"; +} + +def mem_mm_4 : mem_mm_4_generic { + let EncoderMethod = "getMemEncodingMMImm4"; +} + +def mem_mm_4_lsl1 : mem_mm_4_generic { + let EncoderMethod = "getMemEncodingMMImm4Lsl1"; +} + +def mem_mm_4_lsl2 : mem_mm_4_generic { + let EncoderMethod = "getMemEncodingMMImm4Lsl2"; +} + def mem_mm_12 : Operand { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops GPR32, simm12); @@ -132,6 +154,24 @@ let isCommutable = 1; } +class LoadMM16 : + MicroMipsInst16<(outs RO:$rt), (ins MemOpnd:$addr), + !strconcat(opstr, "\t$rt, $addr"), + [(set RO:$rt, (OpNode Addr:$addr))], Itin, FrmI> { + let canFoldAsLoad = 1; + let mayLoad = 1; +} + +class StoreMM16 : + MicroMipsInst16<(outs), (ins RTOpnd:$rt, MemOpnd:$addr), + !strconcat(opstr, "\t$rt, $addr"), + [(OpNode RTOpnd:$rt, Addr:$addr)], Itin, FrmI> { + let mayStore = 1; +} + class AddImmUSP : MicroMipsInst16<(outs), (ins simm9_addiusp:$imm), !strconcat(opstr, "\t$imm"), [], NoItinerary, FrmI>; @@ -232,6 +272,19 @@ SHIFT_FM_MM16<0>; def SRL16_MM : ShiftIMM16<"srl16", uimm3_shift, GPRMM16Opnd, II_SRL>, SHIFT_FM_MM16<1>; +def LBU16_MM : LoadMM16<"lbu16", GPRMM16Opnd, zextloadi8, II_LBU, + mem_mm_4, addrimm4>, LOAD_STORE_FM_MM16<0x02>; +def LHU16_MM : LoadMM16<"lhu16", GPRMM16Opnd, zextloadi16, II_LHU, + mem_mm_4_lsl1, addrimm5>, LOAD_STORE_FM_MM16<0x0a>; +def LW16_MM : LoadMM16<"lw16", GPRMM16Opnd, load, II_LW, mem_mm_4_lsl2, + addrimm6>, LOAD_STORE_FM_MM16<0x1a>; +def SB16_MM : StoreMM16<"sb16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei8, + II_SB, mem_mm_4, addrimm4>, LOAD_STORE_FM_MM16<0x22>; +def SH16_MM : StoreMM16<"sh16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei16, + II_SH, mem_mm_4_lsl1, addrimm5>, + LOAD_STORE_FM_MM16<0x2a>; +def SW16_MM : StoreMM16<"sw16", GPRMM16OpndZero, GPRMM16Opnd, store, II_SW, + mem_mm_4_lsl2, addrimm6>, LOAD_STORE_FM_MM16<0x3a>; 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/MipsISelDAGToDAG.h =================================================================== --- lib/Target/Mips/MipsISelDAGToDAG.h +++ lib/Target/Mips/MipsISelDAGToDAG.h @@ -70,6 +70,15 @@ virtual bool selectIntAddr(SDValue Addr, SDValue &Base, SDValue &Offset) const; + virtual bool selectAddrRegImm4(SDValue Addr, SDValue &Base, + SDValue &Offset) const; + + virtual bool selectAddrRegImm5(SDValue Addr, SDValue &Base, + SDValue &Offset) const; + + virtual bool selectAddrRegImm6(SDValue Addr, SDValue &Base, + SDValue &Offset) const; + virtual bool selectIntAddrMM(SDValue Addr, SDValue &Base, SDValue &Offset) const; Index: lib/Target/Mips/MipsISelDAGToDAG.cpp =================================================================== --- lib/Target/Mips/MipsISelDAGToDAG.cpp +++ lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -89,6 +89,24 @@ return false; } +bool MipsDAGToDAGISel::selectAddrRegImm4(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + llvm_unreachable("Unimplemented function."); + return false; +} + +bool MipsDAGToDAGISel::selectAddrRegImm5(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + llvm_unreachable("Unimplemented function."); + return false; +} + +bool MipsDAGToDAGISel::selectAddrRegImm6(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + llvm_unreachable("Unimplemented function."); + return false; +} + bool MipsDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base, SDValue &Offset) const { llvm_unreachable("Unimplemented function."); Index: lib/Target/Mips/MipsSEISelDAGToDAG.h =================================================================== --- lib/Target/Mips/MipsSEISelDAGToDAG.h +++ lib/Target/Mips/MipsSEISelDAGToDAG.h @@ -56,6 +56,10 @@ bool selectIntAddr(SDValue Addr, SDValue &Base, SDValue &Offset) const override; + bool selectAddrRegImm4(SDValue Addr, SDValue &Base, SDValue &Offset) const; + bool selectAddrRegImm5(SDValue Addr, SDValue &Base, SDValue &Offset) const; + bool selectAddrRegImm6(SDValue Addr, SDValue &Base, SDValue &Offset) const; + bool selectAddrRegImm10(SDValue Addr, SDValue &Base, SDValue &Offset) const; Index: lib/Target/Mips/MipsSEISelDAGToDAG.cpp =================================================================== --- lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -363,6 +363,39 @@ selectAddrDefault(Addr, Base, Offset); } +bool MipsSEDAGToDAGISel::selectAddrRegImm4(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + if (selectAddrFrameIndex(Addr, Base, Offset)) + return true; + + if (selectAddrFrameIndexOffset(Addr, Base, Offset, 4)) + return true; + + return false; +} + +bool MipsSEDAGToDAGISel::selectAddrRegImm5(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + if (selectAddrFrameIndex(Addr, Base, Offset)) + return true; + + if (selectAddrFrameIndexOffset(Addr, Base, Offset, 5)) + return true; + + return false; +} + +bool MipsSEDAGToDAGISel::selectAddrRegImm6(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + if (selectAddrFrameIndex(Addr, Base, Offset)) + return true; + + if (selectAddrFrameIndexOffset(Addr, Base, Offset, 6)) + return true; + + return false; +} + bool MipsSEDAGToDAGISel::selectAddrRegImm10(SDValue Addr, SDValue &Base, SDValue &Offset) const { if (selectAddrFrameIndex(Addr, Base, Offset)) 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 @@ -17,6 +17,13 @@ # 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: lbu16 $3, 4($17) # encoding: [0x94,0x09] +# CHECK-EL: lhu16 $3, 4($16) # encoding: [0x82,0x29] +# CHECK-EL: lw16 $4, 8($17) # encoding: [0x12,0x6a] +# CHECK-EL: sb16 $3, 4($16) # encoding: [0x84,0x89] +# CHECK-EL: sh16 $4, 8($17) # encoding: [0x14,0xaa] +# CHECK-EL: sw16 $4, 4($17) # encoding: [0x11,0xea] +# CHECK-EL: sw16 $zero, 4($17) # encoding: [0x11,0xe8] # CHECK-EL: addius5 $7, -2 # encoding: [0xfc,0x4c] # CHECK-EL: addiusp -16 # encoding: [0xf9,0x4f] # CHECK-EL: mfhi $9 # encoding: [0x09,0x46] @@ -41,6 +48,13 @@ # 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: lbu16 $3, 4($17) # encoding: [0x09,0x94] +# CHECK-EB: lhu16 $3, 4($16) # encoding: [0x29,0x82] +# CHECK-EB: lw16 $4, 8($17) # encoding: [0x6a,0x12] +# CHECK-EB: sb16 $3, 4($16) # encoding: [0x89,0x84] +# CHECK-EB: sh16 $4, 8($17) # encoding: [0xaa,0x14] +# CHECK-EB: sw16 $4, 4($17) # encoding: [0xea,0x11] +# CHECK-EB: sw16 $zero, 4($17) # encoding: [0xe8,0x11] # CHECK-EB: addius5 $7, -2 # encoding: [0x4c,0xfc] # CHECK-EB: addiusp -16 # encoding: [0x4f,0xf9] # CHECK-EB: mfhi $9 # encoding: [0x46,0x09] @@ -63,6 +77,13 @@ xor16 $17, $5 sll16 $3, $16, 5 srl16 $4, $17, 6 + lbu16 $3, 4($17) + lhu16 $3, 4($16) + lw16 $4, 8($17) + sb16 $3, 4($16) + sh16 $4, 8($17) + sw16 $4, 4($17) + sw16 $0, 4($17) addius5 $7, -2 addiusp -16 mfhi $9 Index: test/MC/Mips/micromips-invalid.s =================================================================== --- test/MC/Mips/micromips-invalid.s +++ test/MC/Mips/micromips-invalid.s @@ -13,3 +13,21 @@ 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 + lbu16 $9, 8($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhu16 $9, 4($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lw16 $9, 8($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + sb16 $9, 4($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + sh16 $9, 8($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + sw16 $9, 4($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lbu16 $3, -2($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 + lw16 $4, 68($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + 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 + lbu16 $3, -2($9) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + lhu16 $3, 64($9) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + lw16 $4, 68($10) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + sb16 $16, 4($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + sh16 $16, 8($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + sw16 $16, 4($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction