mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-11 05:17:36 +00:00
[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:
parent
a1e1f01699
commit
18700de8fc
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user