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-exception 6 // 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 31 namespace llvm { 32 33 class MSP430MCCodeEmitter : public MCCodeEmitter { 34 MCContext &Ctx; 35 MCInstrInfo const &MCII; 36 37 // Offset keeps track of current word number being emitted 38 // inside a particular instruction. 39 mutable unsigned Offset; 40 41 /// TableGen'erated function for getting the binary encoding for an 42 /// 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 recorded 50 /// 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 71 public: 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 80 static 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 94 void 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 offset 103 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 115 unsigned 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 133 unsigned 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 164 unsigned 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 176 unsigned 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 195 unsigned 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 213 MCCodeEmitter *createMSP430MCCodeEmitter(const MCInstrInfo &MCII, 214 MCContext &Ctx) { 215 return new MSP430MCCodeEmitter(Ctx, MCII); 216 } 217 218 #include "MSP430GenMCCodeEmitter.inc" 219 220 } // end of namespace llvm 221