fix X86 encoder to output [disp] only addresses with no SIB byte

in X86-32 mode.  This is still required in x86-64 mode to avoid
forming [disp+rip] encoding.  Rewrite the SIB byte decision logic
to be actually understandable.

llvm-svn: 95693
This commit is contained in:
Chris Lattner 2010-02-09 21:47:19 +00:00
parent 02f2a0c279
commit 0c3b66cd87
2 changed files with 89 additions and 74 deletions

View File

@ -387,31 +387,44 @@ void Emitter<CodeEmitter>::emitMemModRMByte(const MachineInstr &MI,
// If no BaseReg, issue a RIP relative instruction only if the MCE can
// resolve addresses on-the-fly, otherwise use SIB (Intel Manual 2A, table
// 2-7) and absolute references.
if ((!Is64BitMode || DispForReloc || BaseReg != 0) &&
if (// The SIB byte must be used if there is an index register.
IndexReg.getReg() == 0 &&
((BaseReg == 0 && MCE.earlyResolveAddresses()) || BaseReg == X86::RIP ||
(BaseReg != 0 && getX86RegNum(BaseReg) != N86::ESP))) {
if (BaseReg == 0 || BaseReg == X86::RIP) { // Just a displacement?
// Emit special case [disp32] encoding
// The SIB byte must be used if the base is ESP/RSP.
BaseReg != X86::ESP && BaseReg != X86::RSP &&
// If there is no base register and we're in 64-bit mode, we need a SIB
// byte to emit an addr that is just 'disp32' (the non-RIP relative form).
(!Is64BitMode || BaseReg != 0)) {
if (BaseReg == 0 || // [disp32] in X86-32 mode
BaseReg == X86::RIP) { // [disp32+RIP] in X86-64 mode
MCE.emitByte(ModRMByte(0, RegOpcodeField, 5));
emitDisplacementField(DispForReloc, DispVal, PCAdj, true);
} else {
unsigned BaseRegNo = getX86RegNum(BaseReg);
if (!DispForReloc && DispVal == 0 && BaseRegNo != N86::EBP) {
// Emit simple indirect register encoding... [EAX] f.e.
MCE.emitByte(ModRMByte(0, RegOpcodeField, BaseRegNo));
} else if (!DispForReloc && isDisp8(DispVal)) {
// Emit the disp8 encoding... [REG+disp8]
MCE.emitByte(ModRMByte(1, RegOpcodeField, BaseRegNo));
emitConstant(DispVal, 1);
} else {
// Emit the most general non-SIB encoding: [REG+disp32]
MCE.emitByte(ModRMByte(2, RegOpcodeField, BaseRegNo));
emitDisplacementField(DispForReloc, DispVal, PCAdj, IsPCRel);
}
return;
}
} else { // We need a SIB byte, so start by outputting the ModR/M byte first
unsigned BaseRegNo = getX86RegNum(BaseReg);
// If the base is not EBP/ESP and there is no displacement, use simple
// indirect register encoding, this handles addresses like [EAX]. The
// encoding for [EBP] with no displacement means [disp32] so we handle it
// by emitting a displacement of 0 below.
if (!DispForReloc && DispVal == 0 && BaseRegNo != N86::EBP) {
MCE.emitByte(ModRMByte(0, RegOpcodeField, BaseRegNo));
return;
}
// Otherwise, if the displacement fits in a byte, encode as [REG+disp8].
if (!DispForReloc && isDisp8(DispVal)) {
MCE.emitByte(ModRMByte(1, RegOpcodeField, BaseRegNo));
emitConstant(DispVal, 1);
return;
}
// Otherwise, emit the most general non-SIB encoding: [REG+disp32]
MCE.emitByte(ModRMByte(2, RegOpcodeField, BaseRegNo));
emitDisplacementField(DispForReloc, DispVal, PCAdj, IsPCRel);
return;
}
// Otherwise we need a SIB byte, so start by outputting the ModR/M byte first.
assert(IndexReg.getReg() != X86::ESP &&
IndexReg.getReg() != X86::RSP && "Cannot use ESP as index reg!");
@ -419,7 +432,7 @@ void Emitter<CodeEmitter>::emitMemModRMByte(const MachineInstr &MI,
bool ForceDisp8 = false;
if (BaseReg == 0) {
// If there is no base register, we emit the special case SIB byte with
// MOD=0, BASE=5, to JUST get the index, scale, and displacement.
// MOD=0, BASE=4, to JUST get the index, scale, and displacement.
MCE.emitByte(ModRMByte(0, RegOpcodeField, 4));
ForceDisp32 = true;
} else if (DispForReloc) {
@ -468,7 +481,6 @@ void Emitter<CodeEmitter>::emitMemModRMByte(const MachineInstr &MI,
emitDisplacementField(DispForReloc, DispVal, PCAdj, IsPCRel);
}
}
}
template<class CodeEmitter>
void Emitter<CodeEmitter>::emitInstruction(const MachineInstr &MI,

View File

@ -4,5 +4,8 @@ fisttpl 3735928559(%ebx,%ecx,8)
# CHECK: encoding: [0xdb,0x8c,0xcb,0xef,0xbe,0xad,0xde]
sbbb $0xfe,0xdeadbeef(%ebx,%ecx,8)
# CHECK: encoding: [0x80,0x9c,0xcb,0xef,0xbe,0xad,0xde,0xfe]
psllw 69, %mm3
# CHECK: encoding: [0x0f,0xf1,0x1d,0x45,0x00,0x00,0x00]