[llvm] 77249ea - [AVR] Support 16-bit LDS/STS on AVRTiny.

Ben Shi via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 22 19:04:00 PST 2022


Author: Ben Shi
Date: 2022-12-23T11:03:45+08:00
New Revision: 77249ea6bc6601d2637cf6c1d73c87c25faf1b71

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

LOG: [AVR] Support 16-bit LDS/STS on AVRTiny.

LDS/STS are 32-bit instructions on AVR, which can access up to
64KB data space. While they are 16-bit instructions on AVRTiny,
which can only access 128B data space.

Reviewed By: aykevl

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

Added: 
    llvm/test/MC/AVR/inst-lds-tiny.s
    llvm/test/MC/AVR/inst-sts-tiny.s

Modified: 
    llvm/lib/Target/AVR/AVRInstrFormats.td
    llvm/lib/Target/AVR/AVRInstrInfo.td
    llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
    llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AVR/AVRInstrFormats.td b/llvm/lib/Target/AVR/AVRInstrFormats.td
index 533bcd9ec2725..dd8da7092d471 100644
--- a/llvm/lib/Target/AVR/AVRInstrFormats.td
+++ b/llvm/lib/Target/AVR/AVRInstrFormats.td
@@ -502,6 +502,29 @@ class F32DM<bit f, dag outs, dag ins, string asmstr, list<dag> pattern>
   let Inst{15 - 0} = k;
 }
 
+//===---------------------------------------------------------------------===//
+// Special format for the LDS/STS instructions on AVRTiny.
+// <|1010|ikkk|dddd|kkkk>
+// d = R16 ~ R31
+// i = 0 - lds, 1 - sts
+// k = 7-bit data space address
+//===---------------------------------------------------------------------===//
+class FLDSSTSTINY<bit i, dag outs, dag ins, string asmstr, list<dag> pattern>
+    : AVRInst16<outs, ins, asmstr, pattern> {
+  bits<5> rd;
+  bits<7> k;
+
+  let Inst{15 - 12} = 0b1010;
+
+  let Inst{11} = i;
+
+  let Inst{10 - 8} = k{6 - 4};
+  let Inst{7 - 4} = rd{3 - 0};
+  let Inst{3 - 0} = k{3 - 0};
+
+  let DecoderNamespace = "AVRTiny";
+}
+
 // <|1001|0100|bfff|1000>
 class FS<bit b, dag outs, dag ins, string asmstr, list<dag> pattern>
     : AVRInst16<outs, ins, asmstr, pattern> {

diff  --git a/llvm/lib/Target/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td
index 412cb7ebb31b5..4a4e2062f91db 100644
--- a/llvm/lib/Target/AVR/AVRInstrInfo.td
+++ b/llvm/lib/Target/AVR/AVRInstrInfo.td
@@ -212,6 +212,11 @@ def call_target : Operand<iPTR> {
 // A 16-bit address (which can lead to an R_AVR_16 relocation).
 def imm16 : Operand<i16> { let EncoderMethod = "encodeImm<AVR::fixup_16, 2>"; }
 
+// A 7-bit address (which can lead to an R_AVR_LDS_STS_16 relocation).
+def imm7tiny : Operand<i8> {
+  let EncoderMethod = "encodeImm<AVR::fixup_lds_sts_16, 0>";
+}
+
 /// A 6-bit immediate used in the ADIW/SBIW instructions.
 def imm_arith6 : Operand<i16> {
   let EncoderMethod = "encodeImm<AVR::fixup_6_adiw, 0>";
@@ -321,7 +326,7 @@ def HasTinyEncoding : Predicate<"Subtarget->hasTinyEncoding()">,
                       AssemblerPredicate<(all_of FeatureTinyEncoding)>;
 
 def HasNonTinyEncoding : Predicate<"!Subtarget->hasTinyEncoding()">,
-                         AssemblerPredicate<(all_of (not FeatureTinyEncoding))>;
+                         AssemblerPredicate<(any_of (not FeatureTinyEncoding))>;
 
 // AVR specific condition code. These correspond to AVR_*_COND in
 // AVRInstrInfo.td. They must be kept in synch.
@@ -1288,6 +1293,11 @@ let canFoldAsLoad = 1, isReMaterializable = 1 in {
                                                : $k))]>,
                Requires<[HasSRAM, HasNonTinyEncoding]>;
 
+  // Load from data space into register, which is only available on AVRTiny.
+  def LDSRdKTiny : FLDSSTSTINY<0b0, (outs LD8:$rd), (ins imm7tiny:$k),
+                               "lds\t$rd, $k", []>,
+                   Requires<[HasSRAM, HasTinyEncoding]>;
+
   // LDSW Rd+1:Rd, K+1:K
   //
   // Expands to:
@@ -1506,6 +1516,11 @@ def STSKRr : F32DM<0b1, (outs),
                                      : $k)]>,
              Requires<[HasSRAM, HasNonTinyEncoding]>;
 
+// Store from register to data space, which is only available on AVRTiny.
+def STSKRrTiny : FLDSSTSTINY<0b1, (outs), (ins imm7tiny:$k, LD8:$rd),
+                             "sts\t$k, $rd", []>,
+                 Requires<[HasSRAM, HasTinyEncoding]>;
+
 // STSW K+1:K, Rr+1:Rr
 //
 // Expands to:

