Skip to content

Commit 1d37198

Browse files
committed
[X86] Preserve redundant Address-Size override prefix
Print and emit redundant Address-Size override prefix if it's set on the instruction. Reviewed By: skan Differential Revision: https://reviews.llvm.org/D120592
1 parent e5b1b9e commit 1d37198

File tree

10 files changed

+166
-128
lines changed

10 files changed

+166
-128
lines changed

llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ void X86ATTInstPrinter::printInst(const MCInst *MI, uint64_t Address,
4646
if (CommentStream)
4747
HasCustomInstComment = EmitAnyX86InstComments(MI, *CommentStream, MII);
4848

49-
printInstFlags(MI, OS);
49+
printInstFlags(MI, OS, STI);
5050

5151
// Output CALLpcrel32 as "callq" in 64-bit mode.
5252
// In Intel annotation it's always emitted as "call".

llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@
1818
#include "llvm/MC/MCInst.h"
1919
#include "llvm/MC/MCInstrDesc.h"
2020
#include "llvm/MC/MCInstrInfo.h"
21-
#include "llvm/Support/raw_ostream.h"
21+
#include "llvm/MC/MCSubtargetInfo.h"
2222
#include "llvm/Support/Casting.h"
23-
#include <cstdint>
23+
#include "llvm/Support/raw_ostream.h"
2424
#include <cassert>
25+
#include <cstdint>
2526

2627
using namespace llvm;
2728

@@ -349,7 +350,8 @@ void X86InstPrinterCommon::printOptionalSegReg(const MCInst *MI, unsigned OpNo,
349350
}
350351
}
351352

352-
void X86InstPrinterCommon::printInstFlags(const MCInst *MI, raw_ostream &O) {
353+
void X86InstPrinterCommon::printInstFlags(const MCInst *MI, raw_ostream &O,
354+
const MCSubtargetInfo &STI) {
353355
const MCInstrDesc &Desc = MII.get(MI->getOpcode());
354356
uint64_t TSFlags = Desc.TSFlags;
355357
unsigned Flags = MI->getFlags();
@@ -379,6 +381,20 @@ void X86InstPrinterCommon::printInstFlags(const MCInst *MI, raw_ostream &O) {
379381
O << "\t{disp8}";
380382
else if (Flags & X86::IP_USE_DISP32)
381383
O << "\t{disp32}";
384+
385+
// Determine where the memory operand starts, if present
386+
int MemoryOperand = X86II::getMemoryOperandNo(TSFlags);
387+
if (MemoryOperand != -1)
388+
MemoryOperand += X86II::getOperandBias(Desc);
389+
390+
// Address-Size override prefix
391+
if (Flags & X86::IP_HAS_AD_SIZE &&
392+
!X86_MC::needsAddressSizeOverride(*MI, STI, MemoryOperand, TSFlags)) {
393+
if (STI.hasFeature(X86::Mode16Bit) || STI.hasFeature(X86::Mode64Bit))
394+
O << "\taddr32\t";
395+
else if (STI.hasFeature(X86::Mode32Bit))
396+
O << "\taddr16\t";
397+
}
382398
}
383399

384400
void X86InstPrinterCommon::printVKPair(const MCInst *MI, unsigned OpNo,

llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ class X86InstPrinterCommon : public MCInstPrinter {
3333
raw_ostream &O);
3434

3535
protected:
36-
void printInstFlags(const MCInst *MI, raw_ostream &O);
36+
void printInstFlags(const MCInst *MI, raw_ostream &O,
37+
const MCSubtargetInfo &STI);
3738
void printOptionalSegReg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
3839
void printVKPair(const MCInst *MI, unsigned OpNo, raw_ostream &OS);
3940
};

llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ void X86IntelInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
4040
void X86IntelInstPrinter::printInst(const MCInst *MI, uint64_t Address,
4141
StringRef Annot, const MCSubtargetInfo &STI,
4242
raw_ostream &OS) {
43-
printInstFlags(MI, OS);
43+
printInstFlags(MI, OS, STI);
4444

4545
// In 16-bit mode, print data16 as data32.
4646
if (MI->getOpcode() == X86::DATA16_PREFIX &&

llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp

Lines changed: 3 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -156,65 +156,6 @@ static MCFixupKind getImmFixupKind(uint64_t TSFlags) {
156156
return MCFixup::getKindForSize(Size, isPCRel);
157157
}
158158

159-
/// \param Op operand # of the memory operand.
160-
///
161-
/// \returns true if the specified instruction has a 16-bit memory operand.
162-
static bool is16BitMemOperand(const MCInst &MI, unsigned Op,
163-
const MCSubtargetInfo &STI) {
164-
const MCOperand &Base = MI.getOperand(Op + X86::AddrBaseReg);
165-
const MCOperand &Index = MI.getOperand(Op + X86::AddrIndexReg);
166-
167-
unsigned BaseReg = Base.getReg();
168-
unsigned IndexReg = Index.getReg();
169-
170-
if (STI.hasFeature(X86::Mode16Bit) && BaseReg == 0 && IndexReg == 0)
171-
return true;
172-
if ((BaseReg != 0 &&
173-
X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg)) ||
174-
(IndexReg != 0 &&
175-
X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg)))
176-
return true;
177-
return false;
178-
}
179-
180-
/// \param Op operand # of the memory operand.
181-
///
182-
/// \returns true if the specified instruction has a 32-bit memory operand.
183-
static bool is32BitMemOperand(const MCInst &MI, unsigned Op) {
184-
const MCOperand &BaseReg = MI.getOperand(Op + X86::AddrBaseReg);
185-
const MCOperand &IndexReg = MI.getOperand(Op + X86::AddrIndexReg);
186-
187-
if ((BaseReg.getReg() != 0 &&
188-
X86MCRegisterClasses[X86::GR32RegClassID].contains(BaseReg.getReg())) ||
189-
(IndexReg.getReg() != 0 &&
190-
X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg.getReg())))
191-
return true;
192-
if (BaseReg.getReg() == X86::EIP) {
193-
assert(IndexReg.getReg() == 0 && "Invalid eip-based address.");
194-
return true;
195-
}
196-
if (IndexReg.getReg() == X86::EIZ)
197-
return true;
198-
return false;
199-
}
200-
201-
/// \param Op operand # of the memory operand.
202-
///
203-
/// \returns true if the specified instruction has a 64-bit memory operand.
204-
#ifndef NDEBUG
205-
static bool is64BitMemOperand(const MCInst &MI, unsigned Op) {
206-
const MCOperand &BaseReg = MI.getOperand(Op + X86::AddrBaseReg);
207-
const MCOperand &IndexReg = MI.getOperand(Op + X86::AddrIndexReg);
208-
209-
if ((BaseReg.getReg() != 0 &&
210-
X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg.getReg())) ||
211-
(IndexReg.getReg() != 0 &&
212-
X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg.getReg())))
213-
return true;
214-
return false;
215-
}
216-
#endif
217-
218159
enum GlobalOffsetTableExprKind { GOT_None, GOT_Normal, GOT_SymDiff };
219160

