Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -875,6 +875,9 @@ template bool isMemWithSimmOffset() const { return isMem() && isConstantMemOff() && isInt(getConstantMemOff()); } + template bool isMemWithSimmOffsetGPR() const { + return isMem() && isConstantMemOff() && isInt(getConstantMemOff()) && getMemBase()->isGPRAsmReg(); + } bool isMemWithGRPMM16Base() const { return isMem() && getMemBase()->isMM16AsmReg(); } Index: lib/Target/Mips/MicroMips32r6InstrFormats.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrFormats.td +++ lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -109,3 +109,29 @@ let Inst{11-6} = funct; let Inst{5-0} = 0x3c; } + +class LW_FM_MMR6 op> : MMR6Arch { + bits<5> rt; + bits<21> addr; + + bits<32> Inst; + + let Inst{31-26} = op; + let Inst{25-21} = rt; + let Inst{20-16} = addr{20-16}; + let Inst{15-0} = addr{15-0}; +} + +class LHUE_FM_MMR6 op, bits<4> fmt, bits<3> funct> : MMR6Arch { + bits<5> rt; + bits<21> addr; + + bits<32> Inst; + + let Inst{31-26} = op; + let Inst{25-21} = rt; + let Inst{20-16} = addr{20-16}; + let Inst{15-12} = fmt; + let Inst{11-9} = funct; + let Inst{8-0} = addr{8-0}; +} Index: lib/Target/Mips/MicroMips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrInfo.td +++ lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -42,6 +42,10 @@ class TLT_MMR6_ENC : TRAP_MMR6_ENC<0b100000>; class TLTU_MMR6_ENC : TRAP_MMR6_ENC<0b101000>; class TNE_MMR6_ENC : TRAP_MMR6_ENC<0b110000>; +class LH_MMR6_ENC : LW_FM_MMR6<"lh", 0xf>; +class LHu_MMR6_ENC : LW_FM_MMR6<"lhu", 0xd>; +class LHE_MMR6_ENC : LHUE_FM_MMR6<"lhe", 0x18, 0x6, 0x5>; +class LHuE_MMR6_ENC : LHUE_FM_MMR6<"lhue", 0x18, 0x6, 0x1>; //===----------------------------------------------------------------------===// // @@ -157,6 +161,11 @@ class TLTU_MMR6_DESC : TRAP_MMR6_DESC<"tltu", GPR32Opnd>; class TNE_MMR6_DESC : TRAP_MMR6_DESC<"tne", GPR32Opnd>; +class LH_MMR6_DESC : LoadMemory<"lh", GPR32Opnd, mem_simm16gpr>; +class LHu_MMR6_DESC : LoadMemory<"lhu", GPR32Opnd, mem_simm16gpr>; +class LHE_MMR6_DESC : LoadMemory<"lhe", GPR32Opnd, mem_simm9gpr>; +class LHuE_MMR6_DESC : LoadMemory<"lhue", GPR32Opnd, mem_simm9gpr>; + //===----------------------------------------------------------------------===// // // Instruction Definitions @@ -193,4 +202,15 @@ def TLT_MMR6 : StdMMR6Rel, TLT_MMR6_ENC, TLT_MMR6_DESC, ISA_MICROMIPS32R6; def TLTU_MMR6 : StdMMR6Rel, TLTU_MMR6_ENC, TLTU_MMR6_DESC, ISA_MICROMIPS32R6; def TNE_MMR6 : StdMMR6Rel, TNE_MMR6_ENC, TNE_MMR6_DESC, ISA_MICROMIPS32R6; + +let DecoderMethod = "DecodeMemMMImm16" in { + def LH_MMR6 : StdMMR6Rel, LH_MMR6_DESC, LH_MMR6_ENC, ISA_MICROMIPS32R6; + def LHu_MMR6 : StdMMR6Rel, LHu_MMR6_DESC, LHu_MMR6_ENC, ISA_MICROMIPS32R6; +} + +let DecoderMethod = "DecodeMemMMImm9" in { + def LHE_MMR6 : StdMMR6Rel, LHE_MMR6_DESC, LHE_MMR6_ENC, ISA_MICROMIPS32R6; + def LHuE_MMR6 : StdMMR6Rel, LHuE_MMR6_DESC, LHuE_MMR6_ENC, ISA_MICROMIPS32R6; +} + } Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -715,8 +715,8 @@ let DecoderMethod = "DecodeMemMMImm16" in { def LB_MM : Load<"lb", GPR32Opnd>, MMRel, LW_FM_MM<0x7>; def LBu_MM : Load<"lbu", GPR32Opnd>, MMRel, LW_FM_MM<0x5>; - def LH_MM : Load<"lh", GPR32Opnd>, MMRel, LW_FM_MM<0xf>; - def LHu_MM : Load<"lhu", GPR32Opnd>, MMRel, LW_FM_MM<0xd>; + def LH_MM : LoadMemory<"lh", GPR32Opnd, mem_simm16gpr>, MMRel, LW_FM_MM<0xf>; + def LHu_MM : LoadMemory<"lhu", GPR32Opnd, mem_simm16gpr>, MMRel, LW_FM_MM<0xd>; def LW_MM : Load<"lw", GPR32Opnd>, MMRel, LW_FM_MM<0x3f>; def SB_MM : Store<"sb", GPR32Opnd>, MMRel, LW_FM_MM<0x6>; def SH_MM : Store<"sh", GPR32Opnd>, MMRel, LW_FM_MM<0xe>; @@ -726,8 +726,8 @@ let DecoderMethod = "DecodeMemMMImm9" in { def LBE_MM : Load<"lbe", GPR32Opnd>, LHUE_FM_MM<0x18, 0x6, 0x4>; def LBuE_MM : Load<"lbue", GPR32Opnd>, LHUE_FM_MM<0x18, 0x6, 0x0>; - def LHE_MM : Load<"lhe", GPR32Opnd>, LHUE_FM_MM<0x18, 0x6, 0x5>; - def LHuE_MM : Load<"lhue", GPR32Opnd>, LHUE_FM_MM<0x18, 0x6, 0x1>; + def LHE_MM : LoadMemory<"lhe", GPR32Opnd, mem_simm9gpr>, LHUE_FM_MM<0x18, 0x6, 0x5>; + def LHuE_MM : LoadMemory<"lhue", GPR32Opnd, mem_simm9gpr>, LHUE_FM_MM<0x18, 0x6, 0x1>; def LWE_MM : Load<"lwe", GPR32Opnd>, LHUE_FM_MM<0x18, 0x6, 0x7>; def SBE_MM : Store<"sbe", GPR32Opnd>, LHUE_FM_MM<0x18, 0xa, 0x4>; def SHE_MM : Store<"she", GPR32Opnd>, LHUE_FM_MM<0x18, 0xa, 0x5>; Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -428,6 +428,14 @@ let ParserMethod = "parseMemOperand"; } +def MipsMemSimm9GPRAsmOperand : AsmOperandClass { + let Name = "MemOffsetSimm9GPR"; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithSimmOffsetGPR<9>"; +} + def MipsMemSimm11AsmOperand : AsmOperandClass { let Name = "MemOffsetSimm11"; let SuperClasses = [MipsMemAsmOperand]; @@ -444,6 +452,14 @@ let PredicateMethod = "isMemWithSimmOffset<16>"; } +def MipsMemSimm16GPRAsmOperand : AsmOperandClass { + let Name = "MemOffsetSimm16GPR"; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithSimmOffsetGPR<16>"; +} + def MipsInvertedImmoperand : AsmOperandClass { let Name = "InvNum"; let RenderMethod = "addImmOperands"; @@ -480,6 +496,12 @@ let EncoderMethod = "getMemEncoding"; } +def mem_simm9gpr : mem_generic { + let MIOperandInfo = (ops ptr_rc, simm9); + let EncoderMethod = "getMemEncoding"; + let ParserMatchClass = MipsMemSimm9GPRAsmOperand; +} + def mem_simm11 : mem_generic { let MIOperandInfo = (ops ptr_rc, simm11); let EncoderMethod = "getMemEncoding"; @@ -492,6 +514,12 @@ let ParserMatchClass = MipsMemSimm16AsmOperand; } +def mem_simm16gpr : mem_generic { + let MIOperandInfo = (ops ptr_rc, simm16); + let EncoderMethod = "getMemEncoding"; + let ParserMatchClass = MipsMemSimm16GPRAsmOperand; +} + def mem_ea : Operand { let PrintMethod = "printMemOperandEA"; let MIOperandInfo = (ops ptr_rc, simm16); @@ -659,15 +687,19 @@ } // Memory Load/Store -class Load : - InstSE<(outs RO:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + InstSE<(outs RO:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"), [(set RO:$rt, (OpNode Addr:$addr))], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMem"; let canFoldAsLoad = 1; let mayLoad = 1; } +class Load : + LoadMemory; + class Store : InstSE<(outs), (ins RO:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), @@ -1199,9 +1231,8 @@ def LB : Load<"lb", GPR32Opnd, sextloadi8, II_LB>, MMRel, LW_FM<0x20>; def LBu : Load<"lbu", GPR32Opnd, zextloadi8, II_LBU, addrDefault>, MMRel, LW_FM<0x24>; -def LH : Load<"lh", GPR32Opnd, sextloadi16, II_LH, addrDefault>, MMRel, - LW_FM<0x21>; -def LHu : Load<"lhu", GPR32Opnd, zextloadi16, II_LHU>, MMRel, LW_FM<0x25>; +def LH : LoadMemory<"lh", GPR32Opnd, mem_simm16gpr, sextloadi16, II_LH, addrDefault>, MMRel, LW_FM<0x21>; +def LHu : LoadMemory<"lhu", GPR32Opnd, mem_simm16gpr, zextloadi16, II_LHU>, MMRel, LW_FM<0x25>; let AdditionalPredicates = [NotInMicroMips] in { def LW : Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel, LW_FM<0x23>; Index: test/MC/Disassembler/Mips/micromips32r6.txt =================================================================== --- test/MC/Disassembler/Mips/micromips32r6.txt +++ test/MC/Disassembler/Mips/micromips32r6.txt @@ -57,3 +57,9 @@ 0x03 0xb0 0xfa 0x3c # CHECK: tltu $16, $sp, 15 0x02 0x26 0x0c 0x3c # CHECK: tne $6, $17, 0 0x01 0x07 0xfc 0x3c # CHECK: tne $7, $8, 15 + +0x3c 0x44 0x00 0x08 # CHECK: lh $2, 8($4) +0x60 0x82 0x6a 0x08 # CHECK: lhe $4, 8($2) +0x34 0x82 0x00 0x08 # CHECK: lhu $4, 8($2) +0x60 0x82 0x62 0x08 # CHECK: lhue $4, 8($2) + Index: test/MC/Mips/micromips-invalid.s =================================================================== --- test/MC/Mips/micromips-invalid.s +++ test/MC/Mips/micromips-invalid.s @@ -74,3 +74,15 @@ movep $5, $6, $5, $3 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction movep $5, $6, $2, $9 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction prefx 33, $8($5) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + lh $33, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhe $34, 8($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhu $35, 8($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhue $36, 8($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lh $2, 8($34) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhe $4, 8($33) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhu $4, 8($35) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhue $4, 8($37) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lh $2, 65536($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhe $4, 512($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhu $4, 65536($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhue $4, 512($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction Index: test/MC/Mips/micromips32r6/invalid.s =================================================================== --- test/MC/Mips/micromips32r6/invalid.s +++ test/MC/Mips/micromips32r6/invalid.s @@ -25,3 +25,15 @@ tlt $8, $9, $2 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction tltu $8, $9, $2 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction tne $8, $9, $2 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lh $33, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhe $34, 8($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhu $35, 8($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhue $36, 8($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lh $2, 8($34) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhe $4, 8($33) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhu $4, 8($35) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhue $4, 8($37) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lh $2, 65536($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhe $4, 512($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhu $4, 65536($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhue $4, 512($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction Index: test/MC/Mips/micromips32r6/valid.s =================================================================== --- test/MC/Mips/micromips32r6/valid.s +++ test/MC/Mips/micromips32r6/valid.s @@ -33,3 +33,7 @@ tltu $16, $sp, 15 # CHECK: tltu $16, $sp, 15 # encoding: [0x03,0xb0,0xfa,0x3c] tne $6, $17 # CHECK: tne $6, $17 # encoding: [0x02,0x26,0x0c,0x3c] tne $7, $8, 15 # CHECK: tne $7, $8, 15 # encoding: [0x01,0x07,0xfc,0x3c] + lh $2, 8($4) # CHECK: lh $2, 8($4) # encoding: [0x3c,0x44,0x00,0x08] + lhe $4, 8($2) # CHECK: lhe $4, 8($2) # encoding: [0x60,0x82,0x6a,0x08] + lhu $4, 8($2) # CHECK: lhu $4, 8($2) # encoding: [0x34,0x82,0x00,0x08] + lhue $4, 8($2) # CHECK: lhue $4, 8($2) # encoding: [0x60,0x82,0x62,0x08] Index: test/MC/Mips/mips32r6/invalid.s =================================================================== --- test/MC/Mips/mips32r6/invalid.s +++ test/MC/Mips/mips32r6/invalid.s @@ -12,3 +12,9 @@ ldc2 $8,-21181($at) # ASM: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled sdc2 $20,23157($s2) # ASM: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled swc2 $25,24880($s0) # ASM: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + lh $33, 8($4) # ASM: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhu $35, 8($2) # ASM: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lh $2, 8($34) # ASM: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhu $4, 8($35) # ASM: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lh $2, 65536($4) # ASM: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhu $4, 65536($2) # ASM: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction Index: test/MC/Mips/mips64r6/invalid.s =================================================================== --- test/MC/Mips/mips64r6/invalid.s +++ test/MC/Mips/mips64r6/invalid.s @@ -10,3 +10,9 @@ jalr.hb $31 # ASM: :[[@LINE]]:9: error: source and destination must be different jalr.hb $31, $31 # ASM: :[[@LINE]]:9: error: source and destination must be different ldc2 $8,-21181($at) # ASM: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + lh $33, 8($4) # ASM: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhu $35, 8($2) # ASM: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lh $2, 8($34) # ASM: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhu $4, 8($35) # ASM: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lh $2, 65536($4) # ASM: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + lhu $4, 65536($2) # ASM: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction