Difference between revisions of "NaplesPUMCCodeEmitter.cpp"

From NaplesPU Documentation
Jump to: navigation, search
 
Line 1: Line 1:
NuPlusMCCodeEmitter class transforms MCInst objects into binary code representation.
+
NaplesPUMCCodeEmitter class transforms MCInst objects into binary code representation.
  
 
<syntaxhighlight>
 
<syntaxhighlight>
//===-- NuPlusMCCodeEmitter.cpp - Convert NuPlus code to machine code -------===//
+
//===-- NaplesPUMCCodeEmitter.cpp - Convert NaplesPU code to machine code -------===//
 
//
 
//
 
//                    The LLVM Compiler Infrastructure
 
//                    The LLVM Compiler Infrastructure
Line 11: Line 11:
 
//===----------------------------------------------------------------------===//
 
//===----------------------------------------------------------------------===//
 
//
 
//
// This file implements the NuPlusMCCodeEmitter class.
+
// This file implements the NaplesPUMCCodeEmitter class.
 
//
 
//
 
//===----------------------------------------------------------------------===//
 
//===----------------------------------------------------------------------===//
  
#include "MCTargetDesc/NuPlusFixupKinds.h"
+
#include "MCTargetDesc/NaplesPUFixupKinds.h"
#include "MCTargetDesc/NuPlusMCTargetDesc.h"
+
#include "MCTargetDesc/NaplesPUMCTargetDesc.h"
 
#include "llvm/ADT/Statistic.h"
 
#include "llvm/ADT/Statistic.h"
 
#include "llvm/MC/MCCodeEmitter.h"
 
#include "llvm/MC/MCCodeEmitter.h"
Line 37: Line 37:
  
 
namespace {
 
namespace {
class NuPlusMCCodeEmitter : public MCCodeEmitter {
+
class NaplesPUMCCodeEmitter : public MCCodeEmitter {
   NuPlusMCCodeEmitter(const NuPlusMCCodeEmitter &) = delete;
+
   NaplesPUMCCodeEmitter(const NaplesPUMCCodeEmitter &) = delete;
   void operator=(const NuPlusMCCodeEmitter &) = delete;
+
   void operator=(const NaplesPUMCCodeEmitter &) = delete;
 
   MCContext &Ctx;
 
   MCContext &Ctx;
  
 
public:
 
public:
   NuPlusMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx): Ctx(ctx) {}
+
   NaplesPUMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx): Ctx(ctx) {}
  
 
   // getBinaryCodeForInstr - TableGen'erated function for getting the
 
   // getBinaryCodeForInstr - TableGen'erated function for getting the
Line 96: Line 96:
 
} // end anonymous namespace
 
} // end anonymous namespace
  
MCCodeEmitter *llvm::createNuPlusMCCodeEmitter(const MCInstrInfo &MCII,
+
MCCodeEmitter *llvm::createNaplesPUMCCodeEmitter(const MCInstrInfo &MCII,
 
                                               const MCRegisterInfo &MRI,
 
                                               const MCRegisterInfo &MRI,
 
                                               MCContext &Ctx) {
 
                                               MCContext &Ctx) {
   return new NuPlusMCCodeEmitter(MCII, Ctx);
+
   return new NaplesPUMCCodeEmitter(MCII, Ctx);
 
}
 
}
  
 
// Return binary encoding of operand.
 
// Return binary encoding of operand.
unsigned NuPlusMCCodeEmitter::
+
unsigned NaplesPUMCCodeEmitter::
 
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
 
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
 
                   SmallVectorImpl<MCFixup> &Fixups,
 
                   SmallVectorImpl<MCFixup> &Fixups,
Line 117: Line 117:
 
}
 
}
  
void NuPlusMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
+
void NaplesPUMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
 
                                           SmallVectorImpl<MCFixup> &Fixups,
 
                                           SmallVectorImpl<MCFixup> &Fixups,
 
                                           const MCSubtargetInfo &STI) const {
 
                                           const MCSubtargetInfo &STI) const {
Line 126: Line 126:
 
}
 
}
  
