[AVR] Implement disassembly of 32-bit instructions
authorAyke van Laethem <aykevanlaethem@gmail.com>
Tue, 16 Jun 2020 19:39:09 +0000 (21:39 +0200)
committerAyke van Laethem <aykevanlaethem@gmail.com>
Thu, 18 Jun 2020 09:26:58 +0000 (11:26 +0200)
This needed two fixes:

  * 32-bit instructions were read in the wrong order. The machine code
    swaps the two 16-bit instruction words, which wasn't undone when
    decoding instructions.
  * Jump and call instructions don't encode the lowest address bit,
    which is always zero. Therefore, the address needed to be shifted by
    one to fix that.

Differential Revision: https://reviews.llvm.org/D81961

llvm/lib/Target/AVR/AVRInstrInfo.td
llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
llvm/test/MC/AVR/inst-call.s
llvm/test/MC/AVR/inst-jmp.s
llvm/test/MC/AVR/inst-lds.s
llvm/test/MC/AVR/inst-sts.s

index e64f465..b66eb79 100644 (file)
@@ -193,6 +193,7 @@ def brtarget_13 : Operand<OtherVT>
 def call_target : Operand<iPTR>
 {
     let EncoderMethod = "encodeCallTarget";
+    let DecoderMethod = "decodeCallTarget";
 }
 
 // A 16-bit address (which can lead to an R_AVR_16 relocation).
index a5c08c4..093e6a4 100644 (file)
@@ -104,6 +104,9 @@ static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn,
 static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn,
                                  uint64_t Address, const void *Decoder);
 
+static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Insn,
+                                     uint64_t Address, const void *Decoder);
+
 #include "AVRGenDisassemblerTables.inc"
 
 static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn,
@@ -139,6 +142,14 @@ static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Field,
+                                     uint64_t Address, const void *Decoder) {
+  // Call targets need to be shifted left by one so this needs a custom
+  // decoder.
+  Inst.addOperand(MCOperand::createImm(Field << 1));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
                                       uint64_t &Size, uint32_t &Insn) {
   if (Bytes.size() < 2) {
@@ -161,7 +172,7 @@ static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
   }
 
   Size = 4;
-  Insn = (Bytes[0] << 0) | (Bytes[1] << 8) | (Bytes[2] << 16) | (Bytes[3] << 24);
+  Insn = (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
 
   return MCDisassembler::Success;
 }
index 312c8ff..9f3d0eb 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llvm-mc -triple avr -mattr=jmpcall -show-encoding < %s | FileCheck %s
+; RUN: llvm-mc -filetype=obj -triple avr -mattr=jmpcall < %s | llvm-objdump -dr --mattr=jmpcall - | FileCheck -check-prefix=CHECK-INST %s
 
 
 foo:
@@ -12,3 +13,9 @@ foo:
 ; CHECK: call -124                  ; encoding: [0xff,0x95,0xc2,0xff]
 ; CHECK: call -12                   ; encoding: [0xff,0x95,0xfa,0xff]
 ; CHECK: call  0                    ; encoding: [0x0e,0x94,0x00,0x00]
+
+
+; CHECK-INST: call 4096
+; CHECK-INST: call 8388484
+; CHECK-INST: call 8388596
+; CHECK-INST: call 0
index 664f8c8..369181c 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llvm-mc -triple avr -mattr=jmpcall -show-encoding < %s | FileCheck %s
+; RUN: llvm-mc -filetype=obj -triple avr -mattr=jmpcall < %s | llvm-objdump -dr --mattr=jmpcall - | FileCheck -check-prefix=CHECK-INST %s
 
 
 foo:
@@ -10,6 +11,10 @@ foo:
 
   jmp foo+1
 
+  jmp   0x03fffe ; Inst{16-0}  or k{16-0}
+  jmp   0x7c0000 ; Inst{24-20} or k{21-17}
+  jmp   0x7ffffe ; all bits set
+
 ; CHECK: jmp  200                  ; encoding: [0x0c,0x94,0x64,0x00]
 ; CHECK: jmp -12                   ; encoding: [0xfd,0x95,0xfa,0xff]
 ; CHECK: jmp  80                   ; encoding: [0x0c,0x94,0x28,0x00]
@@ -17,3 +22,18 @@ foo:
 
 ; CHECK: jmp foo+1                 ; encoding: [0x0c'A',0x94'A',0b00AAAAAA,0x00]
 ; CHECK:                           ;   fixup A - offset: 0, value: foo+1, kind: fixup_call
+
+; CHECK: jmp 262142                ; encoding: [0x0d,0x94,0xff,0xff]
+; CHECK: jmp 8126464               ; encoding: [0xfc,0x95,0x00,0x00]
+; CHECK: jmp 8388606               ; encoding: [0xfd,0x95,0xff,0xff]
+
+
+; CHECK-INST: jmp 200
+; CHECK-INST: jmp 8388596
+; CHECK-INST: jmp 80
+; CHECK-INST: jmp 0
+; CHECK-INST: jmp 0
+; CHECK-INST:     R_AVR_CALL .text+0x1
+; CHECK-INST: jmp 262142
+; CHECK-INST: jmp 8126464
+; CHECK-INST: jmp 8388606
index e8151a3..2936b24 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llvm-mc -triple avr -mattr=sram -show-encoding < %s | FileCheck %s
+; RUN: llvm-mc -filetype=obj -triple avr -mattr=sram < %s | llvm-objdump -dr --mattr=sram - | FileCheck -check-prefix=CHECK-INST %s
 
 
 foo:
@@ -14,3 +15,11 @@ foo:
 ; CHECK: lds r27, 92                  ; encoding: [0xb0,0x91,0x5c,0x00]
 ; CHECK: lds r4, SYMBOL+12            ; encoding: [0x40,0x90,A,A]
 ; CHECK:                              ;   fixup A - offset: 2, value: SYMBOL+12, kind: fixup_16
+
+
+; CHECK-INST: lds r16, 241
+; CHECK-INST: lds r29, 190
+; CHECK-INST: lds r22, 172
+; CHECK-INST: lds r27, 92
+; CHECK-INST: lds r4,  0
+; CHECK-INST:     R_AVR_16 SYMBOL+0xc
index 0f5af7d..d2cc1fc 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llvm-mc -triple avr -mattr=sram -show-encoding < %s | FileCheck %s
+; RUN: llvm-mc -filetype=obj -triple avr -mattr=sram < %s | llvm-objdump -dr --mattr=sram - | FileCheck -check-prefix=CHECK-INST %s
 
 
 foo:
@@ -12,3 +13,8 @@ foo:
 ; CHECK:  sts SYMBOL+1, r25           ; encoding: [0x90,0x93,A,A]
 ; CHECK:                              ;   fixup A - offset: 2, value: SYMBOL+1, kind: fixup_16
 
+
+; CHECK-INST: sts 3, r5
+; CHECK-INST: sts 255, r7
+; CHECK-INST: sts 0, r25
+; CHECK-INST:     R_AVR_16 SYMBOL+0x1