Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1104,6 +1104,7 @@ if (inMicroMipsMode()) { MCOperand Opnd; int Imm; + unsigned UImm; switch (Inst.getOpcode()) { default: @@ -1133,6 +1134,18 @@ if (Imm < 1 || Imm > 7) return Error(IDLoc, "immediate operand value out of range"); break; + case Mips::LHU16_MM: + case Mips::LW16_MM: + case Mips::SB16_MM: + case Mips::SH16_MM: + case Mips::SW16_MM: + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + UImm = Opnd.getImm(); + if (UImm > 60) + 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 @@ -140,6 +140,9 @@ 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 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 @@ -614,6 +614,20 @@ } 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) >> 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,5 @@ +def addrimm4 : ComplexPattern; + def addrimm12 : ComplexPattern; def simm12 : Operand { @@ -22,6 +24,13 @@ def shift_immZExt3 : ImmLeaf= 0 && Imm <= 8;}]>; +def mem_mm_4 : Operand { + let PrintMethod = "printMemOperand"; + let EncoderMethod = "getMemEncodingMMImm4"; + let ParserMatchClass = MipsMemAsmOperand; + let OperandType = "OPERAND_MEMORY"; +} + def mem_mm_12 : Operand { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops GPR32, simm12); @@ -139,6 +148,27 @@ let isCommutable = 1; } +class LoadMM16 : + MicroMipsInst16<(outs RO:$rt), (ins mem_mm_4:$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 RO:$rt, mem_mm_4:$addr), + !strconcat(opstr, "\t$rt, $addr"), + [(OpNode RO:$rt, Addr:$addr)], Itin, FrmI> { + let mayStore = 1; +} + class AddImmUSP : MicroMipsInst16<(outs), (ins addiusp_imm:$imm), !strconcat(opstr, "\t$imm"), [], NoItinerary, FrmI>; @@ -237,6 +267,16 @@ 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 LHU16_MM : LoadMM16<"lhu16", GPRMM16Opnd, zextloadi16, II_LHU>, + LOAD_STORE_FM_MM16<0x0a>; +def LW16_MM : LoadMM16<"lw16", GPRMM16Opnd, load, II_LW>, + LOAD_STORE_FM_MM16<0x1a>; +def SB16_MM : StoreMM16<"sb16", GPRMM16Opnd, truncstorei8, II_SB>, + LOAD_STORE_FM_MM16<0x22>; +def SH16_MM : StoreMM16<"sh16", GPRMM16Opnd, truncstorei16, II_SH>, + LOAD_STORE_FM_MM16<0x2a>; +def SW16_MM : StoreMM16<"sw16", GPRMM16Opnd, store, II_SW>, + 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/MipsCodeEmitter.cpp =================================================================== --- lib/Target/Mips/MipsCodeEmitter.cpp +++ lib/Target/Mips/MipsCodeEmitter.cpp @@ -121,6 +121,7 @@ unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned OpNo) const; unsigned getMemEncoding(const MachineInstr &MI, unsigned OpNo) const; + unsigned getMemEncodingMMImm4(const MachineInstr &MI, unsigned OpNo) const; unsigned getMemEncodingMMImm12(const MachineInstr &MI, unsigned OpNo) const; unsigned getMSAMemEncoding(const MachineInstr &MI, unsigned OpNo) const; unsigned getSizeExtEncoding(const MachineInstr &MI, unsigned OpNo) const; @@ -269,6 +270,12 @@ return (getMachineOpValue(MI, MI.getOperand(OpNo+1)) & 0xFFFF) | RegBits; } +unsigned MipsCodeEmitter::getMemEncodingMMImm4(const MachineInstr &MI, + unsigned OpNo) const { + llvm_unreachable("Unimplemented function."); + return 0; +} + unsigned MipsCodeEmitter::getMemEncodingMMImm12(const MachineInstr &MI, unsigned OpNo) const { llvm_unreachable("Unimplemented function."); Index: lib/Target/Mips/MipsISelDAGToDAG.h =================================================================== --- lib/Target/Mips/MipsISelDAGToDAG.h +++ lib/Target/Mips/MipsISelDAGToDAG.h @@ -70,6 +70,9 @@ virtual bool selectIntAddr(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,12 @@ 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,8 @@ bool selectIntAddr(SDValue Addr, SDValue &Base, SDValue &Offset) const override; + 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,17 @@ selectAddrDefault(Addr, Base, Offset); } +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,11 @@ # 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: lhu16 $3, 4($16) # encoding: [0x81,0x29] +# CHECK-EL: lw16 $4, 8($17) # encoding: [0x12,0x6a] +# 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: addius5 $7, -2 # encoding: [0xfc,0x4c] # CHECK-EL: addiusp -255 # encoding: [0x03,0x4e] # CHECK-EL: mfhi $9 # encoding: [0x09,0x46] @@ -42,6 +47,11 @@ # 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: lhu16 $3, 4($16) # encoding: [0x29,0x81] +# CHECK-EB: lw16 $4, 8($17) # encoding: [0x6a,0x12] +# 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: addius5 $7, -2 # encoding: [0x4c,0xfc] # CHECK-EB: addiusp -255 # encoding: [0x4e,0x03] # CHECK-EB: mfhi $9 # encoding: [0x46,0x09] @@ -65,6 +75,11 @@ xor16 $17, $5 sll16 $3, $16, 5 srl16 $4, $17, 6 + lhu16 $3, 4($16) + lw16 $4, 8($17) + sb16 $3, 4($16) + sh16 $4, 8($17) + sw16 $4, 4($17) 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 @@ -11,3 +11,13 @@ 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 + 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 + 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