Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -256,6 +256,11 @@ uint64_t Address, const void *Decoder); +static DecodeStatus DecodePrefeOpMM(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeSyncI(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -1125,6 +1130,23 @@ return MCDisassembler::Success; } +static DecodeStatus DecodePrefeOpMM(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int Offset = SignExtend32<9>(Insn & 0x1ff); + unsigned Base = fieldFromInstruction(Insn, 16, 5); + unsigned Hint = fieldFromInstruction(Insn, 21, 5); + + Base = getReg(Decoder, Mips::GPR32RegClassID, Base); + + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); + Inst.addOperand(MCOperand::createImm(Hint)); + + return MCDisassembler::Success; +} + static DecodeStatus DecodeCacheOpR6(MCInst &Inst, unsigned Insn, uint64_t Address, Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -172,6 +172,9 @@ unsigned getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMImm9(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 @@ -792,6 +792,19 @@ } unsigned MipsMCCodeEmitter:: +getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // Base register is encoded in bits 20-16, offset is encoded in bits 8-0. + assert(MI.getOperand(OpNo).isReg()); + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, + STI) << 16; + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); + + return (OffBits & 0x1FF) | RegBits; +} + +unsigned MipsMCCodeEmitter:: getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { Index: lib/Target/Mips/MicroMips32r6InstrFormats.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrFormats.td +++ lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -16,6 +16,14 @@ string BaseOpcode = opstr; } +def mem_mm_9 : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops GPR32, simm12); + let EncoderMethod = "getMemEncodingMMImm9"; + let ParserMatchClass = MipsMemAsmOperand; + let OperandType = "OPERAND_MEMORY"; +} + class POOL32A_BITSWAP_FM_MMR6 funct> : MipsR6Inst { bits<5> rd; bits<5> rt; @@ -222,6 +230,51 @@ let Inst{15-0} = offset; } +class EXT_FM_MMR6 funct> { + bits<5> rt; + bits<5> rs; + bits<5> size; + bits<5> pos; + + bits<32> Inst; + + let Inst{31-26} = 0; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-11} = size; + let Inst{10-6} = pos; + let Inst{5-0} = funct; +} + +class PREFE_FM_MMR6 op, bits<3> funct> : MipsR6Inst { + bits<21> addr; + bits<5> hint; + bits<5> base = addr{20-16}; + bits<9> offset = addr{8-0}; + + bits<32> Inst; + + let Inst{31-26} = op; + let Inst{25-21} = hint; + let Inst{20-16} = base; + let Inst{15-12} = 0b1010; + let Inst{11-9} = funct; + let Inst{8-0} = offset; +} + +class JALRC_FM_MMR6 { + bits<5> rt; + bits<5> rs; + + bits<32> Inst; + + let Inst{31-26} = 0; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-6} = 0b0000111100; + let Inst{5-0} = 0b111100; +} + class ERET_FM_MMR6 : MMR6Arch { bits<32> Inst; Index: lib/Target/Mips/MicroMips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrInfo.td +++ lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -68,6 +68,10 @@ class SUBU_MMR6_ENC : ARITH_FM_MMR6<"subu", 0x1d0>; class XOR_MMR6_ENC : ARITH_FM_MMR6<"xor", 0x310>; class XORI_MMR6_ENC : ADDI_FM_MMR6<"xori", 0x1c>; +class EXT_MMR6_ENC : EXT_FM_MMR6<0b101100>; +class PREFE_MMR6_ENC : PREFE_FM_MMR6<0b011000, 0b010>; +class INS_MMR6_ENC : EXT_FM_MMR6<0b001100>; +class JALRC_MMR6_ENC : JALRC_FM_MMR6; class CMP_CBR_RT_Z_MMR6_DESC_BASE @@ -277,6 +281,53 @@ class XOR_MMR6_DESC : ArithLogicR<"xor", GPR32Opnd>; class XORI_MMR6_DESC : ArithLogicI<"xori", simm16, GPR32Opnd>; +class EXT_MMR6_DESC_BASE : MMR6Arch, + MipsR6Inst { + dag OutOperandList = (outs RO:$rt); + dag InOperandList = (ins RO:$rs, PosOpnd:$pos, size_ext:$size); + string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $pos, $size"); + list Pattern = [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size))]; + InstrItinClass Itinerary = II_EXT; + Format Form = FrmR; + string BaseOpcode = instr_asm; +} +class EXT_MMR6_DESC : EXT_MMR6_DESC_BASE<"ext", GPR32Opnd, uimm5, MipsExt>; + +class PREFE_MMR6_DESC_BASE : + CACHE_HINT_MMR6_DESC { + string DecoderMethod = "DecodePrefeOpMM"; +} +class PREFE_MMR6_DESC : PREFE_MMR6_DESC_BASE<"prefe", mem_mm_9, GPR32Opnd>; + +class INS_MMR6_DESC_BASE : MMR6Arch, + MipsR6Inst { + dag OutOperandList = (outs RO:$rt); + dag InOperandList = (ins RO:$rs, PosOpnd:$pos, size_ins:$size, RO:$src); + string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $pos, $size"); + list Pattern = [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size, RO:$src))]; + InstrItinClass Itinerary = II_INS; + Format Form = FrmR; + string BaseOpcode = instr_asm; + string Constraints = "$src = $rt"; +} +class INS_MMR6_DESC : INS_MMR6_DESC_BASE<"ins", GPR32Opnd, uimm5, MipsIns>; + +class JALRC_MMR6_DESC_BASE : + MMR6Arch, MipsR6Inst { + dag OutOperandList = (outs RO:$rt); + dag InOperandList = (ins RO:$dst, RO:$rs); + string AsmString = !strconcat(instr_asm, "\t$rt, $rs"); + list Pattern = []; + InstrItinClass Itinerary = IIBranch; + string Constraints = "$dst = $rt"; + bit isCall = 1; + bit hasDelaySlot = 0; +} +class JALRC_MMR6_DESC : JALRC_MMR6_DESC_BASE<"jalrc", GPR32Opnd>; + //===----------------------------------------------------------------------===// // // Instruction Definitions @@ -348,6 +399,10 @@ def SUBU_MMR6 : StdMMR6Rel, SUBU_MMR6_DESC, SUBU_MMR6_ENC, ISA_MICROMIPS32R6; def XOR_MMR6 : StdMMR6Rel, XOR_MMR6_DESC, XOR_MMR6_ENC, ISA_MICROMIPS32R6; def XORI_MMR6 : StdMMR6Rel, XORI_MMR6_DESC, XORI_MMR6_ENC, ISA_MICROMIPS32R6; +def EXT_MMR6 : StdMMR6Rel, EXT_MMR6_DESC, EXT_MMR6_ENC, ISA_MICROMIPS32R6; +def PREFE_MMR6 : R6MMR6Rel, PREFE_MMR6_ENC, PREFE_MMR6_DESC, ISA_MICROMIPS32R6; +def INS_MMR6 : StdMMR6Rel, INS_MMR6_DESC, INS_MMR6_ENC, ISA_MICROMIPS32R6; +def JALRC_MMR6 : R6MMR6Rel, JALRC_MMR6_DESC, JALRC_MMR6_ENC, ISA_MICROMIPS32R6; } //===----------------------------------------------------------------------===// @@ -358,3 +413,7 @@ def : MipsInstAlias<"ei", (EI_MMR6 ZERO), 1>, ISA_MICROMIPS32R6; def : MipsInstAlias<"nop", (SLL_MMR6 ZERO, ZERO, 0), 1>, ISA_MICROMIPS32R6; +def : MipsInstAlias<"jalrc $src", (JALRC_MMR6 RA, GPR32Opnd:$src), 1>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"jr $src", (JALRC_MMR6 ZERO, GPR32Opnd:$src), 1>, + ISA_MICROMIPS32R6; Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -610,6 +610,11 @@ def BREAK16_MM : BrkSdbbp16MM<"break16">, BRKSDBBP16_FM_MM<0x28>; def SDBBP16_MM : BrkSdbbp16MM<"sdbbp16">, BRKSDBBP16_FM_MM<0x2C>; +let DecoderNamespace = "MicroMips" in { + def JR_MM : MMRel, IndirectBranch<"jr", GPR32Opnd>, JR_FM_MM<0x3c>, + ISA_MICROMIPS32R2; +} + class WaitMM : InstSE<(outs), (ins uimm10:$code_), !strconcat(opstr, "\t$code_"), [], NoItinerary, FrmOther, opstr>; @@ -792,7 +797,7 @@ def JAL_MM : MMRel, JumpLink<"jal", calltarget_mm>, J_FM_MM<0x3d>; def JALX_MM : MMRel, JumpLink<"jalx", calltarget>, J_FM_MM<0x3c>; } - def JR_MM : MMRel, IndirectBranch<"jr", GPR32Opnd>, JR_FM_MM<0x3c>; + def JALR_MM : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM_MM<0x03c>; /// Jump Instructions - Short Delay Slot Index: lib/Target/Mips/Mips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/Mips32r6InstrInfo.td +++ lib/Target/Mips/Mips32r6InstrInfo.td @@ -744,7 +744,9 @@ //===----------------------------------------------------------------------===// def : MipsInstAlias<"sdbbp", (SDBBP_R6 0)>, ISA_MIPS32R6; +let AdditionalPredicates = [NotInMicroMips] in { def : MipsInstAlias<"jr $rs", (JALR ZERO, GPR32Opnd:$rs), 1>, ISA_MIPS32R6; +} //===----------------------------------------------------------------------===// // Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -255,6 +255,9 @@ class ISA_MICROMIPS32R6 { list InsnPredicates = [HasMicroMips32r6]; } +class ISA_MICROMIPS32R2 { + list InsnPredicates = [InMicroMips, NotMips32r6]; +} // The portions of MIPS-III that were also added to MIPS32 class INSN_MIPS3_32 { list InsnPredicates = [HasMips3_32]; } @@ -1315,7 +1318,9 @@ /// Jump and Branch Instructions def J : MMRel, JumpFJ, FJ<2>, AdditionalRequires<[RelocStatic]>, IsBranch; +let AdditionalPredicates = [NotInMicroMips] in { def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>; +} def BEQ : MMRel, CBranch<"beq", brtarget, seteq, GPR32Opnd>, BEQ_FM<4>; def BEQL : MMRel, CBranch<"beql", brtarget, seteq, GPR32Opnd, 0>, BEQ_FM<20>, ISA_MIPS2_NOT_32R6_64R6; @@ -1492,8 +1497,12 @@ def RDHWR : MMRel, ReadHardware, RDHWR_FM; -def EXT : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, MipsExt>, EXT_FM<0>; -def INS : MMRel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>, EXT_FM<4>; +let AdditionalPredicates = [NotInMicroMips] in { +def EXT : MMRel, StdMMR6Rel, ExtBase<"ext", GPR32Opnd, uimm5, MipsExt>, + EXT_FM<0>; +def INS : MMRel, StdMMR6Rel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>, + EXT_FM<4>; +} /// Move Control Registers From/To CPU Registers def MFC0 : MFC3OP<"mfc0", GPR32Opnd, COP0Opnd>, MFC3OP_FM<0x10, 0>, ISA_MIPS32; Index: test/MC/Disassembler/Mips/micromips32r6.txt =================================================================== --- test/MC/Disassembler/Mips/micromips32r6.txt +++ test/MC/Disassembler/Mips/micromips32r6.txt @@ -112,3 +112,15 @@ 0x00 0x64 0x3b 0x3c # CHECK: seh $3, $4 +0x01 0x26 0x30 0xec # CHECK: ext $9, $6, 3, 7 + +0x60 0x25 0xa4 0x08 # CHECK: prefe 1, 8($5) + +0x01 0x26 0x48 0xcc # CHECK: ins $9, $6, 3, 7 + +0x00 0x85 0x0f 0x3c # CHECK: jalrc $4, $5 + +0x03 0xe5 0x0f 0x3c # CHECK: jalrc $ra, $5 + +0x00 0x05 0x0f 0x3c # CHECK: jalrc $zero, $5 + Index: test/MC/Mips/micromips32r6/valid.s =================================================================== --- test/MC/Mips/micromips32r6/valid.s +++ test/MC/Mips/micromips32r6/valid.s @@ -58,4 +58,10 @@ subu $3, $4, $5 # CHECK: subu $3, $4, $5 # encoding: [0x00,0xa4,0x19,0xd0] xor $3, $4, $5 # CHECK: xor $3, $4, $5 # encoding: [0x00,0xa4,0x1b,0x10] xori $3, $4, 1234 # CHECK: xori $3, $4, 1234 # encoding: [0x70,0x64,0x04,0xd2] + ext $9, $6, 3, 7 # CHECK: ext $9, $6, 3, 7 # encoding: [0x01,0x26,0x30,0xec] + prefe 1, 8($5) # CHECK: prefe 1, 8($5) # encoding: [0x60,0x25,0xa4,0x08] + ins $9, $6, 3, 7 # CHECK: ins $9, $6, 3, 7 # encoding: [0x01,0x26,0x48,0xcc] + jalrc $4, $5 # CHECK: jalrc $4, $5 # encoding: [0x00,0x85,0x0f,0x3c] + jalrc $5 # CHECK: jalrc $ra, $5 # encoding: [0x03,0xe5,0x0f,0x3c] + jr $5 # CHECK: jalrc $zero, $5 # encoding: [0x00,0x05,0x0f,0x3c]