220161
/// Check if this expression starts with _GLOBAL_OFFSET_TABLE_ and if it is
@@ -463,7 +404,7 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op,
463404

464405
// 16-bit addressing forms of the ModR/M byte have a different encoding for
465406
// the R/M field and are far more limited in which registers can be used.
466-
if (is16BitMemOperand(MI, Op, STI)) {
407+
if (X86_MC::is16BitMemOperand(MI, Op, STI)) {
467408
if (BaseReg) {
468409
// For 32-bit addressing, the row and column values in Table 2-2 are
469410
// basically the same. It's AX/CX/DX/BX/SP/BP/SI/DI in that order, with
@@ -672,27 +613,8 @@ bool X86MCCodeEmitter::emitPrefixImpl(unsigned &CurOp, const MCInst &MI,
672613
emitByte(0xF2, OS);
673614

674615
// Emit the address size opcode prefix as needed.
675-
bool NeedAddressOverride;
676-
uint64_t AdSize = TSFlags & X86II::AdSizeMask;
677-
if ((STI.hasFeature(X86::Mode16Bit) && AdSize == X86II::AdSize32) ||
678-
(STI.hasFeature(X86::Mode32Bit) && AdSize == X86II::AdSize16) ||
679-
(STI.hasFeature(X86::Mode64Bit) && AdSize == X86II::AdSize32)) {
680-
NeedAddressOverride = true;
681-
} else if (MemoryOperand < 0) {
682-
NeedAddressOverride = false;
683-
} else if (STI.hasFeature(X86::Mode64Bit)) {
684-
assert(!is16BitMemOperand(MI, MemoryOperand, STI));
685-
NeedAddressOverride = is32BitMemOperand(MI, MemoryOperand);
686-
} else if (STI.hasFeature(X86::Mode32Bit)) {
687-
assert(!is64BitMemOperand(MI, MemoryOperand));
688-
NeedAddressOverride = is16BitMemOperand(MI, MemoryOperand, STI);
689-
} else {
690-
assert(STI.hasFeature(X86::Mode16Bit));
691-
assert(!is64BitMemOperand(MI, MemoryOperand));
692-
NeedAddressOverride = !is16BitMemOperand(MI, MemoryOperand, STI);
693-
}
694-
695-
if (NeedAddressOverride)
616+
if (X86_MC::needsAddressSizeOverride(MI, STI, MemoryOperand, TSFlags) ||
617+
Flags & X86::IP_HAS_AD_SIZE)
696618
emitByte(0x67, OS);
697619

698620
// Encoding type for this instruction.
@@ -708,39 +630,20 @@ bool X86MCCodeEmitter::emitPrefixImpl(unsigned &CurOp, const MCInst &MI,
708630
default:
709631
break;
710632
case X86II::RawFrmDstSrc: {
711-
unsigned siReg = MI.getOperand(1).getReg();
712-
assert(((siReg == X86::SI && MI.getOperand(0).getReg() == X86::DI) ||
713-
(siReg == X86::ESI && MI.getOperand(0).getReg() == X86::EDI) ||
714-
(siReg == X86::RSI && MI.getOperand(0).getReg() == X86::RDI)) &&
715-
"SI and DI register sizes do not match");
716633
// Emit segment override opcode prefix as needed (not for %ds).
717634
if (MI.getOperand(2).getReg() != X86::DS)
718635
emitSegmentOverridePrefix(2, MI, OS);
719-
// Emit AdSize prefix as needed.
720-
if ((!STI.hasFeature(X86::Mode32Bit) && siReg == X86::ESI) ||
721-
(STI.hasFeature(X86::Mode32Bit) && siReg == X86::SI))
722-
emitByte(0x67, OS);
723636
CurOp += 3; // Consume operands.
724637
break;
725638
}
726639
case X86II::RawFrmSrc: {
727-
unsigned siReg = MI.getOperand(0).getReg();
728640
// Emit segment override opcode prefix as needed (not for %ds).
729641
if (MI.getOperand(1).getReg() != X86::DS)
730642
emitSegmentOverridePrefix(1, MI, OS);
731-
// Emit AdSize prefix as needed.
732-
if ((!STI.hasFeature(X86::Mode32Bit) && siReg == X86::ESI) ||
733-
(STI.hasFeature(X86::Mode32Bit) && siReg == X86::SI))
734-
emitByte(0x67, OS);
735643
CurOp += 2; // Consume operands.
736644
break;
737645
}
738646
case X86II::RawFrmDst: {
739-
unsigned siReg = MI.getOperand(0).getReg();
740-
// Emit AdSize prefix as needed.
741-
if ((!STI.hasFeature(X86::Mode32Bit) && siReg == X86::EDI) ||
742-
(STI.hasFeature(X86::Mode32Bit) && siReg == X86::DI))
743-
emitByte(0x67, OS);
744647
++CurOp; // Consume operand.
745648
break;
746649
}

llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,97 @@ bool X86_MC::hasLockPrefix(const MCInst &MI) {
7272
return MI.getFlags() & X86::IP_HAS_LOCK;
7373
}
7474

75+
static bool isMemOperand(const MCInst &MI, unsigned Op, unsigned RegClassID) {
76+
const MCOperand &Base = MI.getOperand(Op + X86::AddrBaseReg);
77+
const MCOperand &Index = MI.getOperand(Op + X86::AddrIndexReg);
78+
const MCRegisterClass &RC = X86MCRegisterClasses[RegClassID];
79+
80+
return (Base.isReg() && Base.getReg() != 0 && RC.contains(Base.getReg())) ||
81+
(Index.isReg() && Index.getReg() != 0 && RC.contains(Index.getReg()));
82+
}
83+
84+
bool X86_MC::is16BitMemOperand(const MCInst &MI, unsigned Op,
85+
const MCSubtargetInfo &STI) {
86+
const MCOperand &Base = MI.getOperand(Op + X86::AddrBaseReg);
87+
const MCOperand &Index = MI.getOperand(Op + X86::AddrIndexReg);
88+
89+
if (STI.hasFeature(X86::Mode16Bit) && Base.isReg() && Base.getReg() == 0 &&
90+
Index.isReg() && Index.getReg() == 0)
91+
return true;
92+
return isMemOperand(MI, Op, X86::GR16RegClassID);
93+
}
94+
95+
bool X86_MC::is32BitMemOperand(const MCInst &MI, unsigned Op) {
96+
const MCOperand &Base = MI.getOperand(Op + X86::AddrBaseReg);
97+
const MCOperand &Index = MI.getOperand(Op + X86::AddrIndexReg);
98+
if (Base.isReg() && Base.getReg() == X86::EIP) {
99+
assert(Index.isReg() && Index.getReg() == 0 && "Invalid eip-based address");
100+
return true;
101+
}
102+
if (Index.isReg() && Index.getReg() == X86::EIZ)
103+
return true;
104+
return isMemOperand(MI, Op, X86::GR32RegClassID);
105+
}
106+
107+
#ifndef NDEBUG
108+
bool X86_MC::is64BitMemOperand(const MCInst &MI, unsigned Op) {
109+
return isMemOperand(MI, Op, X86::GR64RegClassID);
110+
}
111+
#endif
112+
113+
bool X86_MC::needsAddressSizeOverride(const MCInst &MI,
114+
const MCSubtargetInfo &STI,
115+
int MemoryOperand, uint64_t TSFlags) {
116+
uint64_t AdSize = TSFlags & X86II::AdSizeMask;
117+
bool Is16BitMode = STI.hasFeature(X86::Mode16Bit);
118+
bool Is32BitMode = STI.hasFeature(X86::Mode32Bit);
119+
bool Is64BitMode = STI.hasFeature(X86::Mode64Bit);
120+
if ((Is16BitMode && AdSize == X86II::AdSize32) ||
121+
(Is32BitMode && AdSize == X86II::AdSize16) ||
122+
(Is64BitMode && AdSize == X86II::AdSize32))
123+
return true;
124+
uint64_t Form = TSFlags & X86II::FormMask;
125+
switch (Form) {
126+
default:
127+
break;
128+
case X86II::RawFrmDstSrc: {
129+
unsigned siReg = MI.getOperand(1).getReg();
130+
assert(((siReg == X86::SI && MI.getOperand(0).getReg() == X86::DI) ||
131+
(siReg == X86::ESI && MI.getOperand(0).getReg() == X86::EDI) ||
132+
(siReg == X86::RSI && MI.getOperand(0).getReg() == X86::RDI)) &&
133+
"SI and DI register sizes do not match");
134+
return (!Is32BitMode && siReg == X86::ESI) ||
135+
(Is32BitMode && siReg == X86::SI);
136+
}
137+
case X86II::RawFrmSrc: {
138+
unsigned siReg = MI.getOperand(0).getReg();
139+
return (!Is32BitMode && siReg == X86::ESI) ||
140+
(Is32BitMode && siReg == X86::SI);
141+
}
142+
case X86II::RawFrmDst: {
143+
unsigned siReg = MI.getOperand(0).getReg();
144+
return (!Is32BitMode && siReg == X86::EDI) ||
145+
(Is32BitMode && siReg == X86::DI);
146+
}
147+
}
148+
149+
// Determine where the memory operand starts, if present.
150+
if (MemoryOperand < 0)
151+
return false;
152+
153+
if (STI.hasFeature(X86::Mode64Bit)) {
154+
assert(!is16BitMemOperand(MI, MemoryOperand, STI));
155+
return is32BitMemOperand(MI, MemoryOperand);
156+
}
157+
if (STI.hasFeature(X86::Mode32Bit)) {
158+
assert(!is64BitMemOperand(MI, MemoryOperand));
159+
return is16BitMemOperand(MI, MemoryOperand, STI);
160+
}
161+
assert(STI.hasFeature(X86::Mode16Bit));
162+
assert(!is64BitMemOperand(MI, MemoryOperand));
163+
return !is16BitMemOperand(MI, MemoryOperand, STI);
164+
}
165+
75166
void X86_MC::initLLVMToSEHAndCVRegMapping(MCRegisterInfo *MRI) {
76167
// FIXME: TableGen these.
77168
for (unsigned Reg = X86::NoRegister + 1; Reg < X86::NUM_TARGET_REGS; ++Reg) {

llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,28 @@ void initLLVMToSEHAndCVRegMapping(MCRegisterInfo *MRI);
6363
/// Returns true if this instruction has a LOCK prefix.
6464
bool hasLockPrefix(const MCInst &MI);
6565

66+
/// \param Op operand # of the memory operand.
67+
///
68+
/// \returns true if the specified instruction has a 16-bit memory operand.
69+
bool is16BitMemOperand(const MCInst &MI, unsigned Op,
70+
const MCSubtargetInfo &STI);
71+
72+
/// \param Op operand # of the memory operand.
73+
///
74+
/// \returns true if the specified instruction has a 32-bit memory operand.
75+
bool is32BitMemOperand(const MCInst &MI, unsigned Op);
76+
77+
/// \param Op operand # of the memory operand.
78+
///
79+
/// \returns true if the specified instruction has a 64-bit memory operand.
80+
#ifndef NDEBUG
81+
bool is64BitMemOperand(const MCInst &MI, unsigned Op);
82+
#endif
83+
84+
/// Returns true if this instruction needs an Address-Size override prefix.
85+
bool needsAddressSizeOverride(const MCInst &MI, const MCSubtargetInfo &STI,
86+
int MemoryOperand, uint64_t TSFlags);
87+
6688
/// Create a X86 MCSubtargetInfo instance. This is exposed so Asm parser, etc.
6789
/// do not need to go through TargetRegistry.
6890
MCSubtargetInfo *createX86MCSubtargetInfo(const Triple &TT, StringRef CPU,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Check that we don't accidentally strip addr32 prefix
2+
3+
# RUN: llvm-mc -disassemble %s -triple=x86_64 | FileCheck %s
4+
# CHECK: addr32 callq
5+
0x67 0xe8 0x00 0x00 0x00 0x00

llvm/test/MC/X86/code16gcc.s

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
lodsb (%esi), %al
1212
//CHECK: lodsb (%esi), %al # encoding: [0x67,0xac]
1313
lodsl %gs:(%esi)
14-
//CHECK: lodsl %gs:(%esi), %eax # encoding: [0x66,0x65,0x67,0xad]
14+
//CHECK: lodsl %gs:(%esi), %eax # encoding: [0x67,0x66,0x65,0xad]
1515
lods (%esi), %ax
1616
//CHECK: lodsw (%esi), %ax # encoding: [0x67,0xad]
1717
stosw
1818
//CHECK: stosw %ax, %es:(%edi) # encoding: [0x67,0xab]
1919
stos %eax, (%edi)
20-
//CHECK: stosl %eax, %es:(%edi) # encoding: [0x66,0x67,0xab]
20+
//CHECK: stosl %eax, %es:(%edi) # encoding: [0x67,0x66,0xab]
2121
stosb %al, %es:(%edi)
2222
//CHECK: stosb %al, %es:(%edi) # encoding: [0x67,0xaa]
2323
scas %es:(%edi), %al
@@ -29,15 +29,15 @@
2929
cmpsw (%edi), (%esi)
3030
//CHECK: cmpsw %es:(%edi), (%esi) # encoding: [0x67,0xa7]
3131
cmpsl %es:(%edi), %ss:(%esi)
32-
//CHECK: cmpsl %es:(%edi), %ss:(%esi) # encoding: [0x66,0x36,0x67,0xa7]
32+
//CHECK: cmpsl %es:(%edi), %ss:(%esi) # encoding: [0x67,0x66,0x36,0xa7]
3333
movsb (%esi), (%edi)
3434
//CHECK: movsb (%esi), %es:(%edi) # encoding: [0x67,0xa4]
3535
movsl %gs:(%esi), (%edi)
36-
//CHECK: movsl %gs:(%esi), %es:(%edi) # encoding: [0x66,0x65,0x67,0xa5]
36+
//CHECK: movsl %gs:(%esi), %es:(%edi) # encoding: [0x67,0x66,0x65,0xa5]
3737
outsb
3838
//CHECK: outsb (%esi), %dx # encoding: [0x67,0x6e]
3939
outsw %fs:(%esi), %dx
40-
//CHECK: outsw %fs:(%esi), %dx # encoding: [0x64,0x67,0x6f]
40+
//CHECK: outsw %fs:(%esi), %dx # encoding: [0x67,0x64,0x6f]
4141
insw %dx, (%di)
4242
//CHECK: insw %dx, %es:(%di) # encoding: [0x6d]
4343
call $0x7ace,$0x7ace

0 commit comments

Comments
 (0)