Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -1100,12 +1100,21 @@ unsigned Insn, uint64_t Address, const void *Decoder) { - int Offset = SignExtend32<12>(Insn & 0xfff); + int Offset; unsigned Base = fieldFromInstruction(Insn, 16, 5); unsigned Hint = fieldFromInstruction(Insn, 21, 5); Base = getReg(Decoder, Mips::GPR32RegClassID, Base); + switch (Inst.getOpcode()) { + default: + Offset = SignExtend32<12>(Insn & 0xfff); + break; + case Mips::CACHEE_MMR6: + Offset = SignExtend32<9>(Insn & 0x1ff); + break; + } + Inst.addOperand(MCOperand::createReg(Base)); Inst.addOperand(MCOperand::createImm(Offset)); Inst.addOperand(MCOperand::createImm(Hint)); Index: lib/Target/Mips/MicroMips32r6InstrFormats.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrFormats.td +++ lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -43,6 +43,20 @@ let Inst{11-0} = addr{11-0}; } +class CACHEE_FM_MMR6 opgroup, bits<4> fmt, bits<3> funct> : MipsR6Inst { + bits<21> addr; + bits<5> hint; + + bits<32> Inst; + + let Inst{31-26} = opgroup; + let Inst{25-21} = hint; + let Inst{20-16} = addr{20-16}; + let Inst{15-12} = fmt; + let Inst{11-9} = funct; + let Inst{8-0} = addr{8-0}; +} + class ARITH_FM_MMR6 funct> : MMR6Arch { bits<5> rd; bits<5> rt; @@ -225,3 +239,15 @@ let Inst{8-0} = addr{8-0}; } +class WSBH_FM_MMR6 funct> : MipsR6Inst { + bits<5> rt; + bits<5> rs; + + bits<32> Inst; + + let Inst{31-26} = 0x00; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-6} = funct; + let Inst{5-0} = 0x3c; +} Index: lib/Target/Mips/MicroMips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrInfo.td +++ lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -30,6 +30,7 @@ class BC_MMR6_ENC : BRANCH_OFF26_FM<0b100101>; class BITSWAP_MMR6_ENC : POOL32A_BITSWAP_FM_MMR6<0b101100>; class CACHE_MMR6_ENC : CACHE_PREF_FM_MMR6<0b001000, 0b0110>; +class CACHEE_MMR6_ENC : CACHEE_FM_MMR6<0b011000, 0b1010, 0b011>; class CLO_MMR6_ENC : POOL32A_2R_FM_MMR6<0b0100101100>; class CLZ_MMR6_ENC : SPECIAL_2R_FM_MMR6<0b010000>; class DIV_MMR6_ENC : ARITH_FM_MMR6<"div", 0x118>; @@ -64,6 +65,8 @@ 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>; +class WRPGPR_MMR6_ENC : WSBH_FM_MMR6<0x3c5>; +class WSBH_MMR6_ENC : WSBH_FM_MMR6<0x1ec>; //===----------------------------------------------------------------------===// // @@ -115,6 +118,7 @@ } class CACHE_MMR6_DESC : CACHE_HINT_MMR6_DESC<"cache", mem_mm_12, GPR32Opnd>; +class CACHEE_MMR6_DESC : CACHE_HINT_MMR6_DESC<"cachee", mem_simm9gpr, GPR32Opnd>; class PREF_MMR6_DESC : CACHE_HINT_MMR6_DESC<"pref", mem_mm_12, GPR32Opnd>; class CLO_CLZ_MMR6_DESC_BASE @@ -246,6 +250,19 @@ class LHE_MMR6_DESC : LoadMemory<"lhe", GPR32Opnd, mem_simm9gpr>; class LHuE_MMR6_DESC : LoadMemory<"lhue", GPR32Opnd, mem_simm9gpr>; +class WORDSWAP_MMR6_DESC_BASE + : MMR6Arch { + dag InOperandList = (ins RO:$rs); + dag OutOperandList = (outs RO:$rt); + string AsmString = !strconcat(instr_asm, "\t$rt, $rs"); + list Pattern = []; + Format f = FrmR; + string BaseOpcode = instr_asm; + bit hasSideEffects = 0; +} +class WRPGPR_MMR6_DESC : WORDSWAP_MMR6_DESC_BASE<"wrpgpr", GPR32Opnd>; +class WSBH_MMR6_DESC : WORDSWAP_MMR6_DESC_BASE<"wsbh", GPR32Opnd>; + //===----------------------------------------------------------------------===// // // Instruction Definitions @@ -270,6 +287,8 @@ def BITSWAP_MMR6 : R6MMR6Rel, BITSWAP_MMR6_ENC, BITSWAP_MMR6_DESC, ISA_MICROMIPS32R6; def CACHE_MMR6 : R6MMR6Rel, CACHE_MMR6_ENC, CACHE_MMR6_DESC, ISA_MICROMIPS32R6; +def CACHEE_MMR6 : StdMMR6Rel, CACHEE_MMR6_ENC, CACHEE_MMR6_DESC, + ISA_MICROMIPS32R6; def CLO_MMR6 : R6MMR6Rel, CLO_MMR6_ENC, CLO_MMR6_DESC, ISA_MICROMIPS32R6; def CLZ_MMR6 : R6MMR6Rel, CLZ_MMR6_ENC, CLZ_MMR6_DESC, ISA_MICROMIPS32R6; def DIV_MMR6 : R6MMR6Rel, DIV_MMR6_DESC, DIV_MMR6_ENC, ISA_MICROMIPS32R6; @@ -313,4 +332,6 @@ def LHuE_MMR6 : StdMMR6Rel, LHuE_MMR6_DESC, LHuE_MMR6_ENC, ISA_MICROMIPS32R6; } +def WRPGPR_MMR6 : StdMMR6Rel, WRPGPR_MMR6_ENC, WRPGPR_MMR6_DESC, ISA_MICROMIPS32R6; +def WSBH_MMR6 : StdMMR6Rel, WSBH_MMR6_ENC, WSBH_MMR6_DESC, ISA_MICROMIPS32R6; } Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -1457,8 +1457,10 @@ def CLO : MMRel, CountLeading1<"clo", GPR32Opnd>, CLO_FM<0x21>, ISA_MIPS32_NOT_32R6_64R6; +let AdditionalPredicates = [NotInMicroMips] in { /// Word Swap Bytes Within Halfwords def WSBH : MMRel, SubwordSwap<"wsbh", GPR32Opnd>, SEB_FM<2, 0x20>, ISA_MIPS32R2; +} /// No operation. def NOP : PseudoSE<(outs), (ins), []>, PseudoInstExpansion<(SLL ZERO, ZERO, 0)>; Index: test/MC/Disassembler/Mips/micromips32r6.txt =================================================================== --- test/MC/Disassembler/Mips/micromips32r6.txt +++ test/MC/Disassembler/Mips/micromips32r6.txt @@ -32,6 +32,8 @@ # CHECK: cache 1, 8($5) 0x20 0x25 0x60 0x08 +0x60 0x25 0xa6 0x08 # CHECK: cachee 1, 8($5) + 0x01 0x65 0x4b 0x3c # CHECK: clo $11, $5 0x03 0x80 0xe8 0x50 # CHECK: clz $sp, $gp @@ -77,6 +79,10 @@ 0x00 0xa4 0x19 0xd0 # CHECK: subu $3, $4, $5 +0x00 0x64 0xf1 0x7c # CHECK: wrpgpr $3, $4 + +0x00 0x64 0x7b 0x3c # CHECK: wsbh $3, $4 + 0x00 0xa4 0x1b 0x10 # CHECK: xor $3, $4, $5 0x70 0x64 0x04 0xd2 # CHECK: xori $3, $4, 1234 Index: test/MC/Mips/micromips32r6/invalid.s =================================================================== --- test/MC/Mips/micromips32r6/invalid.s +++ test/MC/Mips/micromips32r6/invalid.s @@ -1,6 +1,13 @@ # RUN: not llvm-mc %s -triple=mips -show-encoding -mcpu=mips32r6 -mattr=micromips 2>%t1 # RUN: FileCheck %s < %t1 + wrpgpr $34, $4 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + wrpgpr $3, $33 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + wsbh $34, $4 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + wsbh $3, $33 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + cachee 1, 8($34) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + cachee 1, 512($34) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + cachee 32, 8($34) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction teq $34, $9, 5 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction teq $8, $35, 6 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction teq $8, $9, 16 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range Index: test/MC/Mips/micromips32r6/valid.s =================================================================== --- test/MC/Mips/micromips32r6/valid.s +++ test/MC/Mips/micromips32r6/valid.s @@ -15,6 +15,7 @@ bc 14572256 # CHECK: bc 14572256 # encoding: [0x94,0x37,0x96,0xb8] bitswap $4, $2 # CHECK: bitswap $4, $2 # encoding: [0x00,0x44,0x0b,0x3c] cache 1, 8($5) # CHECK: cache 1, 8($5) # encoding: [0x20,0x25,0x60,0x08] + cachee 1, 8($5) # CHECK: cachee 1, 8($5) # encoding: [0x60,0x25,0xa6,0x08] clo $11, $a1 # CHECK: clo $11, $5 # encoding: [0x01,0x65,0x4b,0x3c] clz $sp, $gp # CHECK: clz $sp, $gp # encoding: [0x03,0x80,0xe8,0x50] div $3, $4, $5 # CHECK: div $3, $4, $5 # encoding: [0x00,0xa4,0x19,0x18] @@ -37,7 +38,8 @@ selnez $2,$3,$4 # CHECK: selnez $2, $3, $4 # encoding: [0x00,0x83,0x11,0x80] sub $3, $4, $5 # CHECK: sub $3, $4, $5 # encoding: [0x00,0xa4,0x19,0x90] subu $3, $4, $5 # CHECK: subu $3, $4, $5 # encoding: [0x00,0xa4,0x19,0xd0] - + wrpgpr $3, $4 # CHECK: wrpgpr $3, $4 # encoding: [0x00,0x64,0xf1,0x7c] + wsbh $3, $4 # CHECK: wsbh $3, $4 # encoding: [0x00,0x64,0x7b,0x3c] 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]