[llvm] b1dcd6b - [MC][AVR] Implement decoding ST/LD

Ben Shi via llvm-commits llvm-commits at lists.llvm.org
Wed May 4 19:08:20 PDT 2022


Author: Ben Shi
Date: 2022-05-05T01:53:59Z
New Revision: b1dcd6bafb9096cf86e67664260dc4c0348b5764

URL: https://github.com/llvm/llvm-project/commit/b1dcd6bafb9096cf86e67664260dc4c0348b5764
DIFF: https://github.com/llvm/llvm-project/commit/b1dcd6bafb9096cf86e67664260dc4c0348b5764.diff

LOG: [MC][AVR] Implement decoding ST/LD

Reviewed By: aykevl, dylanmckay

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

Added: 
    

Modified: 
    llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
    llvm/test/MC/AVR/inst-ld.s
    llvm/test/MC/AVR/inst-st.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
index 23554109680bb5..20d1cf9c0d5cdd 100644
--- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
+++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
@@ -276,9 +276,11 @@ static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,
 static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
                                     uint64_t Address,
                                     const MCDisassembler *Decoder) {
+  // Get the register will be loaded or stored.
+  unsigned RegVal = GPRDecoderTable[(Insn >> 4) & 0x1f];
+
   // Decode LDD/STD with offset less than 8.
   if ((Insn & 0xf000) == 0x8000) {
-    unsigned RegVal = GPRDecoderTable[(Insn >> 4) & 0x1f];
     unsigned RegBase = (Insn & 0x8) ? AVR::R29R28 : AVR::R31R30;
     unsigned Offset = Insn & 7; // We need not consider offset > 7.
     if ((Insn & 0x200) == 0) { // Decode LDD.
@@ -295,8 +297,85 @@ static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
     return MCDisassembler::Success;
   }
 
-  // TODO: Decode ST/LD with postinc/predec properly.
-  return MCDisassembler::Fail;
+  // Decode the following 14 instructions. Bit 9 indicates load(0) or store(1),
+  // bits 8~4 indicate the value register, bits 3-2 indicate the base address
+  // register (11-X, 10-Y, 00-Z), bits 1~0 indicate the mode (00-basic,
+  // 01-postinc, 10-predec).
+  // ST X,  Rr : 1001 001r rrrr 1100
+  // ST X+, Rr : 1001 001r rrrr 1101
+  // ST -X, Rr : 1001 001r rrrr 1110
+  // ST Y+, Rr : 1001 001r rrrr 1001
+  // ST -Y, Rr : 1001 001r rrrr 1010
+  // ST Z+, Rr : 1001 001r rrrr 0001
+  // ST -Z, Rr : 1001 001r rrrr 0010
+  // LD Rd, X  : 1001 000d dddd 1100
+  // LD Rd, X+ : 1001 000d dddd 1101
+  // LD Rd, -X : 1001 000d dddd 1110
+  // LD Rd, Y+ : 1001 000d dddd 1001
+  // LD Rd, -Y : 1001 000d dddd 1010
+  // LD Rd, Z+ : 1001 000d dddd 0001
+  // LD Rd, -Z : 1001 000d dddd 0010
+  if ((Insn & 0xfc00) != 0x9000 || (Insn & 0xf) == 0)
+    return MCDisassembler::Fail;
+
+  // Get the base address register.
+  unsigned RegBase;
+  switch (Insn & 0xc) {
+  case 0xc:
+    RegBase = AVR::R27R26;
+    break;
+  case 0x8:
+    RegBase = AVR::R29R28;
+    break;
+  case 0x0:
+    RegBase = AVR::R31R30;
+    break;
+  default:
+    return MCDisassembler::Fail;
+  }
+
+  // Set the opcode.
+  switch (Insn & 0x203) {
+  case 0x200:
+    Inst.setOpcode(AVR::STPtrRr);
+    Inst.addOperand(MCOperand::createReg(RegBase));
+    Inst.addOperand(MCOperand::createReg(RegVal));
+    return MCDisassembler::Success;
+  case 0x201:
+    Inst.setOpcode(AVR::STPtrPiRr);
+    break;
+  case 0x202:
+    Inst.setOpcode(AVR::STPtrPdRr);
+    break;
+  case 0:
+    Inst.setOpcode(AVR::LDRdPtr);
+    Inst.addOperand(MCOperand::createReg(RegVal));
+    Inst.addOperand(MCOperand::createReg(RegBase));
+    return MCDisassembler::Success;
+  case 1:
+    Inst.setOpcode(AVR::LDRdPtrPi);
+    break;
+  case 2:
+    Inst.setOpcode(AVR::LDRdPtrPd);
+    break;
+  default:
+    return MCDisassembler::Fail;
+  }
+
+  // Build postinc/predec machine instructions.
+  if ((Insn & 0x200) == 0) { // This is a load instruction.
+    Inst.addOperand(MCOperand::createReg(RegVal));
+    Inst.addOperand(MCOperand::createReg(RegBase));
+    Inst.addOperand(MCOperand::createReg(RegBase));
+  } else { // This is a store instruction.
+    Inst.addOperand(MCOperand::createReg(RegBase));
+    Inst.addOperand(MCOperand::createReg(RegBase));
+    Inst.addOperand(MCOperand::createReg(RegVal));
+    // STPtrPiRr and STPtrPdRr have an extra immediate operand.
+    Inst.addOperand(MCOperand::createImm(1));
+  }
+
+  return MCDisassembler::Success;
 }
 
 static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
@@ -357,7 +436,12 @@ DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
     // Try to auto-decode a 16-bit instruction.
     Result = decodeInstruction(getDecoderTable(Size), Instr, Insn, Address,
                                this, STI);
+    if (Result != MCDisassembler::Fail)
+      return Result;
 
+    // Try to decode to a load/store instruction. ST/LD need a specified
+    // DecoderMethod, as they already have a specified PostEncoderMethod.
+    Result = decodeLoadStore(Instr, Insn, Address, this);
     if (Result != MCDisassembler::Fail)
       return Result;
   }

