Skip to content

Commit ea22c4c

Browse files
author
Jozef Kolek
committedNov 24, 2014
[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 llvm-svn: 222648
1 parent 23e2cfa commit ea22c4c

File tree

4 files changed

+147
-14
lines changed

4 files changed

+147
-14
lines changed
 

‎llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp

+54-11
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,26 @@ static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn,
700700
return MCDisassembler::Success;
701701
}
702702

703+
/// Read two bytes from the ArrayRef and return 16 bit halfword sorted
704+
/// according to the given endianess.
705+
static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
706+
uint64_t &Size, uint32_t &Insn,
707+
bool IsBigEndian) {
708+
// We want to read exactly 2 Bytes of data.
709+
if (Bytes.size() < 2) {
710+
Size = 0;
711+
return MCDisassembler::Fail;
712+
}
713+
714+
if (IsBigEndian) {
715+
Insn = (Bytes[0] << 8) | Bytes[1];
716+
} else {
717+
Insn = (Bytes[1] << 8) | Bytes[0];
718+
}
719+
720+
return MCDisassembler::Success;
721+
}
722+
703723
/// Read four bytes from the ArrayRef and return 32 bit word sorted
704724
/// according to the given endianess
705725
static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
@@ -711,15 +731,19 @@ static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
711731
return MCDisassembler::Fail;
712732
}
713733

734+
// High 16 bits of a 32-bit microMIPS instruction (where the opcode is)
735+
// always precede the low 16 bits in the instruction stream (that is, they
736+
// are placed at lower addresses in the instruction stream).
737+
//
738+
// microMIPS byte ordering:
739+
// Big-endian: 0 | 1 | 2 | 3
740+
// Little-endian: 1 | 0 | 3 | 2
741+
714742
if (IsBigEndian) {
715743
// Encoded as a big-endian 32-bit word in the stream.
716744
Insn =
717745
(Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) | (Bytes[0] << 24);
718746
} else {
719-
// Encoded as a small-endian 32-bit word in the stream.
720-
// Little-endian byte ordering:
721-
// mips32r2: 4 | 3 | 2 | 1
722-
// microMIPS: 2 | 1 | 4 | 3
723747
if (IsMicroMips) {
724748
Insn = (Bytes[2] << 0) | (Bytes[3] << 8) | (Bytes[0] << 16) |
725749
(Bytes[1] << 24);
@@ -738,14 +762,25 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
738762
raw_ostream &VStream,
739763
raw_ostream &CStream) const {
740764
uint32_t Insn;
741-
742-
DecodeStatus Result =
743-
readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, IsMicroMips);
744-
if (Result == MCDisassembler::Fail)
745-
return MCDisassembler::Fail;
765+
DecodeStatus Result;
746766

747767
if (IsMicroMips) {
748-
DEBUG(dbgs() << "Trying MicroMips32 table (32-bit opcodes):\n");
768+
Result = readInstruction16(Bytes, Address, Size, Insn, IsBigEndian);
769+
770+
DEBUG(dbgs() << "Trying MicroMips16 table (16-bit instructions):\n");
771+
// Calling the auto-generated decoder function.
772+
Result = decodeInstruction(DecoderTableMicroMips16, Instr, Insn, Address,
773+
this, STI);
774+
if (Result != MCDisassembler::Fail) {
775+
Size = 2;
776+
return Result;
777+
}
778+
779+
Result = readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, true);
780+
if (Result == MCDisassembler::Fail)
781+
return MCDisassembler::Fail;
782+
783+
DEBUG(dbgs() << "Trying MicroMips32 table (32-bit instructions):\n");
749784
// Calling the auto-generated decoder function.
750785
Result = decodeInstruction(DecoderTableMicroMips32, Instr, Insn, Address,
751786
this, STI);
@@ -756,6 +791,10 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
756791
return MCDisassembler::Fail;
757792
}
758793