unsigned NuPlusMCCodeEmitter::encodeABShValue(const MCInst &MI, unsigned Op,
+
unsigned NaplesPUMCCodeEmitter::encodeABShValue(const MCInst &MI, unsigned Op,
 
                                             SmallVectorImpl<MCFixup> &Fixups,
 
                                             SmallVectorImpl<MCFixup> &Fixups,
 
                                             const MCSubtargetInfo &STI) const {
 
                                             const MCSubtargetInfo &STI) const {
Line 137: Line 137:
 
     Fixups.push_back(MCFixup::create(
 
     Fixups.push_back(MCFixup::create(
 
         0, MI.getOperand(1).getExpr(),
 
         0, MI.getOperand(1).getExpr(),
         MCFixupKind(NuPlus::fixup_NuPlus_Absh)));
+
         MCFixupKind(NaplesPU::fixup_NaplesPU_Absh)));
 
   } else if ( MI.getOperand(2).isExpr()) {
 
   } else if ( MI.getOperand(2).isExpr()) {
 
     Fixups.push_back(MCFixup::create(
 
     Fixups.push_back(MCFixup::create(
 
         0,  MI.getOperand(2).getExpr(),
 
         0,  MI.getOperand(2).getExpr(),
         MCFixupKind(NuPlus::fixup_NuPlus_Absh)));
+
         MCFixupKind(NaplesPU::fixup_NaplesPU_Absh)));
 
   }
 
   }
  
Line 147: Line 147:
 
}
 
}
  
unsigned NuPlusMCCodeEmitter::encodeABSlValue(const MCInst &MI, unsigned Op,
+
unsigned NaplesPUMCCodeEmitter::encodeABSlValue(const MCInst &MI, unsigned Op,
 
                                             SmallVectorImpl<MCFixup> &Fixups,
 
                                             SmallVectorImpl<MCFixup> &Fixups,
 
                                             const MCSubtargetInfo &STI) const {
 
                                             const MCSubtargetInfo &STI) const {
Line 158: Line 158:
 
     Fixups.push_back(MCFixup::create(
 
     Fixups.push_back(MCFixup::create(
 
         0, MI.getOperand(2).getExpr(),
 
         0, MI.getOperand(2).getExpr(),
         MCFixupKind(NuPlus::fixup_NuPlus_Absl)));
+
         MCFixupKind(NaplesPU::fixup_NaplesPU_Absl)));
 
   } else if (MI.getOperand(3).isExpr()) {
 
   } else if (MI.getOperand(3).isExpr()) {
 
     Fixups.push_back(MCFixup::create(
 
     Fixups.push_back(MCFixup::create(
 
         0, MI.getOperand(3).getExpr(),
 
         0, MI.getOperand(3).getExpr(),
         MCFixupKind(NuPlus::fixup_NuPlus_Absl)));
+
         MCFixupKind(NaplesPU::fixup_NaplesPU_Absl)));
 
   }
 
   }
  
Line 168: Line 168:
 
}
 
}
  
unsigned NuPlusMCCodeEmitter::encodeLEAValue(const MCInst &MI, unsigned Op,
+
unsigned NaplesPUMCCodeEmitter::encodeLEAValue(const MCInst &MI, unsigned Op,
 
                                             SmallVectorImpl<MCFixup> &Fixups,
 
                                             SmallVectorImpl<MCFixup> &Fixups,
 
                                             const MCSubtargetInfo &STI) const {
 
                                             const MCSubtargetInfo &STI) const {
Line 180: Line 180:
 
     Fixups.push_back(MCFixup::create(
 
     Fixups.push_back(MCFixup::create(
 
         0, offsetOp.getExpr(),
 
         0, offsetOp.getExpr(),
         MCFixupKind(NuPlus::fixup_NuPlus_PCRel_Lea)));
+
         MCFixupKind(NaplesPU::fixup_NaplesPU_PCRel_Lea)));
 
   } else if (offsetOp.isImm())
 
   } else if (offsetOp.isImm())
 
     encoding |= static_cast<short>(offsetOp.getImm())<<1;
 
     encoding |= static_cast<short>(offsetOp.getImm())<<1;
