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