[llvm] cef2739 - [MC][AVR] Implement decoding STD/LDD

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


Author: Ben Shi
Date: 2022-05-05T01:53:49Z
New Revision: cef2739d682e329e4bf3aebcb82bf516438e095b

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

LOG: [MC][AVR] Implement decoding STD/LDD

Reviewed By: aykevl, dylanmckay

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

Added: 
    

Modified: 
    llvm/lib/Target/AVR/AVRInstrFormats.td
    llvm/lib/Target/AVR/AVRInstrInfo.td
    llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
    llvm/test/MC/AVR/inst-ldd.s
    llvm/test/MC/AVR/inst-std.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AVR/AVRInstrFormats.td b/llvm/lib/Target/AVR/AVRInstrFormats.td
index 2bcbcdfbf925c..83c32c80dfb98 100644
--- a/llvm/lib/Target/AVR/AVRInstrFormats.td
+++ b/llvm/lib/Target/AVR/AVRInstrFormats.td
@@ -179,7 +179,8 @@ class FSTDLDD<bit type, dag outs, dag ins, string asmstr, list<dag> pattern>
 // r = src/dst register
 //
 // Note that the bit labelled 'i' above does not follow a simple pattern,
-// so there exists a post encoder method to set it manually.
+// so there exists a post encoder method to set it manually. Also a specified
+// decoder method is needed.
 //===---------------------------------------------------------------------===//
 class FSTLD<bit type, bits<2> mode, dag outs, dag ins, string asmstr,
             list<dag> pattern> : AVRInst16<outs, ins, asmstr, pattern> {
@@ -200,6 +201,7 @@ class FSTLD<bit type, bits<2> mode, dag outs, dag ins, string asmstr,
   let Inst{3 - 2} = ptrreg{1 - 0};
   let Inst{1 - 0} = mode{1 - 0};
 
+  let DecoderMethod = "decodeLoadStore";
   let PostEncoderMethod = "loadStorePostEncoder";
 }
 

diff  --git a/llvm/lib/Target/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td
index 9b45b50ac98bd..b04c5978dd008 100644
--- a/llvm/lib/Target/AVR/AVRInstrInfo.td
+++ b/llvm/lib/Target/AVR/AVRInstrInfo.td
@@ -177,6 +177,7 @@ def memri : Operand<iPTR> {
 
   let PrintMethod = "printMemri";
   let EncoderMethod = "encodeMemri";
+  let DecoderMethod = "decodeMemri";
 
   let ParserMatchClass = MemriAsmOperand;
 }

diff  --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
index bc245d2306229..23554109680bb 100644
--- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
+++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
@@ -128,6 +128,13 @@ static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,
                                     uint64_t Address,
                                     const MCDisassembler *Decoder);
 
+static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,
+                                const MCDisassembler *Decoder);
+
+static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
+                                    uint64_t Address,
+                                    const MCDisassembler *Decoder);
+
 #include "AVRGenDisassemblerTables.inc"
 
 static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn, uint64_t Address,
@@ -249,6 +256,49 @@ static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,
+                                const MCDisassembler *Decoder) {
+  // As in the EncoderMethod `AVRMCCodeEmitter::encodeMemri`, the memory
+  // address is encoded into 7-bit, in which bits 0-5 are the immediate offset,
+  // and the bit-6 is the pointer register bit (Z=0, Y=1).
+  if (Insn > 127)
+    return MCDisassembler::Fail;
+
+  // Append the base register operand.
+  Inst.addOperand(
+      MCOperand::createReg((Insn & 0x40) ? AVR::R29R28 : AVR::R31R30));
+  // Append the immediate offset operand.
+  Inst.addOperand(MCOperand::createImm(Insn & 0x3f));
+
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
+                                    uint64_t Address,
+                                    const MCDisassembler *Decoder) {
+  // 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.
+      Inst.setOpcode(AVR::LDDRdPtrQ);
+      Inst.addOperand(MCOperand::createReg(RegVal));
+      Inst.addOperand(MCOperand::createReg(RegBase));
+      Inst.addOperand(MCOperand::createImm(Offset));
+    } else { // Decode STD.
+      Inst.setOpcode(AVR::STDPtrQRr);
+      Inst.addOperand(MCOperand::createReg(RegBase));
+      Inst.addOperand(MCOperand::createImm(Offset));
+      Inst.addOperand(MCOperand::createReg(RegVal));
+    }
+    return MCDisassembler::Success;
+  }
+
+  // TODO: Decode ST/LD with postinc/predec properly.
+  return MCDisassembler::Fail;
+}
+
 static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
                                       uint64_t &Size, uint32_t &Insn) {
   if (Bytes.size() < 2) {

diff  --git a/llvm/test/MC/AVR/inst-ldd.s b/llvm/test/MC/AVR/inst-ldd.s
index 974cd39665a15..66b2c04a68638 100644
--- a/llvm/test/MC/AVR/inst-ldd.s
+++ b/llvm/test/MC/AVR/inst-ldd.s
@@ -1,5 +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:
   ldd r2, Y+2
@@ -18,3 +19,8 @@ foo:
 
 ; CHECK: ldd r9, Z+foo                ; encoding: [0x90'A',0x80'A']
 ; CHECK:                              ;   fixup A - offset: 0, value: +foo, kind: fixup_6
+
+; INST: ldd r2, Y+2
+; INST: ldd r0, Y+0
+; INST: ldd r9, Z+12
+; INST: ldd r7, Z+30

diff  --git a/llvm/test/MC/AVR/inst-std.s b/llvm/test/MC/AVR/inst-std.s
index 94ae3bd2eb68f..571d5f475f9d7 100644
--- a/llvm/test/MC/AVR/inst-std.s
+++ b/llvm/test/MC/AVR/inst-std.s
@@ -1,5 +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:
 
@@ -20,3 +21,7 @@ foo:
 ; CHECK: std Y+foo, r9                ; encoding: [0x98'A',0x82'A']
 ; CHECK:                              ;   fixup A - offset: 0, value: +foo, kind: fixup_6
 
+; INST: std Y+2, r2
+; INST: std Y+0, r0
+; INST: std Z+12, r9
+; INST: std Z+30, r7


        


More information about the llvm-commits mailing list