Line 189: Line 189:
 
}
 
}
  
// Encode NuPlus Memory Operand.  The result is a packed field with the
+
// Encode NaplesPU Memory Operand.  The result is a packed field with the
 
// register in the low 5 bits and the offset in the remainder.  The instruction
 
// register in the low 5 bits and the offset in the remainder.  The instruction
 
// patterns will put these into the proper part of the instruction
 
// patterns will put these into the proper part of the instruction
// (NuPlusInstrFormats.td).
+
// (NaplesPUInstrFormats.td).
 
unsigned
 
unsigned
NuPlusMCCodeEmitter::encodeMemoryOpValue(const MCInst &MI, unsigned Op,
+
NaplesPUMCCodeEmitter::encodeMemoryOpValue(const MCInst &MI, unsigned Op,
 
                                         SmallVectorImpl<MCFixup> &Fixups,
 
                                         SmallVectorImpl<MCFixup> &Fixups,
 
                                         const MCSubtargetInfo &STI) const {
 
                                         const MCSubtargetInfo &STI) const {
Line 218: Line 218:
 
     Fixups.push_back(
 
     Fixups.push_back(
 
         MCFixup::create(0, offsetOp.getExpr(),
 
         MCFixup::create(0, offsetOp.getExpr(),
                         MCFixupKind(NuPlus::fixup_NuPlus_PCRel_Mem)));
+
                         MCFixupKind(NaplesPU::fixup_NaplesPU_PCRel_Mem)));
 
   } else if (offsetOp.isImm())
 
   } else if (offsetOp.isImm())
 
     encoding |= static_cast<short>(offsetOp.getImm()) << 6;
 
     encoding |= static_cast<short>(offsetOp.getImm()) << 6;
Line 229: Line 229:
 
// target operand. If the machine operand requires relocation,
 
// target operand. If the machine operand requires relocation,
 
// record the relocation and return zero.
 
// record the relocation and return zero.
unsigned NuPlusMCCodeEmitter::encodeBranchTargetOpValue(
+
unsigned NaplesPUMCCodeEmitter::encodeBranchTargetOpValue(
 
     const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
 
     const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
 
     const MCSubtargetInfo &STI) const {
 
     const MCSubtargetInfo &STI) const {
Line 242: Line 242:
 
   const MCExpr *Expr = MO.getExpr();
 
   const MCExpr *Expr = MO.getExpr();
 
   Fixups.push_back(
 
   Fixups.push_back(
       MCFixup::create(0, Expr, MCFixupKind(NuPlus::fixup_NuPlus_Branch)));
+
       MCFixup::create(0, Expr, MCFixupKind(NaplesPU::fixup_NaplesPU_Branch)));
 
   return 0;
 
   return 0;
 
}
 
}
  
#include "NuPlusGenMCCodeEmitter.inc"
+
#include "NaplesPUGenMCCodeEmitter.inc"
  
 
</syntaxhighlight>
 
</syntaxhighlight>

Latest revision as of 16:05, 21 June 2019

NaplesPUMCCodeEmitter class transforms MCInst objects into binary code representation.

//===-- NaplesPUMCCodeEmitter.cpp - Convert NaplesPU code to machine code -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the NaplesPUMCCodeEmitter class.
//
//===----------------------------------------------------------------------===//

#include "MCTargetDesc/NaplesPUFixupKinds.h"
#include "MCTargetDesc/NaplesPUMCTargetDesc.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

#define DEBUG_TYPE "mccodeemitter"

STATISTIC(MCNumEmitted, "Number of MC instructions emitted");

namespace {
class NaplesPUMCCodeEmitter : public MCCodeEmitter {
  NaplesPUMCCodeEmitter(const NaplesPUMCCodeEmitter &) = delete;
  void operator=(const NaplesPUMCCodeEmitter &) = delete;
  MCContext &Ctx;

public:
  NaplesPUMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx): Ctx(ctx) {}

  // getBinaryCodeForInstr - TableGen'erated function for getting the
  // binary encoding for an instruction.
  uint64_t getBinaryCodeForInstr(const MCInst &MI,
                                 SmallVectorImpl<MCFixup> &Fixups,
                                 const MCSubtargetInfo &STI) const;

