mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
Fix branch relaxation in 16-bit mode.
Thread through MCSubtargetInfo to relaxInstruction function allowing relaxation to generate jumps with 16-bit sized immediates in 16-bit mode. This fixes PR22097. Reviewers: dwmw2, tstellarAMD, craig.topper, jyknight Subscribers: jfb, arsenm, jyknight, llvm-commits, dsanders Differential Revision: http://reviews.llvm.org/D20830 llvm-svn: 275068
This commit is contained in:
parent
8da2d8fa34
commit
209a4b5ef4
@ -102,8 +102,10 @@ public:
|
||||
///
|
||||
/// \param Inst The instruction to relax, which may be the same as the
|
||||
/// output.
|
||||
/// \param STI the subtarget information for the associated instruction.
|
||||
/// \param [out] Res On return, the relaxed instruction.
|
||||
virtual void relaxInstruction(const MCInst &Inst, MCInst &Res) const = 0;
|
||||
virtual void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const = 0;
|
||||
|
||||
/// @}
|
||||
|
||||
|
@ -765,7 +765,7 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout,
|
||||
// Relax the fragment.
|
||||
|
||||
MCInst Relaxed;
|
||||
getBackend().relaxInstruction(F.getInst(), Relaxed);
|
||||
getBackend().relaxInstruction(F.getInst(), F.getSubtargetInfo(), Relaxed);
|
||||
|
||||
// Encode the new instruction.
|
||||
//
|
||||
|
@ -252,9 +252,9 @@ void MCObjectStreamer::EmitInstruction(const MCInst &Inst,
|
||||
if (Assembler.getRelaxAll() ||
|
||||
(Assembler.isBundlingEnabled() && Sec->isBundleLocked())) {
|
||||
MCInst Relaxed;
|
||||
getAssembler().getBackend().relaxInstruction(Inst, Relaxed);
|
||||
getAssembler().getBackend().relaxInstruction(Inst, STI, Relaxed);
|
||||
while (getAssembler().getBackend().mayNeedRelaxation(Relaxed))
|
||||
getAssembler().getBackend().relaxInstruction(Relaxed, Relaxed);
|
||||
getAssembler().getBackend().relaxInstruction(Relaxed, STI, Relaxed);
|
||||
EmitInstToData(Relaxed, STI);
|
||||
return;
|
||||
}
|
||||
|
@ -78,7 +78,8 @@ public:
|
||||
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout) const override;
|
||||
void relaxInstruction(const MCInst &Inst, MCInst &Res) const override;
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override;
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
|
||||
|
||||
void HandleAssemblerFlag(MCAssemblerFlag Flag) {}
|
||||
@ -313,6 +314,7 @@ bool AArch64AsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
|
||||
}
|
||||
|
||||
void AArch64AsmBackend::relaxInstruction(const MCInst &Inst,
|
||||
const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const {
|
||||
llvm_unreachable("AArch64AsmBackend::relaxInstruction() unimplemented");
|
||||
}
|
||||
|
@ -53,7 +53,8 @@ public:
|
||||
const MCAsmLayout &Layout) const override {
|
||||
return false;
|
||||
}
|
||||
void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override {
|
||||
assert(!"Not implemented");
|
||||
}
|
||||
bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
|
||||
|
@ -258,7 +258,9 @@ bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
|
||||
return reasonForFixupRelaxation(Fixup, Value);
|
||||
}
|
||||
|
||||
void ARMAsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const {
|
||||
void ARMAsmBackend::relaxInstruction(const MCInst &Inst,
|
||||
const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const {
|
||||
unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode());
|
||||
|
||||
// Sanity check w/ diagnostic if we get here w/ a bogus instruction.
|
||||
|
@ -63,7 +63,8 @@ public:
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout) const override;
|
||||
|
||||
void relaxInstruction(const MCInst &Inst, MCInst &Res) const override;
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override;
|
||||
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
|
||||
|
||||
|
@ -47,7 +47,8 @@ public:
|
||||
|
||||
bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
|
||||
|
||||
void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {}
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override {}
|
||||
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
|
||||
};
|
||||
|
@ -634,8 +634,8 @@ public:
|
||||
llvm_unreachable("Handled by fixupNeedsRelaxationAdvanced");
|
||||
}
|
||||
|
||||
void relaxInstruction(MCInst const & Inst,
|
||||
MCInst & Res) const override {
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override {
|
||||
assert(HexagonMCInstrInfo::isBundle(Inst) &&
|
||||
"Hexagon relaxInstruction only works on bundles");
|
||||
|
||||
|
@ -69,7 +69,8 @@ public:
|
||||
|
||||
bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
|
||||
|
||||
void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {}
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override {}
|
||||
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
|
||||
};
|
||||
|
@ -75,7 +75,8 @@ public:
|
||||
/// \param Inst - The instruction to relax, which may be the same
|
||||
/// as the output.
|
||||
/// \param [out] Res On return, the relaxed instruction.
|
||||
void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {}
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override {}
|
||||
|
||||
/// @}
|
||||
|
||||
|
@ -168,8 +168,8 @@ public:
|
||||
llvm_unreachable("relaxInstruction() unimplemented");
|
||||
}
|
||||
|
||||
|
||||
void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override {
|
||||
// FIXME.
|
||||
llvm_unreachable("relaxInstruction() unimplemented");
|
||||
}
|
||||
|
@ -248,7 +248,8 @@ namespace {
|
||||
llvm_unreachable("fixupNeedsRelaxation() unimplemented");
|
||||
return false;
|
||||
}
|
||||
void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override {
|
||||
// FIXME.
|
||||
llvm_unreachable("relaxInstruction() unimplemented");
|
||||
}
|
||||
|
@ -58,7 +58,8 @@ public:
|
||||
const MCAsmLayout &Layout) const override {
|
||||
return false;
|
||||
}
|
||||
void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override {
|
||||
llvm_unreachable("SystemZ does do not have assembler relaxation");
|
||||
}
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
|
||||
|
@ -55,7 +55,8 @@ public:
|
||||
|
||||
bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
|
||||
|
||||
void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {}
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override {}
|
||||
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
|
||||
};
|
||||
|
@ -131,38 +131,57 @@ public:
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout) const override;
|
||||
|
||||
void relaxInstruction(const MCInst &Inst, MCInst &Res) const override;
|
||||
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const override;
|
||||
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
static unsigned getRelaxedOpcodeBranch(unsigned Op) {
|
||||
static unsigned getRelaxedOpcodeBranch(const MCInst &Inst, bool is16BitMode) {
|
||||
unsigned Op = Inst.getOpcode();
|
||||
switch (Op) {
|
||||
default:
|
||||
return Op;
|
||||
|
||||
case X86::JAE_1: return X86::JAE_4;
|
||||
case X86::JA_1: return X86::JA_4;
|
||||
case X86::JBE_1: return X86::JBE_4;
|
||||
case X86::JB_1: return X86::JB_4;
|
||||
case X86::JE_1: return X86::JE_4;
|
||||
case X86::JGE_1: return X86::JGE_4;
|
||||
case X86::JG_1: return X86::JG_4;
|
||||
case X86::JLE_1: return X86::JLE_4;
|
||||
case X86::JL_1: return X86::JL_4;
|
||||
case X86::JMP_1: return X86::JMP_4;
|
||||
case X86::JNE_1: return X86::JNE_4;
|
||||
case X86::JNO_1: return X86::JNO_4;
|
||||
case X86::JNP_1: return X86::JNP_4;
|
||||
case X86::JNS_1: return X86::JNS_4;
|
||||
case X86::JO_1: return X86::JO_4;
|
||||
case X86::JP_1: return X86::JP_4;
|
||||
case X86::JS_1: return X86::JS_4;
|
||||
case X86::JAE_1:
|
||||
return (is16BitMode) ? X86::JAE_2 : X86::JAE_4;
|
||||
case X86::JA_1:
|
||||
return (is16BitMode) ? X86::JA_2 : X86::JA_4;
|
||||
case X86::JBE_1:
|
||||
return (is16BitMode) ? X86::JBE_2 : X86::JBE_4;
|
||||
case X86::JB_1:
|
||||
return (is16BitMode) ? X86::JB_2 : X86::JB_4;
|
||||
case X86::JE_1:
|
||||
return (is16BitMode) ? X86::JE_2 : X86::JE_4;
|
||||
case X86::JGE_1:
|
||||
return (is16BitMode) ? X86::JGE_2 : X86::JGE_4;
|
||||
case X86::JG_1:
|
||||
return (is16BitMode) ? X86::JG_2 : X86::JG_4;
|
||||
case X86::JLE_1:
|
||||
return (is16BitMode) ? X86::JLE_2 : X86::JLE_4;
|
||||
case X86::JL_1:
|
||||
return (is16BitMode) ? X86::JL_2 : X86::JL_4;
|
||||
case X86::JMP_1:
|
||||
return (is16BitMode) ? X86::JMP_2 : X86::JMP_4;
|
||||
case X86::JNE_1:
|
||||
return (is16BitMode) ? X86::JNE_2 : X86::JNE_4;
|
||||
case X86::JNO_1:
|
||||
return (is16BitMode) ? X86::JNO_2 : X86::JNO_4;
|
||||
case X86::JNP_1:
|
||||
return (is16BitMode) ? X86::JNP_2 : X86::JNP_4;
|
||||
case X86::JNS_1:
|
||||
return (is16BitMode) ? X86::JNS_2 : X86::JNS_4;
|
||||
case X86::JO_1:
|
||||
return (is16BitMode) ? X86::JO_2 : X86::JO_4;
|
||||
case X86::JP_1:
|
||||
return (is16BitMode) ? X86::JP_2 : X86::JP_4;
|
||||
case X86::JS_1:
|
||||
return (is16BitMode) ? X86::JS_2 : X86::JS_4;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned getRelaxedOpcodeArith(unsigned Op) {
|
||||
static unsigned getRelaxedOpcodeArith(const MCInst &Inst) {
|
||||
unsigned Op = Inst.getOpcode();
|
||||
switch (Op) {
|
||||
default:
|
||||
return Op;
|
||||
@ -246,20 +265,20 @@ static unsigned getRelaxedOpcodeArith(unsigned Op) {
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned getRelaxedOpcode(unsigned Op) {
|
||||
unsigned R = getRelaxedOpcodeArith(Op);
|
||||
if (R != Op)
|
||||
static unsigned getRelaxedOpcode(const MCInst &Inst, bool is16BitMode) {
|
||||
unsigned R = getRelaxedOpcodeArith(Inst);
|
||||
if (R != Inst.getOpcode())
|
||||
return R;
|
||||
return getRelaxedOpcodeBranch(Op);
|
||||
return getRelaxedOpcodeBranch(Inst, is16BitMode);
|
||||
}
|
||||
|
||||
bool X86AsmBackend::mayNeedRelaxation(const MCInst &Inst) const {
|
||||
// Branches can always be relaxed.
|
||||
if (getRelaxedOpcodeBranch(Inst.getOpcode()) != Inst.getOpcode())
|
||||
// Branches can always be relaxed in either mode.
|
||||
if (getRelaxedOpcodeBranch(Inst, false) != Inst.getOpcode())
|
||||
return true;
|
||||
|
||||
// Check if this instruction is ever relaxable.
|
||||
if (getRelaxedOpcodeArith(Inst.getOpcode()) == Inst.getOpcode())
|
||||
if (getRelaxedOpcodeArith(Inst) == Inst.getOpcode())
|
||||
return false;
|
||||
|
||||
|
||||
@ -282,9 +301,12 @@ bool X86AsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
|
||||
|
||||
// FIXME: Can tblgen help at all here to verify there aren't other instructions
|
||||
// we can relax?
|
||||
void X86AsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const {
|
||||
void X86AsmBackend::relaxInstruction(const MCInst &Inst,
|
||||
const MCSubtargetInfo &STI,
|
||||
MCInst &Res) const {
|
||||
// The only relaxations X86 does is from a 1byte pcrel to a 4byte pcrel.
|
||||
unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode());
|
||||
bool is16BitMode = STI.getFeatureBits()[X86::Mode16Bit];
|
||||
unsigned RelaxedOp = getRelaxedOpcode(Inst, is16BitMode);
|
||||
|
||||
if (RelaxedOp == Inst.getOpcode()) {
|
||||
SmallString<256> Tmp;
|
||||
|
31
test/MC/X86/x86-branch-relaxation.s
Normal file
31
test/MC/X86/x86-branch-relaxation.s
Normal file
@ -0,0 +1,31 @@
|
||||
# RUN: llvm-mc -filetype=obj -triple=i386-unknown-unknown %s -o %t
|
||||
# RUN: llvm-objdump -r -D -section .text.bar -triple i386-unknown-unknown-code16 %t | FileCheck --check-prefix=CHECK16 %s
|
||||
# RUN: llvm-objdump -r -D -section .text.baz -triple i386-unknown-unknown %t | FileCheck --check-prefix=CHECK32 %s
|
||||
.text
|
||||
.section .text.foo,"",@progbits
|
||||
|
||||
.code16
|
||||
.globl foo
|
||||
foo:
|
||||
nop
|
||||
|
||||
.section .text.bar,"",@progbits
|
||||
.globl bar16
|
||||
bar16:
|
||||
jmp foo
|
||||
|
||||
.section .text.baz,"",@progbits
|
||||
.code32
|
||||
.globl baz32
|
||||
baz32:
|
||||
jmp foo
|
||||
|
||||
|
||||
|
||||
|
||||
// CHECK16-LABEL: bar16
|
||||
// CHECK16-NEXT: e9 fe ff jmp -2 <bar16+0x1>
|
||||
// CHECK32-LABEL: baz32
|
||||
// CHECK32-NEXT: e9 fc ff ff ff jmp -4 <baz32+0x1>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user