brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.3 KiB · f018bdb Raw
221 lines · cpp
1//===-- MSP430MCCodeEmitter.cpp - Convert MSP430 code to machine code -----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the MSP430MCCodeEmitter class.10//11//===----------------------------------------------------------------------===//12 13#include "MSP430.h"14#include "MCTargetDesc/MSP430MCTargetDesc.h"15#include "MCTargetDesc/MSP430FixupKinds.h"16 17#include "llvm/ADT/APFloat.h"18#include "llvm/ADT/SmallVector.h"19#include "llvm/MC/MCCodeEmitter.h"20#include "llvm/MC/MCContext.h"21#include "llvm/MC/MCExpr.h"22#include "llvm/MC/MCFixup.h"23#include "llvm/MC/MCInst.h"24#include "llvm/MC/MCInstrInfo.h"25#include "llvm/MC/MCRegisterInfo.h"26#include "llvm/MC/MCSubtargetInfo.h"27#include "llvm/Support/EndianStream.h"28 29#define DEBUG_TYPE "mccodeemitter"30 31namespace llvm {32 33class MSP430MCCodeEmitter : public MCCodeEmitter {34  MCContext &Ctx;35  MCInstrInfo const &MCII;36 37  // Offset keeps track of current word number being emitted38  // inside a particular instruction.39  mutable unsigned Offset;40 41  /// TableGen'erated function for getting the binary encoding for an42  /// instruction.43  uint64_t getBinaryCodeForInstr(const MCInst &MI,44                                 SmallVectorImpl<MCFixup> &Fixups,45                                 const MCSubtargetInfo &STI) const;46 47  /// Returns the binary encoding of operands.48  ///49  /// If an operand requires relocation, the relocation is recorded50  /// and zero is returned.51  unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,52                             SmallVectorImpl<MCFixup> &Fixups,53                             const MCSubtargetInfo &STI) const;54 55  unsigned getMemOpValue(const MCInst &MI, unsigned Op,56                         SmallVectorImpl<MCFixup> &Fixups,57                         const MCSubtargetInfo &STI) const;58 59  unsigned getPCRelImmOpValue(const MCInst &MI, unsigned Op,60                              SmallVectorImpl<MCFixup> &Fixups,61                              const MCSubtargetInfo &STI) const;62 63  unsigned getCGImmOpValue(const MCInst &MI, unsigned Op,64                           SmallVectorImpl<MCFixup> &Fixups,65                           const MCSubtargetInfo &STI) const;66 67  unsigned getCCOpValue(const MCInst &MI, unsigned Op,68                        SmallVectorImpl<MCFixup> &Fixups,69                        const MCSubtargetInfo &STI) const;70 71public:72  MSP430MCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)73      : Ctx(ctx), MCII(MCII) {}74 75  void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,76                         SmallVectorImpl<MCFixup> &Fixups,77                         const MCSubtargetInfo &STI) const override;78};79 80static void addFixup(SmallVectorImpl<MCFixup> &Fixups, uint32_t Offset,81                     const MCExpr *Value, uint16_t Kind) {82  bool PCRel = false;83  switch (Kind) {84  case MSP430::fixup_10_pcrel:85  case MSP430::fixup_16_pcrel:86  case MSP430::fixup_16_pcrel_byte:87  case MSP430::fixup_2x_pcrel:88  case MSP430::fixup_rl_pcrel:89    PCRel = true;90  }91  Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));92}93 94void MSP430MCCodeEmitter::encodeInstruction(const MCInst &MI,95                                            SmallVectorImpl<char> &CB,96                                            SmallVectorImpl<MCFixup> &Fixups,97                                            const MCSubtargetInfo &STI) const {98  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());99  // Get byte count of instruction.100  unsigned Size = Desc.getSize();101 102  // Initialize fixup offset103  Offset = 2;104 105  uint64_t BinaryOpCode = getBinaryCodeForInstr(MI, Fixups, STI);106  size_t WordCount = Size / 2;107 108  while (WordCount--) {109    support::endian::write(CB, (uint16_t)BinaryOpCode,110                           llvm::endianness::little);111    BinaryOpCode >>= 16;112  }113}114 115unsigned MSP430MCCodeEmitter::getMachineOpValue(const MCInst &MI,116                                                const MCOperand &MO,117                                                SmallVectorImpl<MCFixup> &Fixups,118                                                const MCSubtargetInfo &STI) const {119  if (MO.isReg())120    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());121 122  if (MO.isImm()) {123    Offset += 2;124    return MO.getImm();125  }126 127  assert(MO.isExpr() && "Expected expr operand");128  addFixup(Fixups, Offset, MO.getExpr(), MSP430::fixup_16_byte);129  Offset += 2;130  return 0;131}132 133unsigned MSP430MCCodeEmitter::getMemOpValue(const MCInst &MI, unsigned Op,134                                            SmallVectorImpl<MCFixup> &Fixups,135                                            const MCSubtargetInfo &STI) const {136  const MCOperand &MO1 = MI.getOperand(Op);137  assert(MO1.isReg() && "Register operand expected");138  unsigned Reg = Ctx.getRegisterInfo()->getEncodingValue(MO1.getReg());139 140  const MCOperand &MO2 = MI.getOperand(Op + 1);141  if (MO2.isImm()) {142    Offset += 2;143    return ((unsigned)MO2.getImm() << 4) | Reg;144  }145 146  assert(MO2.isExpr() && "Expr operand expected");147  MSP430::Fixups FixupKind;148  switch (Reg) {149  case 0:150    FixupKind = MSP430::fixup_16_pcrel_byte;151    break;152  case 2:153    FixupKind = MSP430::fixup_16_byte;154    break;155  default:156    FixupKind = MSP430::fixup_16_byte;157    break;158  }159  addFixup(Fixups, Offset, MO2.getExpr(), FixupKind);160  Offset += 2;161  return Reg;162}163 164unsigned MSP430MCCodeEmitter::getPCRelImmOpValue(const MCInst &MI, unsigned Op,165                                                 SmallVectorImpl<MCFixup> &Fixups,166                                                 const MCSubtargetInfo &STI) const {167  const MCOperand &MO = MI.getOperand(Op);168  if (MO.isImm())169    return MO.getImm();170 171  assert(MO.isExpr() && "Expr operand expected");172  addFixup(Fixups, 0, MO.getExpr(), MSP430::fixup_10_pcrel);173  return 0;174}175 176unsigned MSP430MCCodeEmitter::getCGImmOpValue(const MCInst &MI, unsigned Op,177                                              SmallVectorImpl<MCFixup> &Fixups,178                                              const MCSubtargetInfo &STI) const {179  const MCOperand &MO = MI.getOperand(Op);180  assert(MO.isImm() && "Expr operand expected");181 182  int64_t Imm = MO.getImm();183  switch (Imm) {184  default:185    llvm_unreachable("Invalid immediate value");186  case 4:  return 0x22;187  case 8:  return 0x32;188  case 0:  return 0x03;189  case 1:  return 0x13;190  case 2:  return 0x23;191  case -1: return 0x33;192  }193}194 195unsigned MSP430MCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned Op,196                                           SmallVectorImpl<MCFixup> &Fixups,197                                           const MCSubtargetInfo &STI) const {198  const MCOperand &MO = MI.getOperand(Op);199  assert(MO.isImm() && "Immediate operand expected");200  switch (MO.getImm()) {201  case MSP430CC::COND_NE: return 0;202  case MSP430CC::COND_E:  return 1;203  case MSP430CC::COND_LO: return 2;204  case MSP430CC::COND_HS: return 3;205  case MSP430CC::COND_N:  return 4;206  case MSP430CC::COND_GE: return 5;207  case MSP430CC::COND_L:  return 6;208  default:209    llvm_unreachable("Unknown condition code");210  }211}212 213MCCodeEmitter *createMSP430MCCodeEmitter(const MCInstrInfo &MCII,214                                         MCContext &Ctx) {215  return new MSP430MCCodeEmitter(Ctx, MCII);216}217 218#include "MSP430GenMCCodeEmitter.inc"219 220} // end of namespace llvm221