  /// getMachineOpValue - Return binary encoding of operand. If the machine
  /// operand requires relocation, record the relocation and return zero.
  unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
                             SmallVectorImpl<MCFixup> &Fixups,
                             const MCSubtargetInfo &STI) const;

  void encodeInstruction(const MCInst &MI, raw_ostream &OS,
                         SmallVectorImpl<MCFixup> &Fixups,
                         const MCSubtargetInfo &STI) const override;

  unsigned encodeMemoryOpValue(const MCInst &MI, unsigned Op,
                               SmallVectorImpl<MCFixup> &Fixups,
                               const MCSubtargetInfo &STI) const;

  unsigned encodeLEAValue(const MCInst &MI, unsigned Op,
                          SmallVectorImpl<MCFixup> &Fixups,
                          const MCSubtargetInfo &STI) const;

  unsigned encodeABShValue(const MCInst &MI, unsigned Op,
                          SmallVectorImpl<MCFixup> &Fixups,
                          const MCSubtargetInfo &STI) const; 

  unsigned encodeABSlValue(const MCInst &MI, unsigned Op,
                          SmallVectorImpl<MCFixup> &Fixups,
                          const MCSubtargetInfo &STI) const;                        

  unsigned encodeBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
                                     SmallVectorImpl<MCFixup> &Fixups,
                                     const MCSubtargetInfo &STI) const;
  
  // Emit one byte through output stream (from MCBlazeMCCodeEmitter)
  void EmitByte(unsigned char C, raw_ostream &OS) const { OS << (char)C; }

  void EmitLEConstant(uint64_t Val, unsigned Size, raw_ostream &OS) const {
    assert(Size <= 8 && "size too big in emit constant");

    for (unsigned i = 0; i != Size; ++i) {
      EmitByte(Val & 255, OS);
      Val >>= 8;
    }
  }

};
} // end anonymous namespace

MCCodeEmitter *llvm::createNaplesPUMCCodeEmitter(const MCInstrInfo &MCII,
                                              const MCRegisterInfo &MRI,
                                              MCContext &Ctx) {
  return new NaplesPUMCCodeEmitter(MCII, Ctx);
}

// Return binary encoding of operand.
unsigned NaplesPUMCCodeEmitter::
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
                  SmallVectorImpl<MCFixup> &Fixups,
                  const MCSubtargetInfo &STI) const {

  if (MO.isReg())
    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());

  if (MO.isImm())
    return static_cast<unsigned>(MO.getImm());

  return 0;
}

void NaplesPUMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
                                           SmallVectorImpl<MCFixup> &Fixups,
                                           const MCSubtargetInfo &STI) const {
  unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI);
  EmitLEConstant(Bits, 4, OS);

  ++MCNumEmitted;  // Keep track of the # of mi's emitted.
}

unsigned NaplesPUMCCodeEmitter::encodeABShValue(const MCInst &MI, unsigned Op,
                                            SmallVectorImpl<MCFixup> &Fixups,
                                            const MCSubtargetInfo &STI) const {
  // with LEAH the second operand is expected to be the global address
  //MCOperand address = MI.getOperand(1);
  // the third operand is the label used in the asm
  //MCOperand address_asm = MI.getOperand(2);

  if (MI.getOperand(1).isExpr()) {
    Fixups.push_back(MCFixup::create(
        0, MI.getOperand(1).getExpr(),
        MCFixupKind(NaplesPU::fixup_NaplesPU_Absh)));
  } else if ( MI.getOperand(2).isExpr()) {
    Fixups.push_back(MCFixup::create(
        0,  MI.getOperand(2).getExpr(),
        MCFixupKind(NaplesPU::fixup_NaplesPU_Absh)));
  }

  return 0;
}

