[mips][microMIPS] Implement disassembler support for 16-bit instructions

With the help of new method readInstruction16() two bytes are read and
decodeInstruction() is called with DecoderTableMicroMips16, if this fails
four bytes are read and decodeInstruction() is called with
DecoderTableMicroMips32.

Differential Revision: http://reviews.llvm.org/D6149


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222648 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jozef Kolek 2014-11-24 13:29:59 +00:00
parent a1e1f01699
commit 18700de8fc
4 changed files with 147 additions and 14 deletions

View File

@ -700,6 +700,26 @@ static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn,
return MCDisassembler::Success;
}
/// Read two bytes from the ArrayRef and return 16 bit halfword sorted
/// according to the given endianess.
static DecodeStatus readInstruction16(ArrayRef<uint8_t> 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<uint8_t> Bytes, uint64_t Address,
@ -711,15 +731,19 @@ static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
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);
@ -738,14 +762,25 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
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);
@ -756,6 +791,10 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
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 =
@ -854,7 +893,11 @@ static DecodeStatus DecodeGPRMM16RegisterClass(MCInst &Inst,
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 DecodeGPR32RegisterClass(MCInst &Inst,

View File

@ -289,10 +289,10 @@ def GPR32 : GPR32Class<[i32]>;
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 GPR64 : RegisterClass<"Mips", [i64], 64, (add
// Reserved

View File

@ -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

View File

@ -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