//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mccodeemitter"
#include "MCTargetDesc/PPCMCTargetDesc.h"
#include "MCTargetDesc/PPCFixupKinds.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Target/TargetOpcodes.h"
using namespace llvm;
+#define DEBUG_TYPE "mccodeemitter"
+
STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
namespace {
const MCInstrInfo &MCII;
const MCContext &CTX;
+ bool IsLittleEndian;
public:
- PPCMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
- : MCII(mcii), CTX(ctx) {
+ PPCMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx, bool isLittle)
+ : MCII(mcii), CTX(ctx), IsLittleEndian(isLittle) {
}
~PPCMCCodeEmitter() {}
const MCSubtargetInfo &STI) const;
void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
+ const MCSubtargetInfo &STI) const override {
// For fast-isel, a float COPY_TO_REGCLASS can survive this long.
// It's just a nop to keep the register classes happy, so don't
// generate anything.
uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
- // Output the constant in big endian byte order.
+ // Output the constant in big/little endian byte order.
unsigned Size = Desc.getSize();
- int ShiftValue = (Size * 8) - 8;
- for (unsigned i = 0; i != Size; ++i) {
- OS << (char)(Bits >> ShiftValue);
- Bits <<= 8;
+ switch (Size) {
+ case 4:
+ if (IsLittleEndian) {
+ OS << (char)(Bits);
+ OS << (char)(Bits >> 8);
+ OS << (char)(Bits >> 16);
+ OS << (char)(Bits >> 24);
+ } else {
+ OS << (char)(Bits >> 24);
+ OS << (char)(Bits >> 16);
+ OS << (char)(Bits >> 8);
+ OS << (char)(Bits);
+ }
+ break;
+ case 8:
+ // If we emit a pair of instructions, the first one is
+ // always in the top 32 bits, even on little-endian.
+ if (IsLittleEndian) {
+ OS << (char)(Bits >> 32);
+ OS << (char)(Bits >> 40);
+ OS << (char)(Bits >> 48);
+ OS << (char)(Bits >> 56);
+ OS << (char)(Bits);
+ OS << (char)(Bits >> 8);
+ OS << (char)(Bits >> 16);
+ OS << (char)(Bits >> 24);
+ } else {
+ OS << (char)(Bits >> 56);
+ OS << (char)(Bits >> 48);
+ OS << (char)(Bits >> 40);
+ OS << (char)(Bits >> 32);
+ OS << (char)(Bits >> 24);
+ OS << (char)(Bits >> 16);
+ OS << (char)(Bits >> 8);
+ OS << (char)(Bits);
+ }
+ break;
+ default:
+ llvm_unreachable ("Invalid instruction size");
}
++MCNumEmitted; // Keep track of the # of mi's emitted.
const MCRegisterInfo &MRI,
const MCSubtargetInfo &STI,
MCContext &Ctx) {
- return new PPCMCCodeEmitter(MCII, Ctx);
+ Triple TT(STI.getTargetTriple());
+ bool IsLittleEndian = TT.getArch() == Triple::ppc64le;
+ return new PPCMCCodeEmitter(MCII, Ctx, IsLittleEndian);
}
unsigned PPCMCCodeEmitter::
if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
// Add a fixup for the immediate field.
- Fixups.push_back(MCFixup::Create(2, MO.getExpr(),
+ Fixups.push_back(MCFixup::Create(IsLittleEndian? 0 : 2, MO.getExpr(),
(MCFixupKind)PPC::fixup_ppc_half16));
return 0;
}
return (getMachineOpValue(MI, MO, Fixups, STI) & 0xFFFF) | RegBits;
// Add a fixup for the displacement field.
- Fixups.push_back(MCFixup::Create(2, MO.getExpr(),
+ Fixups.push_back(MCFixup::Create(IsLittleEndian? 0 : 2, MO.getExpr(),
(MCFixupKind)PPC::fixup_ppc_half16));
return RegBits;
}
return ((getMachineOpValue(MI, MO, Fixups, STI) >> 2) & 0x3FFF) | RegBits;
// Add a fixup for the displacement field.
- Fixups.push_back(MCFixup::Create(2, MO.getExpr(),
+ Fixups.push_back(MCFixup::Create(IsLittleEndian? 0 : 2, MO.getExpr(),
(MCFixupKind)PPC::fixup_ppc_half16ds));
return RegBits;
}