unsigned NaplesPUMCCodeEmitter::encodeABSlValue(const MCInst &MI, unsigned Op,
                                            SmallVectorImpl<MCFixup> &Fixups,
                                            const MCSubtargetInfo &STI) const {
  // with LEAH the third operand is expected to be the global address
  //MCOperand address = MI.getOperand(2);
  // the fourth operand is the label used in the asm
  //MCOperand address_asm = MI.getOperand(3);

  if (MI.getOperand(2).isExpr()) {
    Fixups.push_back(MCFixup::create(
        0, MI.getOperand(2).getExpr(),
        MCFixupKind(NaplesPU::fixup_NaplesPU_Absl)));
  } else if (MI.getOperand(3).isExpr()) {
    Fixups.push_back(MCFixup::create(
        0, MI.getOperand(3).getExpr(),
        MCFixupKind(NaplesPU::fixup_NaplesPU_Absl)));
  }

  return 0;
}

unsigned NaplesPUMCCodeEmitter::encodeLEAValue(const MCInst &MI, unsigned Op,
                                            SmallVectorImpl<MCFixup> &Fixups,
                                            const MCSubtargetInfo &STI) const {
  MCOperand baseReg = MI.getOperand(1);
  MCOperand offsetOp = MI.getOperand(2);

  assert(baseReg.isReg() && "First operand of LEA op is not register.");
  unsigned encoding = Ctx.getRegisterInfo()->getEncodingValue(baseReg.getReg())<<10;
  if (offsetOp.isExpr()) {
    // Load with a label. This is a PC relative load.  Add a fixup.
    Fixups.push_back(MCFixup::create(
        0, offsetOp.getExpr(),
        MCFixupKind(NaplesPU::fixup_NaplesPU_PCRel_Lea)));
  } else if (offsetOp.isImm())
    encoding |= static_cast<short>(offsetOp.getImm())<<1;
  else
    assert(offsetOp.isImm() && "Second operand of LEA op is unknown type.");

  return encoding;
}

// Encode NaplesPU Memory Operand.  The result is a packed field with the
// register in the low 5 bits and the offset in the remainder.  The instruction
// patterns will put these into the proper part of the instruction
// (NaplesPUInstrFormats.td).
unsigned
NaplesPUMCCodeEmitter::encodeMemoryOpValue(const MCInst &MI, unsigned Op,
                                        SmallVectorImpl<MCFixup> &Fixups,
                                        const MCSubtargetInfo &STI) const {
  unsigned encoding;

  MCOperand baseReg;
  MCOperand offsetOp;

  baseReg = MI.getOperand(1);
  offsetOp = MI.getOperand(2); 
  
  // Register
  // This is register/offset.  No need for relocation.
  assert(baseReg.isReg() && "First operand is not register.");
  //encoding just the register
  encoding = Ctx.getRegisterInfo()->getEncodingValue(baseReg.getReg());
  // Offset
  if (offsetOp.isExpr()) {
    // Load with a label. This is a PC relative load.  Add a fixup.
    // XXX Note that this assumes unmasked instructions.  A masked
    // instruction will not work and should not be used. Check for this
    // and return an error.
    Fixups.push_back(
        MCFixup::create(0, offsetOp.getExpr(),
                        MCFixupKind(NaplesPU::fixup_NaplesPU_PCRel_Mem)));
  } else if (offsetOp.isImm())
    encoding |= static_cast<short>(offsetOp.getImm()) << 6;
  else
    assert(offsetOp.isImm() && "Second operand of memory op is unknown type.");
  return encoding;
}

// encodeBranchTargetOpValue - Return binary encoding of the jump
// target operand. If the machine operand requires relocation,
// record the relocation and return zero.
unsigned NaplesPUMCCodeEmitter::encodeBranchTargetOpValue(
    const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
    const MCSubtargetInfo &STI) const {

  const MCOperand &MO = MI.getOperand(OpNo);
  if (MO.isImm())
    return MO.getImm();

  assert(MO.isExpr() &&
         "encodeBranchTargetOpValue expects only expressions or an immediate");

  const MCExpr *Expr = MO.getExpr();
  Fixups.push_back(
      MCFixup::create(0, Expr, MCFixupKind(NaplesPU::fixup_NaplesPU_Branch)));
  return 0;
}

#include "NaplesPUGenMCCodeEmitter.inc"