Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -705,6 +705,28 @@ return MCDisassembler::Success; } +/// Read two bytes from the ArrayRef and return 16 bit halfword sorted +/// according to the given endianess +static DecodeStatus readInstruction16(ArrayRef Bytes, + uint64_t Address, + uint64_t &Size, + uint32_t &Insn, + bool IsBigEndian) { + // We want to read exactly 2 Bytes of data. + if (Bytes.size() < 2) { + Size = 0; + return MCDisassembler::Fail; + } + + if (IsBigEndian) { + Insn = (Bytes[0] << 8) | Bytes[1]; + } else { + Insn = (Bytes[1] << 8) | Bytes[0]; + } + + return MCDisassembler::Success; +} + /// Read four bytes from the ArrayRef and return 32 bit word sorted /// according to the given endianess static DecodeStatus readInstruction32(ArrayRef Bytes, uint64_t Address, @@ -716,15 +738,19 @@ return MCDisassembler::Fail; } + // High 16 bits of a 32-bit microMIPS instruction (where the opcode is) + // always precede the low 16 bits in the instruction stream (that is, they + // are placed at lower addresses in the instruction stream). + // + // MicroMIPS byte ordering: + // Big-endian: 0 | 1 | 2 | 3 + // Little-endian: 1 | 0 | 3 | 2 + if (IsBigEndian) { // Encoded as a big-endian 32-bit word in the stream. Insn = (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) | (Bytes[0] << 24); } else { - // Encoded as a small-endian 32-bit word in the stream. - // Little-endian byte ordering: - // mips32r2: 4 | 3 | 2 | 1 - // microMIPS: 2 | 1 | 4 | 3 if (IsMicroMips) { Insn = (Bytes[2] << 0) | (Bytes[3] << 8) | (Bytes[0] << 16) | (Bytes[1] << 24); @@ -743,14 +769,25 @@ raw_ostream &VStream, raw_ostream &CStream) const { uint32_t Insn; - - DecodeStatus Result = - readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, IsMicroMips); - if (Result == MCDisassembler::Fail) - return MCDisassembler::Fail; + DecodeStatus Result; if (IsMicroMips) { - DEBUG(dbgs() << "Trying MicroMips32 table (32-bit opcodes):\n"); + Result = readInstruction16(Bytes, Address, Size, Insn, IsBigEndian); + + DEBUG(dbgs() << "Trying MicroMips16 table (16-bit instructions):\n"); + // Calling the auto-generated decoder function. + Result = decodeInstruction(DecoderTableMicroMips16, Instr, Insn, Address, + this, STI); + if (Result != MCDisassembler::Fail) { + Size = 2; + return Result; + } + + Result = readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, true); + if (Result == MCDisassembler::Fail) + return MCDisassembler::Fail; + + DEBUG(dbgs() << "Trying MicroMips32 table (32-bit instructions):\n"); // Calling the auto-generated decoder function. Result = decodeInstruction(DecoderTableMicroMips32, Instr, Insn, Address, this, STI); @@ -761,6 +798,10 @@ return MCDisassembler::Fail; } + Result = readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, false); + if (Result == MCDisassembler::Fail) + return MCDisassembler::Fail; + if (hasCOP3()) { DEBUG(dbgs() << "Trying COP3_ table (32-bit opcodes):\n"); Result = @@ -859,7 +900,11 @@ unsigned RegNo, uint64_t Address, const void *Decoder) { - return MCDisassembler::Fail; + if (RegNo > 7) + return MCDisassembler::Fail; + unsigned Reg = getReg(Decoder, Mips::GPRMM16RegClassID, RegNo); + Inst.addOperand(MCOperand::CreateReg(Reg)); + return MCDisassembler::Success; } static DecodeStatus DecodeGPRMM16ZeroRegisterClass(MCInst &Inst, Index: lib/Target/Mips/MipsRegisterInfo.td =================================================================== --- lib/Target/Mips/MipsRegisterInfo.td +++ lib/Target/Mips/MipsRegisterInfo.td @@ -289,10 +289,10 @@ def DSPR : GPR32Class<[v4i8, v2i16]>; def GPRMM16 : RegisterClass<"Mips", [i32], 32, (add - // Return Values and Arguments - V0, V1, A0, A1, A2, A3, // Callee save - S0, S1)>; + S0, S1, + // Return Values and Arguments + V0, V1, A0, A1, A2, A3)>; def GPRMM16Zero : RegisterClass<"Mips", [i32], 32, (add // Reserved Index: test/MC/Disassembler/Mips/micromips.txt =================================================================== --- test/MC/Disassembler/Mips/micromips.txt +++ test/MC/Disassembler/Mips/micromips.txt @@ -321,3 +321,48 @@ # CHECK: swm32 $16, $17, 8($4) 0x20 0x44 0xd0 0x08 + +# CHECK: addu16 $6, $17, $4 +0x07 0x42 + +# CHECK: subu16 $5, $16, $3 +0x06 0xb1 + +# CHECK: and16 $16, $2 +0x44 0x82 + +# CHECK: not16 $17, $3 +0x44 0x0b + +# CHECK: or16 $16, $4 +0x44 0xc4 + +# CHECK: xor16 $17, $5 +0x44 0x4d + +# CHECK: sll16 $3, $16, 5 +0x25 0x8a + +# CHECK: srl16 $4, $17, 6 +0x26 0x1d + +# CHECK: mfhi $9 +0x46 0x09 + +# CHECK: mflo $9 +0x46 0x49 + +# CHECK: move $25, $1 +0x0f 0x21 + +# CHECK: jrc $9 +0x45 0xa9 + +# CHECK: jalr $9 +0x45 0xc9 + +# CHECK: jalrs16 $9 +0x45 0xe9 + +# CHECK: jr16 $9 +0x45 0x89 Index: test/MC/Disassembler/Mips/micromips_le.txt =================================================================== --- test/MC/Disassembler/Mips/micromips_le.txt +++ test/MC/Disassembler/Mips/micromips_le.txt @@ -321,3 +321,48 @@ # CHECK: swm32 $16, $17, 8($4) 0x44 0x20 0x08 0xd0 + +# CHECK: addu16 $6, $17, $4 +0x42 0x07 + +# CHECK: subu16 $5, $16, $3 +0xb1 0x06 + +# CHECK: and16 $16, $2 +0x82 0x44 + +# CHECK: not16 $17, $3 +0x0b 0x44 + +# CHECK: or16 $16, $4 +0xc4 0x44 + +# CHECK: xor16 $17, $5 +0x4d 0x44 + +# CHECK: sll16 $3, $16, 5 +0x8a 0x25 + +# CHECK: srl16 $4, $17, 6 +0x1d 0x26 + +# CHECK: mfhi $9 +0x09 0x46 + +# CHECK: mflo $9 +0x49 0x46 + +# CHECK: move $25, $1 +0x21 0x0f + +# CHECK: jrc $9 +0xa9 0x45 + +# CHECK: jalr $9 +0xc9 0x45 + +# CHECK: jalrs16 $9 +0xe9 0x45 + +# CHECK: jr16 $9 +0x89 0x45