diff  --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
index ee0ae08e192fb..d8734596148d5 100644
--- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
+++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
@@ -425,6 +425,14 @@ DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
     if (Result == MCDisassembler::Fail)
       return MCDisassembler::Fail;
 
+    // Try to decode AVRTiny instructions.
+    if (STI.getFeatureBits()[AVR::FeatureTinyEncoding]) {
+      Result = decodeInstruction(DecoderTableAVRTiny16, Instr, Insn, Address,
+                                 this, STI);
+      if (Result != MCDisassembler::Fail)
+        return Result;
+    }
+
     // Try to auto-decode a 16-bit instruction.
     Result = decodeInstruction(getDecoderTable(Size), Instr, Insn, Address,
                                this, STI);

diff  --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
index 3624ade854c00..da9ad4960ef41 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
@@ -187,6 +187,16 @@ static void fixup_port6(const MCFixup &Fixup, uint64_t &Value,
   Value = ((Value & 0x30) << 5) | (Value & 0x0f);
 }
 
+/// 7-bit data space address fixup for the LDS/STS instructions on AVRTiny.
+///
+/// Resolves to:
+/// 1010 ikkk dddd kkkk
+static void fixup_lds_sts_16(const MCFixup &Fixup, uint64_t &Value,
+                             MCContext *Ctx = nullptr) {
+  unsigned_width(7, Value, std::string("immediate"), Fixup, Ctx);
+  Value = ((Value & 0x70) << 8) | (Value & 0x0f);
+}
+
 /// Adjusts a program memory address.
 /// This is a simple right-shift.
 static void pm(uint64_t &Value) { Value >>= 1; }
@@ -343,6 +353,10 @@ void AVRAsmBackend::adjustFixupValue(const MCFixup &Fixup,
     adjust::fixup_port6(Fixup, Value, Ctx);
     break;
 
+  case AVR::fixup_lds_sts_16:
+    adjust::fixup_lds_sts_16(Fixup, Value, Ctx);
+    break;
+
   // Fixups which do not require adjustments.
   case FK_Data_1:
   case FK_Data_2:

diff  --git a/llvm/test/MC/AVR/inst-lds-tiny.s b/llvm/test/MC/AVR/inst-lds-tiny.s
new file mode 100644
index 0000000000000..9faea6b0a928e
--- /dev/null
+++ b/llvm/test/MC/AVR/inst-lds-tiny.s
@@ -0,0 +1,23 @@
+; RUN: llvm-mc -triple avr -mattr=sram,tinyencoding -show-encoding < %s | FileCheck %s
+; RUN: llvm-mc -filetype=obj -triple avr -mattr=sram,tinyencoding < %s | llvm-objdump --no-print-imm-hex -dr --mattr=sram,tinyencoding - | FileCheck -check-prefix=CHECK-INST %s
+
+foo:
+  lds r16, 113
+  lds r29, 62
+  lds r22, 44
+  lds r27, 92
+  lds r20, SYMBOL+12
+
+; CHECK:  lds r16, 113                 ; encoding: [0x01,0xa7]
+; CHECK:  lds r29, 62                  ; encoding: [0xde,0xa3]
+; CHECK:  lds r22, 44                  ; encoding: [0x6c,0xa2]
+; CHECK:  lds r27, 92                  ; encoding: [0xbc,0xa5]
+; CHECK:  lds r20, SYMBOL+12           ; encoding: [0x40'A',0xa0'A']
+; CHECK:                               ; fixup A - offset: 0, value: SYMBOL+12, kind: fixup_lds_sts_16
+
+; CHECK-INST: lds r16, 113
+; CHECK-INST: lds r29, 62
+; CHECK-INST: lds r22, 44
+; CHECK-INST: lds r27, 92
+; CHECK-INST: lds r20,  0
+; CHECK-INST: R_AVR_LDS_STS_16 SYMBOL+0xc

diff  --git a/llvm/test/MC/AVR/inst-sts-tiny.s b/llvm/test/MC/AVR/inst-sts-tiny.s
new file mode 100644
index 0000000000000..a3b1208cbeb95
--- /dev/null
+++ b/llvm/test/MC/AVR/inst-sts-tiny.s
@@ -0,0 +1,17 @@
+; RUN: llvm-mc -triple avr -mattr=sram,tinyencoding -show-encoding < %s | FileCheck %s
+; RUN: llvm-mc -filetype=obj -triple avr -mattr=sram,tinyencoding < %s | llvm-objdump --no-print-imm-hex -dr --mattr=sram,tinyencoding - | FileCheck -check-prefix=CHECK-INST %s
+
+foo:
+  sts 3,        r16
+  sts 127,      r17
+  sts SYMBOL+1, r25
+
+; CHECK:  sts 3,        r16           ; encoding: [0x03,0xa8]
+; CHECK:  sts 127,      r17           ; encoding: [0x1f,0xaf]
+; CHECK:  sts SYMBOL+1, r25           ; encoding: [0x90'A',0xa8'A']
+; CHECK:                              ; fixup A - offset: 0, value: SYMBOL+1, kind: fixup_lds_sts_16
+
+; CHECK-INST: sts 3,   r16
+; CHECK-INST: sts 127, r17
+; CHECK-INST: sts 0,   r25
+; CHECK-INST: R_AVR_LDS_STS_16 SYMBOL+0x1


        


More information about the llvm-commits mailing list