[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