[llvm] [Mips] Emit 16-bit microMIPS NOPs for alignment (PR #228879)

Jiaxun Yang via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 4 05:44:16 PDT 2026


https://github.com/FlyGoat updated https://github.com/llvm/llvm-project/pull/228879

>From 028a4f3cb524ea4ac9424fcddb20f3b7c3c5b7ae Mon Sep 17 00:00:00 2001
From: Jiaxun Yang <jiaxun.yang at flygoat.com>
Date: Sun, 4 Oct 2026 12:23:41 +0100
Subject: [PATCH] [Mips] Emit 16-bit microMIPS NOPs for alignment

Zero-filled halfword padding is not a complete microMIPS NOP. Emit
move $zero, $zero when alignment requires a two-byte instruction, then
use zero-encoded 32-bit NOPs for the remaining padding.

Handle an odd leading byte as data padding and preserve zero filling in
standard MIPS mode. Extend the unaligned-NOP test to cover both byte
orders, odd-sized data, and mode changes.

Assisted-by: OpenAI Codex # Testcases
---
 .../Mips/MCTargetDesc/MipsAsmBackend.cpp      | 26 ++++++++++----
 llvm/test/MC/Mips/unaligned-nops.s            | 36 +++++++++++++++++++
 2 files changed, 56 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
index 74e7baf1db293e..71069722aa4a14 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
@@ -24,6 +24,7 @@
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCTargetOptions.h"
 #include "llvm/MC/MCValue.h"
+#include "llvm/Support/EndianStream.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
@@ -583,13 +584,26 @@ MCFixupKindInfo MipsAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
 /// \return - True on success.
 bool MipsAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
                                   const MCSubtargetInfo *STI) const {
-  // Check for a less than instruction size number of bytes
-  // FIXME: 16 bit instructions are not handled yet here.
-  // We shouldn't be using a hard coded number for instruction size.
+  // We mostly follow binutils' convention here: align to an even boundary with
+  // zero-fill padding, then emit up to one 2-byte NOP. Use move $zero, $zero
+  // for microMIPS, or zero-fill for standard MIPS. Pad the remainder with
+  // 4-byte NOPs.
+
+  // An odd byte is data padding. Align to an instruction boundary first.
+  if (Count % 2) {
+    OS.write_zeros(1);
+    Count -= 1;
+  }
+
+  if (Count % 4 == 2) {
+    // Use move $zero, $zero for a microMIPS 16-bit NOP. For standard MIPS,
+    // this halfword is data padding.
+    uint16_t Nop = STI && STI->hasFeature(Mips::FeatureMicroMips) ? 0x0c00 : 0;
+    support::endian::write<uint16_t>(OS, Nop, Endian);
+    Count -= 2;
+  }
 
-  // If the count is not 4-byte aligned, we must be writing data into the text
-  // section (otherwise we have unaligned instructions, and thus have far
-  // bigger problems), so just write zeros instead.
+  // Zero encodes a 32-bit NOP in both standard MIPS and microMIPS.
   OS.write_zeros(Count);
   return true;
 }
diff --git a/llvm/test/MC/Mips/unaligned-nops.s b/llvm/test/MC/Mips/unaligned-nops.s
index ebbbb40f4dc691..45dc65d9b2ec52 100644
--- a/llvm/test/MC/Mips/unaligned-nops.s
+++ b/llvm/test/MC/Mips/unaligned-nops.s
@@ -1,4 +1,40 @@
+# RUN: llvm-mc -triple=mipsel -mcpu=mips32r2 -mattr=+micromips -filetype=obj %s -o %t.le.o
+# RUN: llvm-objdump -s -j .text.micromips %t.le.o | FileCheck %s --check-prefix=LE
+# RUN: llvm-mc -triple=mips -mcpu=mips32r2 -mattr=+micromips -filetype=obj %s -o %t.be.o
+# RUN: llvm-objdump -s -j .text.micromips %t.be.o | FileCheck %s --check-prefix=BE
 # RUN: llvm-mc -filetype=obj  -triple=mipsel %s -o %t
 .byte 1
 .p2align 2
 foo:
+
+.section .text.micromips,"ax", at progbits
+.set micromips
+.set noreorder
+  move $2, $3
+  .p2align 2
+  move $2, $3
+  .p2align 3
+  move $2, $3
+  .p2align 3
+
+## Emit one 16-bit NOP (0x0c00), then fill the remaining words with zero NOPs.
+# LE: 0000 430c000c 430c000c 430c000c 00000000
+# BE: 0000 0c430c00 0c430c00 0c430c00 00000000
+
+## An odd-sized data item needs a zero byte before the NOPs.
+  .byte 0xff
+  .p2align 3
+
+## Standard MIPS padding remains zero; .set pop restores microMIPS padding.
+.set push
+.set nomicromips
+  nop
+  .p2align 3
+.set pop
+  move $2, $3
+  .p2align 3
+
+# LE: 0010 ff00000c 00000000 00000000 00000000
+# BE: 0010 ff000c00 00000000 00000000 00000000
+# LE: 0020 430c000c 00000000
+# BE: 0020 0c430c00 00000000



More information about the llvm-commits mailing list