//===-- SystemZMCCodeEmitter.cpp - Convert SystemZ 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 SystemZMCCodeEmitter class.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "mccodeemitter"
#include "MCTargetDesc/SystemZMCTargetDesc.h"
#include "MCTargetDesc/SystemZMCFixups.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInstrInfo.h"

using namespace llvm;

namespace {
class SystemZMCCodeEmitter : public MCCodeEmitter {
  const MCInstrInfo &MCII;
  MCContext &Ctx;

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

  ~SystemZMCCodeEmitter() {}

  // OVerride MCCodeEmitter.
  virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
                                 SmallVectorImpl<MCFixup> &Fixups) const
    LLVM_OVERRIDE;

private:
  // Automatically generated by TableGen.
  uint64_t getBinaryCodeForInstr(const MCInst &MI,
                                 SmallVectorImpl<MCFixup> &Fixups) const;

  // Called by the TableGen code to get the binary encoding of operand
  // MO in MI.  Fixups is the list of fixups against MI.
  uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
                             SmallVectorImpl<MCFixup> &Fixups) const;

  // Called by the TableGen code to get the binary encoding of an address.
  // The index or length, if any, is encoded first, followed by the base,
  // followed by the displacement.  In a 20-bit displacement,
  // the low 12 bits are encoded before the high 8 bits.
  uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
                               SmallVectorImpl<MCFixup> &Fixups) const;
  uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
                               SmallVectorImpl<MCFixup> &Fixups) const;
  uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
                                SmallVectorImpl<MCFixup> &Fixups) const;
  uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
                                SmallVectorImpl<MCFixup> &Fixups) const;
  uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
                                    SmallVectorImpl<MCFixup> &Fixups) const;

  // Operand OpNum of MI needs a PC-relative fixup of kind Kind at
  // Offset bytes from the start of MI.  Add the fixup to Fixups
  // and return the in-place addend, which since we're a RELA target
  // is always 0.
  uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,
                            SmallVectorImpl<MCFixup> &Fixups,
                            unsigned Kind, int64_t Offset) const;

  uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,
                              SmallVectorImpl<MCFixup> &Fixups) const {
    return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC16DBL, 2);
  }
  uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,
                              SmallVectorImpl<MCFixup> &Fixups) const {
    return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC32DBL, 2);
  }
};
}

MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,
                                                const MCRegisterInfo &MRI,
                                                const MCSubtargetInfo &MCSTI,
                                                MCContext &Ctx) {
  return new SystemZMCCodeEmitter(MCII, Ctx);
}

void SystemZMCCodeEmitter::
EncodeInstruction(const MCInst &MI, raw_ostream &OS,
                  SmallVectorImpl<MCFixup> &Fixups) const {
  uint64_t Bits = getBinaryCodeForInstr(MI, Fixups);
  unsigned Size = MCII.get(MI.getOpcode()).getSize();
  // Big-endian insertion of Size bytes.
  unsigned ShiftValue = (Size * 8) - 8;
  for (unsigned I = 0; I != Size; ++I) {
    OS << uint8_t(Bits >> ShiftValue);
    ShiftValue -= 8;
  }
}

uint64_t SystemZMCCodeEmitter::
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
                  SmallVectorImpl<MCFixup> &Fixups) const {
  if (MO.isReg())
    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
  if (MO.isImm())
    return static_cast<uint64_t>(MO.getImm());
  llvm_unreachable("Unexpected operand type!");
}

uint64_t SystemZMCCodeEmitter::
getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
                    SmallVectorImpl<MCFixup> &Fixups) const {
  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups);
  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups);
  assert(isUInt<4>(Base) && isUInt<12>(Disp));
  return (Base << 12) | Disp;
}

uint64_t SystemZMCCodeEmitter::
getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
                    SmallVectorImpl<MCFixup> &Fixups) const {
  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups);
  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups);
  assert(isUInt<4>(Base) && isInt<20>(Disp));
  return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12);
}

uint64_t SystemZMCCodeEmitter::
getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
                     SmallVectorImpl<MCFixup> &Fixups) const {
  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups);
  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups);
  uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups);
  assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index));
  return (Index << 16) | (Base << 12) | Disp;
}

uint64_t SystemZMCCodeEmitter::
getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
                     SmallVectorImpl<MCFixup> &Fixups) const {
  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups);
  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups);
  uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups);
  assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index));
  return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8)
    | ((Disp & 0xff000) >> 12);
}

uint64_t SystemZMCCodeEmitter::
getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
                         SmallVectorImpl<MCFixup> &Fixups) const {
  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups);
  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups);
  uint64_t Len  = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups) - 1;
  assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len));
  return (Len << 16) | (Base << 12) | Disp;
}

uint64_t
SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
                                       SmallVectorImpl<MCFixup> &Fixups,
                                       unsigned Kind, int64_t Offset) const {
  const MCOperand &MO = MI.getOperand(OpNum);
  const MCExpr *Expr;
  if (MO.isImm())
    Expr = MCConstantExpr::Create(MO.getImm() + Offset, Ctx);
  else {
    Expr = MO.getExpr();
    if (Offset) {
      // The operand value is relative to the start of MI, but the fixup
      // is relative to the operand field itself, which is Offset bytes
      // into MI.  Add Offset to the relocation value to cancel out
      // this difference.
      const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx);
      Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx);
    }
  }
  Fixups.push_back(MCFixup::Create(Offset, Expr, (MCFixupKind)Kind));
  return 0;
}

#include "SystemZGenMCCodeEmitter.inc"
