diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -1073,8 +1073,11 @@ } unsigned X86AsmBackend::getMaximumNopSize() const { - if (!STI.hasFeature(X86::FeatureNOPL) && !STI.hasFeature(X86::Mode64Bit)) + if (!STI.hasFeature(X86::FeatureNOPL) && !STI.hasFeature(X86::Mode64Bit) && + !STI.hasFeature(X86::Mode16Bit)) return 1; + if (STI.getFeatureBits()[X86::Mode16Bit]) + return 4; if (STI.getFeatureBits()[X86::FeatureFast7ByteNOP]) return 7; if (STI.getFeatureBits()[X86::FeatureFast15ByteNOP]) @@ -1091,29 +1094,44 @@ /// bytes. /// \return - true on success, false on failure bool X86AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { - static const char Nops[10][11] = { - // nop - "\x90", - // xchg %ax,%ax - "\x66\x90", - // nopl (%[re]ax) - "\x0f\x1f\x00", - // nopl 0(%[re]ax) - "\x0f\x1f\x40\x00", - // nopl 0(%[re]ax,%[re]ax,1) - "\x0f\x1f\x44\x00\x00", - // nopw 0(%[re]ax,%[re]ax,1) - "\x66\x0f\x1f\x44\x00\x00", - // nopl 0L(%[re]ax) - "\x0f\x1f\x80\x00\x00\x00\x00", - // nopl 0L(%[re]ax,%[re]ax,1) - "\x0f\x1f\x84\x00\x00\x00\x00\x00", - // nopw 0L(%[re]ax,%[re]ax,1) - "\x66\x0f\x1f\x84\x00\x00\x00\x00\x00", - // nopw %cs:0L(%[re]ax,%[re]ax,1) - "\x66\x2e\x0f\x1f\x84\x00\x00\x00\x00\x00", + static const char Nops32Bit[10][11] = { + // nop + "\x90", + // xchg %ax,%ax + "\x66\x90", + // nopl (%[re]ax) + "\x0f\x1f\x00", + // nopl 0(%[re]ax) + "\x0f\x1f\x40\x00", + // nopl 0(%[re]ax,%[re]ax,1) + "\x0f\x1f\x44\x00\x00", + // nopw 0(%[re]ax,%[re]ax,1) + "\x66\x0f\x1f\x44\x00\x00", + // nopl 0L(%[re]ax) + "\x0f\x1f\x80\x00\x00\x00\x00", + // nopl 0L(%[re]ax,%[re]ax,1) + "\x0f\x1f\x84\x00\x00\x00\x00\x00", + // nopw 0L(%[re]ax,%[re]ax,1) + "\x66\x0f\x1f\x84\x00\x00\x00\x00\x00", + // nopw %cs:0L(%[re]ax,%[re]ax,1) + "\x66\x2e\x0f\x1f\x84\x00\x00\x00\x00\x00", }; + // 16-bit mode uses different nop patterns than 32-bit. + static const char Nops16Bit[4][11] = { + // nop + "\x90", + // xchg %eax,%eax + "\x66\x90", + // lea 0(%si),%si + "\x8d\x74\x00", + // lea 0w(%si),%si + "\x8d\xb4\x00\x00", + }; + + const char(*Nops)[11] = + STI.getFeatureBits()[X86::Mode16Bit] ? Nops16Bit : Nops32Bit; + uint64_t MaxNopLength = (uint64_t)getMaximumNopSize(); // Emit as many MaxNopLength NOPs as needed, then emit a NOP of the remaining diff --git a/llvm/test/MC/X86/code16gcc-align.s b/llvm/test/MC/X86/code16gcc-align.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/X86/code16gcc-align.s @@ -0,0 +1,40 @@ +# RUN: llvm-mc -filetype=obj -triple=i386-unknown-unknown-code16 %s | llvm-objdump --triple=i386-unknown-unknown-code16 -d - | FileCheck %s + +# Ensure that the "movzbl" is aligned such that the prefixes 0x67 0x66 are +# properly included in the "movz" instruction. + +# CHECK-LABEL: : +# CHECK: 1c: 8d b4 00 00 leaw (%si), %si +# CHECK-NEXT: 20: 66 90 nop +# CHECK-NEXT: 22: 66 89 c7 movl %eax, %edi +# CHECK-NEXT: 25: 66 31 db xorl %ebx, %ebx +# CHECK-NEXT: 28: 8d b4 00 00 leaw (%si), %si +# CHECK-NEXT: 2c: 8d b4 00 00 leaw (%si), %si +# CHECK-NEXT: 30: 67 66 0f b6 0c 1e movzbl (%esi,%ebx), %ecx +# CHECK-NEXT: 36: 66 e8 14 00 00 00 calll 0x50 +# CHECK-NEXT: 3c: 8d 74 00 leaw (%si), %si + +# CHECK-LABEL: : +# CHECK-NEXT: 50: 90 nop +# CHECK-NEXT: 51: 66 c3 retl + + .text + .code16gcc + .globl test + .p2align 4, 0x90 + .type test,@function +test: + .nops 34 + movl %eax, %edi + xorl %ebx, %ebx + .p2align 4, 0x90 + movzbl (%esi,%ebx), %ecx + calll called + .nops 3 + retl + + .p2align 4, 0x90 + .type called,@function +called: + .nops 1 + retl