[llvm] [AVR] Add AVR MOVW/ADIW/SUBIW disassembly (PR #146360)

Tom Vijlbrief via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 30 12:48:23 PDT 2025


https://github.com/tomtor updated https://github.com/llvm/llvm-project/pull/146360

>From fcb60b224ff92d17a5d413fae6a4aca79f86b547 Mon Sep 17 00:00:00 2001
From: Tom Vijlbrief <tvijlbrief at gmail.com>
Date: Mon, 30 Jun 2025 15:12:51 +0200
Subject: [PATCH 1/6] [AVR] Add MOVW disassembly

---
 .../AVR/Disassembler/AVRDisassembler.cpp      | 21 +++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
index c7a584868f4e6..dd7d6b0ab3389 100644
--- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
+++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
@@ -328,6 +328,22 @@ static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus decodeMoveWord(MCInst &Inst, unsigned Insn,
+                                   uint64_t Address,
+                                   const MCDisassembler *Decoder) {
+  // Get the registers
+  unsigned RegValD = GPRDecoderTable[2 * ((Insn >> 4) & 0xf)];
+  unsigned RegValR = GPRDecoderTable[2 * (Insn & 0xf)];
+
+  if ((Insn & 0xff00) == 0x0100) {
+    Inst.setOpcode(AVR::MOVWRdRr);
+    Inst.addOperand(MCOperand::createReg(RegValD));
+    Inst.addOperand(MCOperand::createReg(RegValR));
+    return MCDisassembler::Success;
+  }
+  return MCDisassembler::Fail;
+}
+
 static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
                                     uint64_t Address,
                                     const MCDisassembler *Decoder) {
@@ -502,6 +518,11 @@ DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
     if (Result != MCDisassembler::Fail)
       return Result;
 
+    // Try to decode to a MOVW instruction
+    Result = decodeMoveWord(Instr, Insn, Address, this);
+    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);

>From 2f48e117a11812b800181df3e65c0686b2dc7a85 Mon Sep 17 00:00:00 2001
From: Tom Vijlbrief <tvijlbrief at gmail.com>
Date: Mon, 30 Jun 2025 15:51:51 +0200
Subject: [PATCH 2/6] [AVR] Add ADIW disassembly

---
 .../AVR/Disassembler/AVRDisassembler.cpp      | 21 +++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
index dd7d6b0ab3389..1bf68daeef192 100644
--- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
+++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
@@ -328,6 +328,22 @@ static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus decodeAddWordImm(MCInst &Inst, unsigned Insn,
+                                     uint64_t Address,
+                                     const MCDisassembler *Decoder) {
+  // Get the register
+  unsigned RegVal = GPRDecoderTable[24 + 2 * ((Insn >> 4) & 0x3)];
+
+  if ((Insn & 0xff00) == 0x9600) {
+    Inst.setOpcode(AVR::ADIWRdK);
+    Inst.addOperand(MCOperand::createReg(RegVal));
+    Inst.addOperand(
+        MCOperand::createImm(((Insn & 0x00C0) >> 2) | (Insn & 0xF)));
+    return MCDisassembler::Success;
+  }
+  return MCDisassembler::Fail;
+}
+
 static DecodeStatus decodeMoveWord(MCInst &Inst, unsigned Insn,
                                    uint64_t Address,
                                    const MCDisassembler *Decoder) {
@@ -522,6 +538,11 @@ DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
     Result = decodeMoveWord(Instr, Insn, Address, this);
     if (Result != MCDisassembler::Fail)
       return Result;
+    
+    // Try to decode to a ADIW instruction
+    Result = decodeAddWordImm(Instr, Insn, Address, this);
+    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.

>From b9eeb0c34ca5e1631c1136417aacab0ec9dd6569 Mon Sep 17 00:00:00 2001
From: Tom Vijlbrief <tvijlbrief at gmail.com>
Date: Mon, 30 Jun 2025 16:29:22 +0200
Subject: [PATCH 3/6] [AVR] Add SUBIW disassembly

---
 llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
index 1bf68daeef192..5af0fa78929e8 100644
--- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
+++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
@@ -328,14 +328,14 @@ static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn,
   return MCDisassembler::Success;
 }
 
