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

Jozef Kolek jozef.kolek at imgtec.com
Mon Nov 24 05:30:00 PST 2014


Author: jkolek
Date: Mon Nov 24 07:29:59 2014
New Revision: 222648

URL: http://llvm.org/viewvc/llvm-project?rev=222648&view=rev
Log:
[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

Modified:
    llvm/trunk/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
    llvm/trunk/lib/Target/Mips/MipsRegisterInfo.td
    llvm/trunk/test/MC/Disassembler/Mips/micromips.txt
    llvm/trunk/test/MC/Disassembler/Mips/micromips_le.txt

Modified: llvm/trunk/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/Disassembler/MipsDisassembler.cpp?rev=222648&r1=222647&r2=222648&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/Disassembler/MipsDisassembler.cpp (original)
+++ llvm/trunk/lib/Target/Mips/Disassembler/MipsDisassembler.cpp Mon Nov 24 07:29:59 2014
@@ -700,6 +700,26 @@ static DecodeStatus DecodeBlezGroupBranc
   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(Ar
     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::getInstru
                                               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::getInstru
     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 DecodeGPRMM16Registe
                                                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,

Modified: llvm/trunk/lib/Target/Mips/MipsRegisterInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsRegisterInfo.td?rev=222648&r1=222647&r2=222648&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsRegisterInfo.td (original)
+++ llvm/trunk/lib/Target/Mips/MipsRegisterInfo.td Mon Nov 24 07:29:59 2014
@@ -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

Modified: llvm/trunk/test/MC/Disassembler/Mips/micromips.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/Mips/micromips.txt?rev=222648&r1=222647&r2=222648&view=diff
==============================================================================
--- llvm/trunk/test/MC/Disassembler/Mips/micromips.txt (original)
+++ llvm/trunk/test/MC/Disassembler/Mips/micromips.txt Mon Nov 24 07:29:59 2014
@@ -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

Modified: llvm/trunk/test/MC/Disassembler/Mips/micromips_le.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/Mips/micromips_le.txt?rev=222648&r1=222647&r2=222648&view=diff
==============================================================================
--- llvm/trunk/test/MC/Disassembler/Mips/micromips_le.txt (original)
+++ llvm/trunk/test/MC/Disassembler/Mips/micromips_le.txt Mon Nov 24 07:29:59 2014
@@ -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





More information about the llvm-commits mailing list