[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