diff  --git a/llvm/test/MC/AVR/inst-ld.s b/llvm/test/MC/AVR/inst-ld.s
index 3b0ade182518b3..ad3f8fd62616bd 100644
--- a/llvm/test/MC/AVR/inst-ld.s
+++ b/llvm/test/MC/AVR/inst-ld.s
@@ -1,4 +1,6 @@
 ; RUN: llvm-mc -triple avr -mattr=sram -show-encoding < %s | FileCheck %s
+; RUN: llvm-mc -filetype=obj -triple avr -mattr=sram < %s \
+; RUN:     | llvm-objdump -d --mattr=sram - | FileCheck --check-prefix=INST %s
 
 
 foo:
@@ -71,3 +73,24 @@ foo:
 
 ; CHECK: ld r10, -Z                 ; encoding: [0xa2,0x90]
 ; CHECK: ld r2,  -Z                 ; encoding: [0x22,0x90]
+
+; INST: ld r10, X
+; INST: ld r17, X
+; INST: ldd r30, Y+0
+; INST: ldd r19, Y+0
+; INST: ldd r10, Z+0
+; INST: ldd r2,  Z+0
+
+; INST: ld r10, X+
+; INST: ld r17, X+
+; INST: ld r30, Y+
+; INST: ld r19, Y+
+; INST: ld r10, Z+
+; INST: ld r2,  Z+
+
+; INST: ld r10, -X
+; INST: ld r17, -X
+; INST: ld r30, -Y
+; INST: ld r19, -Y
+; INST: ld r10, -Z
+; INST: ld r2,  -Z

diff  --git a/llvm/test/MC/AVR/inst-st.s b/llvm/test/MC/AVR/inst-st.s
index 8d9a4a6fe1527a..ffa9a3c4370215 100644
--- a/llvm/test/MC/AVR/inst-st.s
+++ b/llvm/test/MC/AVR/inst-st.s
@@ -1,4 +1,6 @@
 ; RUN: llvm-mc -triple avr -mattr=sram -show-encoding < %s | FileCheck %s
+; RUN: llvm-mc -filetype=obj -triple avr -mattr=sram < %s \
+; RUN:     | llvm-objdump -d --mattr=sram - | FileCheck --check-prefix=INST %s
 
 
 foo:
@@ -69,3 +71,24 @@ foo:
 
 ; CHECK: st -Z,  r10                  ; encoding: [0xa2,0x92]
 ; CHECK: st -Z,  r2                   ; encoding: [0x22,0x92]
+
+; INST: st X, r10
+; INST: st X, r17
+; INST: std Y+0, r30
+; INST: std Y+0, r19
+; INST: std Z+0, r10
+; INST: std Z+0, r2
+
+; INST: st X+, r10
+; INST: st X+, r17
+; INST: st Y+, r30
+; INST: st Y+, r19
+; INST: st Z+, r10
+; INST: st Z+, r2
+
+; INST: st -X, r10
+; INST: st -X, r17
+; INST: st -Y, r30
+; INST: st -Y, r19
+; INST: st -Z, r10
+; INST: st -Z, r2


        


More information about the llvm-commits mailing list