mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-13 22:24:07 +00:00
MC: Add TargetAsmBackend::WriteNopData and use to eliminate some target dependencies in MCMachOStreamer and MCAssembler.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@99248 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -102,6 +102,13 @@ public:
|
|||||||
/// wider instruction.
|
/// wider instruction.
|
||||||
virtual void RelaxInstruction(const MCInstFragment *IF,
|
virtual void RelaxInstruction(const MCInstFragment *IF,
|
||||||
MCInst &Res) const = 0;
|
MCInst &Res) const = 0;
|
||||||
|
|
||||||
|
/// WriteNopData - Write an (optimal) nop sequence of Count bytes to the given
|
||||||
|
/// output. If the target cannot generate such a sequence, it should return an
|
||||||
|
/// error.
|
||||||
|
///
|
||||||
|
/// \return - True on success.
|
||||||
|
virtual bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
@ -373,66 +373,9 @@ void MCAssembler::LayoutSection(MCSectionData &SD,
|
|||||||
SD.setFileSize(Address - SD.getAddress());
|
SD.setFileSize(Address - SD.getAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// WriteNopData - Write optimal nops to the output file for the \arg Count
|
|
||||||
/// bytes. This returns the number of bytes written. It may return 0 if
|
|
||||||
/// the \arg Count is more than the maximum optimal nops.
|
|
||||||
///
|
|
||||||
/// FIXME this is X86 32-bit specific and should move to a better place.
|
|
||||||
static uint64_t WriteNopData(uint64_t Count, MCObjectWriter *OW) {
|
|
||||||
static const uint8_t Nops[16][16] = {
|
|
||||||
// nop
|
|
||||||
{0x90},
|
|
||||||
// xchg %ax,%ax
|
|
||||||
{0x66, 0x90},
|
|
||||||
// nopl (%[re]ax)
|
|
||||||
{0x0f, 0x1f, 0x00},
|
|
||||||
// nopl 0(%[re]ax)
|
|
||||||
{0x0f, 0x1f, 0x40, 0x00},
|
|
||||||
// nopl 0(%[re]ax,%[re]ax,1)
|
|
||||||
{0x0f, 0x1f, 0x44, 0x00, 0x00},
|
|
||||||
// nopw 0(%[re]ax,%[re]ax,1)
|
|
||||||
{0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00},
|
|
||||||
// nopl 0L(%[re]ax)
|
|
||||||
{0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
// nopl 0L(%[re]ax,%[re]ax,1)
|
|
||||||
{0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
// nopw 0L(%[re]ax,%[re]ax,1)
|
|
||||||
{0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
// nopw %cs:0L(%[re]ax,%[re]ax,1)
|
|
||||||
{0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
// nopl 0(%[re]ax,%[re]ax,1)
|
|
||||||
// nopw 0(%[re]ax,%[re]ax,1)
|
|
||||||
{0x0f, 0x1f, 0x44, 0x00, 0x00,
|
|
||||||
0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00},
|
|
||||||
// nopw 0(%[re]ax,%[re]ax,1)
|
|
||||||
// nopw 0(%[re]ax,%[re]ax,1)
|
|
||||||
{0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00,
|
|
||||||
0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00},
|
|
||||||
// nopw 0(%[re]ax,%[re]ax,1)
|
|
||||||
// nopl 0L(%[re]ax) */
|
|
||||||
{0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00,
|
|
||||||
0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
// nopl 0L(%[re]ax)
|
|
||||||
// nopl 0L(%[re]ax)
|
|
||||||
{0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
// nopl 0L(%[re]ax)
|
|
||||||
// nopl 0L(%[re]ax,%[re]ax,1)
|
|
||||||
{0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (Count > 15)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (uint64_t i = 0; i < Count; i++)
|
|
||||||
OW->Write8(uint8_t(Nops[Count - 1][i]));
|
|
||||||
|
|
||||||
return Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// WriteFragmentData - Write the \arg F data to the output file.
|
/// WriteFragmentData - Write the \arg F data to the output file.
|
||||||
static void WriteFragmentData(const MCFragment &F, MCObjectWriter *OW) {
|
static void WriteFragmentData(const MCAssembler &Asm, const MCFragment &F,
|
||||||
|
MCObjectWriter *OW) {
|
||||||
uint64_t Start = OW->getStream().tell();
|
uint64_t Start = OW->getStream().tell();
|
||||||
(void) Start;
|
(void) Start;
|
||||||
|
|
||||||
@ -456,11 +399,15 @@ static void WriteFragmentData(const MCFragment &F, MCObjectWriter *OW) {
|
|||||||
// See if we are aligning with nops, and if so do that first to try to fill
|
// See if we are aligning with nops, and if so do that first to try to fill
|
||||||
// the Count bytes. Then if that did not fill any bytes or there are any
|
// the Count bytes. Then if that did not fill any bytes or there are any
|
||||||
// bytes left to fill use the the Value and ValueSize to fill the rest.
|
// bytes left to fill use the the Value and ValueSize to fill the rest.
|
||||||
|
// If we are aligning with nops, ask that target to emit the right data.
|
||||||
if (AF.getEmitNops()) {
|
if (AF.getEmitNops()) {
|
||||||
uint64_t NopByteCount = WriteNopData(Count, OW);
|
if (!Asm.getBackend().WriteNopData(Count, OW))
|
||||||
Count -= NopByteCount;
|
llvm_report_error("unable to write nop sequence of " +
|
||||||
|
Twine(Count) + " bytes");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Otherwise, write out in multiples of the value size.
|
||||||
for (uint64_t i = 0; i != Count; ++i) {
|
for (uint64_t i = 0; i != Count; ++i) {
|
||||||
switch (AF.getValueSize()) {
|
switch (AF.getValueSize()) {
|
||||||
default:
|
default:
|
||||||
@ -531,7 +478,7 @@ void MCAssembler::WriteSectionData(const MCSectionData *SD,
|
|||||||
|
|
||||||
for (MCSectionData::const_iterator it = SD->begin(),
|
for (MCSectionData::const_iterator it = SD->begin(),
|
||||||
ie = SD->end(); it != ie; ++it)
|
ie = SD->end(); it != ie; ++it)
|
||||||
WriteFragmentData(*it, OW);
|
WriteFragmentData(*this, *it, OW);
|
||||||
|
|
||||||
// Add section padding.
|
// Add section padding.
|
||||||
assert(SD->getFileSize() >= SD->getSize() && "Invalid section sizes!");
|
assert(SD->getFileSize() >= SD->getSize() && "Invalid section sizes!");
|
||||||
|
@ -353,8 +353,7 @@ void MCMachOStreamer::EmitCodeAlignment(unsigned ByteAlignment,
|
|||||||
unsigned MaxBytesToEmit) {
|
unsigned MaxBytesToEmit) {
|
||||||
if (MaxBytesToEmit == 0)
|
if (MaxBytesToEmit == 0)
|
||||||
MaxBytesToEmit = ByteAlignment;
|
MaxBytesToEmit = ByteAlignment;
|
||||||
// FIXME: The 0x90 is the default x86 1 byte nop opcode.
|
new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit,
|
||||||
new MCAlignFragment(ByteAlignment, 0x90, 1, MaxBytesToEmit,
|
|
||||||
true /* EmitNops */, CurSectionData);
|
true /* EmitNops */, CurSectionData);
|
||||||
|
|
||||||
// Update the maximum alignment on the current section if necessary.
|
// Update the maximum alignment on the current section if necessary.
|
||||||
|
@ -53,6 +53,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RelaxInstruction(const MCInstFragment *IF, MCInst &Res) const;
|
void RelaxInstruction(const MCInstFragment *IF, MCInst &Res) const;
|
||||||
|
|
||||||
|
bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned getRelaxedOpcode(unsigned Op) {
|
static unsigned getRelaxedOpcode(unsigned Op) {
|
||||||
@ -98,6 +100,67 @@ void X86AsmBackend::RelaxInstruction(const MCInstFragment *IF,
|
|||||||
Res.setOpcode(RelaxedOp);
|
Res.setOpcode(RelaxedOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// WriteNopData - Write optimal nops to the output file for the \arg Count
|
||||||
|
/// bytes. This returns the number of bytes written. It may return 0 if
|
||||||
|
/// the \arg Count is more than the maximum optimal nops.
|
||||||
|
///
|
||||||
|
/// FIXME this is X86 32-bit specific and should move to a better place.
|
||||||
|
bool X86AsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const {
|
||||||
|
static const uint8_t Nops[16][16] = {
|
||||||
|
// nop
|
||||||
|
{0x90},
|
||||||
|
// xchg %ax,%ax
|
||||||
|
{0x66, 0x90},
|
||||||
|
// nopl (%[re]ax)
|
||||||
|
{0x0f, 0x1f, 0x00},
|
||||||
|
// nopl 0(%[re]ax)
|
||||||
|
{0x0f, 0x1f, 0x40, 0x00},
|
||||||
|
// nopl 0(%[re]ax,%[re]ax,1)
|
||||||
|
{0x0f, 0x1f, 0x44, 0x00, 0x00},
|
||||||
|
// nopw 0(%[re]ax,%[re]ax,1)
|
||||||
|
{0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00},
|
||||||
|
// nopl 0L(%[re]ax)
|
||||||
|
{0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
// nopl 0L(%[re]ax,%[re]ax,1)
|
||||||
|
{0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
// nopw 0L(%[re]ax,%[re]ax,1)
|
||||||
|
{0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
// nopw %cs:0L(%[re]ax,%[re]ax,1)
|
||||||
|
{0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
// nopl 0(%[re]ax,%[re]ax,1)
|
||||||
|
// nopw 0(%[re]ax,%[re]ax,1)
|
||||||
|
{0x0f, 0x1f, 0x44, 0x00, 0x00,
|
||||||
|
0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00},
|
||||||
|
// nopw 0(%[re]ax,%[re]ax,1)
|
||||||
|
// nopw 0(%[re]ax,%[re]ax,1)
|
||||||
|
{0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00,
|
||||||
|
0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00},
|
||||||
|
// nopw 0(%[re]ax,%[re]ax,1)
|
||||||
|
// nopl 0L(%[re]ax) */
|
||||||
|
{0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00,
|
||||||
|
0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
// nopl 0L(%[re]ax)
|
||||||
|
// nopl 0L(%[re]ax)
|
||||||
|
{0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00},
|
||||||
|
// nopl 0L(%[re]ax)
|
||||||
|
// nopl 0L(%[re]ax,%[re]ax,1)
|
||||||
|
{0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write an optimal sequence for the first 15 bytes.
|
||||||
|
uint64_t OptimalCount = (Count < 16) ? Count : 15;
|
||||||
|
for (uint64_t i = 0, e = OptimalCount; i != e; i++)
|
||||||
|
OW->Write8(Nops[OptimalCount - 1][i]);
|
||||||
|
|
||||||
|
// Finish with single byte nops.
|
||||||
|
for (uint64_t i = OptimalCount, e = Count; i != e; ++i)
|
||||||
|
OW->Write8(0x90);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* *** */
|
/* *** */
|
||||||
|
|
||||||
class ELFX86AsmBackend : public X86AsmBackend {
|
class ELFX86AsmBackend : public X86AsmBackend {
|
||||||
|
Reference in New Issue
Block a user