-static DecodeStatus decodeAddWordImm(MCInst &Inst, unsigned Insn,
-                                     uint64_t Address,
-                                     const MCDisassembler *Decoder) {
+static DecodeStatus decodeAddSubWordImm(MCInst &Inst, unsigned Insn,
+                                        uint64_t Address,
+                                        const MCDisassembler *Decoder) {
   // Get the register
   unsigned RegVal = GPRDecoderTable[24 + 2 * ((Insn >> 4) & 0x3)];
 
-  if ((Insn & 0xff00) == 0x9600) {
-    Inst.setOpcode(AVR::ADIWRdK);
+  if ((Insn & 0xfe00) == 0x9600) {
+    Inst.setOpcode((Insn & 0xff00) == 0x9600 ? AVR::ADIWRdK : AVR::SUBIWRdK);
     Inst.addOperand(MCOperand::createReg(RegVal));
     Inst.addOperand(
         MCOperand::createImm(((Insn & 0x00C0) >> 2) | (Insn & 0xF)));
@@ -540,7 +540,7 @@ DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
       return Result;
     
     // Try to decode to a ADIW instruction
-    Result = decodeAddWordImm(Instr, Insn, Address, this);
+    Result = decodeAddSubWordImm(Instr, Insn, Address, this);
     if (Result != MCDisassembler::Fail)
       return Result;
 

>From 9e26c524a40ee39f6a5c3451c559a72387b556a2 Mon Sep 17 00:00:00 2001
From: Tom Vijlbrief <tvijlbrief at gmail.com>
Date: Mon, 30 Jun 2025 17:02:32 +0200
Subject: [PATCH 4/6] fix formatting

---
 llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
index 5af0fa78929e8..dfa3724d0081b 100644
--- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
+++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
@@ -337,8 +337,8 @@ static DecodeStatus decodeAddSubWordImm(MCInst &Inst, unsigned Insn,
   if ((Insn & 0xfe00) == 0x9600) {
     Inst.setOpcode((Insn & 0xff00) == 0x9600 ? AVR::ADIWRdK : AVR::SUBIWRdK);
     Inst.addOperand(MCOperand::createReg(RegVal));
-    Inst.addOperand(
-        MCOperand::createImm(((Insn & 0x00C0) >> 2) | (Insn & 0xF)));
+    unsigned imm = ((Insn & 0x00C0) >> 2) | (Insn & 0xF);
+    Inst.addOperand(MCOperand::createImm(imm));
     return MCDisassembler::Success;
   }
   return MCDisassembler::Fail;
@@ -538,8 +538,8 @@ DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
     Result = decodeMoveWord(Instr, Insn, Address, this);
     if (Result != MCDisassembler::Fail)
       return Result;
-    
-    // Try to decode to a ADIW instruction
+
+    // Try to decode to a ADIW /SBIW instruction
     Result = decodeAddSubWordImm(Instr, Insn, Address, this);
     if (Result != MCDisassembler::Fail)
       return Result;

>From f711e7c33478cc53a9290d3b43ca9a012b67bdc4 Mon Sep 17 00:00:00 2001
From: Tom Vijlbrief <tvijlbrief at gmail.com>
Date: Mon, 30 Jun 2025 18:14:01 +0200
Subject: [PATCH 5/6] refactor

---
 .../AVR/Disassembler/AVRDisassembler.cpp      | 26 ++++++++++++++-----
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
index dfa3724d0081b..d5c9ed54d5f64 100644
--- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
+++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
@@ -331,10 +331,23 @@ static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn,
 static DecodeStatus decodeAddSubWordImm(MCInst &Inst, unsigned Insn,
                                         uint64_t Address,
                                         const MCDisassembler *Decoder) {
-  // Get the register
-  unsigned RegVal = GPRDecoderTable[24 + 2 * ((Insn >> 4) & 0x3)];
-
   if ((Insn & 0xfe00) == 0x9600) {
+    // Get the register
+    unsigned RegVal;
+    switch ((Insn >> 4) & 0x3) {
+    case 0:
+      RegVal = AVR::R25R24;
+      break;
+    case 1:
+      RegVal = AVR::R27R26;
+      break;
+    case 2:
+      RegVal = AVR::R29R28;
+      break;
+    case 3:
+      RegVal = AVR::R31R30;
+    }
+
     Inst.setOpcode((Insn & 0xff00) == 0x9600 ? AVR::ADIWRdK : AVR::SUBIWRdK);
     Inst.addOperand(MCOperand::createReg(RegVal));
     unsigned imm = ((Insn & 0x00C0) >> 2) | (Insn & 0xF);
@@ -347,11 +360,10 @@ static DecodeStatus decodeAddSubWordImm(MCInst &Inst, unsigned Insn,
 static DecodeStatus decodeMoveWord(MCInst &Inst, unsigned Insn,
                                    uint64_t Address,
                                    const MCDisassembler *Decoder) {
-  // Get the registers
-  unsigned RegValD = GPRDecoderTable[2 * ((Insn >> 4) & 0xf)];
-  unsigned RegValR = GPRDecoderTable[2 * (Insn & 0xf)];
-
   if ((Insn & 0xff00) == 0x0100) {
+    // Get the registers
+    unsigned RegValD = GPRDecoderTable[2 * ((Insn >> 4) & 0xf)];
+    unsigned RegValR = GPRDecoderTable[2 * (Insn & 0xf)];
     Inst.setOpcode(AVR::MOVWRdRr);
     Inst.addOperand(MCOperand::createReg(RegValD));
     Inst.addOperand(MCOperand::createReg(RegValR));

>From ad003f7de4eaf5a9cdc0c14bf35c6c53ba12dca4 Mon Sep 17 00:00:00 2001
From: Tom Vijlbrief <tvijlbrief at gmail.com>
Date: Mon, 30 Jun 2025 21:48:08 +0200
Subject: [PATCH 6/6] Add Patryk suggestion

---
 llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
index d5c9ed54d5f64..57b4ee819cbd3 100644
--- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
+++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
@@ -350,6 +350,7 @@ static DecodeStatus decodeAddSubWordImm(MCInst &Inst, unsigned Insn,
 
     Inst.setOpcode((Insn & 0xff00) == 0x9600 ? AVR::ADIWRdK : AVR::SUBIWRdK);
     Inst.addOperand(MCOperand::createReg(RegVal));
+    Inst.addOperand(MCOperand::createReg(RegVal));
     unsigned imm = ((Insn & 0x00C0) >> 2) | (Insn & 0xF);
     Inst.addOperand(MCOperand::createImm(imm));
     return MCDisassembler::Success;



More information about the llvm-commits mailing list