794+
Result = readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, false);
795+
if (Result == MCDisassembler::Fail)
796+
return MCDisassembler::Fail;
797+
759798
if (hasCOP3()) {
760799
DEBUG(dbgs() << "Trying COP3_ table (32-bit opcodes):\n");
761800
Result =
@@ -854,7 +893,11 @@ static DecodeStatus DecodeGPRMM16RegisterClass(MCInst &Inst,
854893
unsigned RegNo,
855894
uint64_t Address,
856895
const void *Decoder) {
857-
return MCDisassembler::Fail;
896+
if (RegNo > 7)
897+
return MCDisassembler::Fail;
898+
unsigned Reg = getReg(Decoder, Mips::GPRMM16RegClassID, RegNo);
899+
Inst.addOperand(MCOperand::CreateReg(Reg));
900+
return MCDisassembler::Success;
858901
}
859902

860903
static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst,

‎llvm/lib/Target/Mips/MipsRegisterInfo.td

+3-3
Original file line numberDiff line numberDiff line change
@@ -289,10 +289,10 @@ def GPR32 : GPR32Class<[i32]>;
289289
def DSPR : GPR32Class<[v4i8, v2i16]>;
290290

291291
def GPRMM16 : RegisterClass<"Mips", [i32], 32, (add
292-
// Return Values and Arguments
293-
V0, V1, A0, A1, A2, A3,
294292
// Callee save
295-
S0, S1)>;
293+
S0, S1,
294+
// Return Values and Arguments
295+
V0, V1, A0, A1, A2, A3)>;
296296

297297
def GPR64 : RegisterClass<"Mips", [i64], 64, (add
298298
// Reserved

‎llvm/test/MC/Disassembler/Mips/micromips.txt

+45
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,48 @@
321321

322322
# CHECK: swm32 $16, $17, 8($4)
323323
0x20 0x44 0xd0 0x08
324+
325+
# CHECK: addu16 $6, $17, $4
326+
0x07 0x42
327+
328+
# CHECK: subu16 $5, $16, $3
329+
0x06 0xb1
330+
331+
# CHECK: and16 $16, $2
332+
0x44 0x82
333+
334+
# CHECK: not16 $17, $3
335+
0x44 0x0b
336+
337+
# CHECK: or16 $16, $4
338+
0x44 0xc4
339+
340+
# CHECK: xor16 $17, $5
341+
0x44 0x4d
342+
343+
# CHECK: sll16 $3, $16, 5
344+
0x25 0x8a
345+
346+
# CHECK: srl16 $4, $17, 6
347+
0x26 0x1d
348+
349+
# CHECK: mfhi $9
350+
0x46 0x09
351+
352+
# CHECK: mflo $9
353+
0x46 0x49
354+
355+
# CHECK: move $25, $1
356+
0x0f 0x21
357+
358+
# CHECK: jrc $9
359+
0x45 0xa9
360+
361+
# CHECK: jalr $9
362+
0x45 0xc9
363+
364+
# CHECK: jalrs16 $9
365+
0x45 0xe9
366+
367+
# CHECK: jr16 $9
368+
0x45 0x89

‎llvm/test/MC/Disassembler/Mips/micromips_le.txt

+45
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,48 @@
321321

322322
# CHECK: swm32 $16, $17, 8($4)
323323
0x44 0x20 0x08 0xd0
324+
325+
# CHECK: addu16 $6, $17, $4
326+
0x42 0x07
327+
328+
# CHECK: subu16 $5, $16, $3
329+
0xb1 0x06
330+
331+
# CHECK: and16 $16, $2
332+
0x82 0x44
333+
334+
# CHECK: not16 $17, $3
335+
0x0b 0x44
336+
337+
# CHECK: or16 $16, $4
338+
0xc4 0x44
339+
340+
# CHECK: xor16 $17, $5
341+
0x4d 0x44
342+
343+
# CHECK: sll16 $3, $16, 5
344+
0x8a 0x25
345+
346+
# CHECK: srl16 $4, $17, 6
347+
0x1d 0x26
348+
349+
# CHECK: mfhi $9
350+
0x09 0x46
351+
352+
# CHECK: mflo $9
353+
0x49 0x46
354+
355+
# CHECK: move $25, $1
356+
0x21 0x0f
357+
358+
# CHECK: jrc $9
359+
0xa9 0x45
360+
361+
# CHECK: jalr $9
362+
0xc9 0x45
363+
364+
# CHECK: jalrs16 $9
365+
0xe9 0x45
366+
367+
# CHECK: jr16 $9
368+
0x89 0x45

0 commit comments

Comments
 (0)
Please sign in to comment.