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/Endian.h" 28 #include "llvm/Support/EndianStream.h" 29 #include "llvm/Support/raw_ostream.h" 30 31 #define DEBUG_TYPE "mccodeemitter" 32 33 namespace llvm { 34 35 class MSP430MCCodeEmitter : public MCCodeEmitter { 36 MCContext &Ctx; 37 MCInstrInfo const &MCII; 38 39 // Offset keeps track of current word number being emitted 40 // inside a particular instruction. 41 mutable unsigned Offset; 42 43 /// TableGen'erated function for getting the binary encoding for an 44 /// instruction. 45 uint64_t getBinaryCodeForInstr(const MCInst &MI, 46 SmallVectorImpl<MCFixup> &Fixups, 47 const MCSubtargetInfo &STI) const; 48 49 /// Returns the binary encoding of operands. 50 /// 51 /// If an operand requires relocation, the relocation is recorded 52 /// and zero is returned. 53 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 54 SmallVectorImpl<MCFixup> &Fixups, 55 const MCSubtargetInfo &STI) const; 56 57 unsigned getMemOpValue(const MCInst &MI, unsigned Op, 58 SmallVectorImpl<MCFixup> &Fixups, 59 const MCSubtargetInfo &STI) const; 60 61 unsigned getPCRelImmOpValue(const MCInst &MI, unsigned Op, 62 SmallVectorImpl<MCFixup> &Fixups, 63 const MCSubtargetInfo &STI) const; 64 65 unsigned getCGImmOpValue(const MCInst &MI, unsigned Op, 66 SmallVectorImpl<MCFixup> &Fixups, 67 const MCSubtargetInfo &STI) const; 68 69 unsigned getCCOpValue(const MCInst &MI, unsigned Op, 70 SmallVectorImpl<MCFixup> &Fixups, 71 const MCSubtargetInfo &STI) const; 72 73 public: 74 MSP430MCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) 75 : Ctx(ctx), MCII(MCII) {} 76 77 void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB, 78 SmallVectorImpl<MCFixup> &Fixups, 79 const MCSubtargetInfo &STI) const override; 80 }; 81 82 void MSP430MCCodeEmitter::encodeInstruction(const MCInst &MI, 83 SmallVectorImpl<char> &CB, 84 SmallVectorImpl<MCFixup> &Fixups, 85 const MCSubtargetInfo &STI) const { 86 const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 87 // Get byte count of instruction. 88 unsigned Size = Desc.getSize(); 89 90 // Initialize fixup offset 91 Offset = 2; 92 93 uint64_t BinaryOpCode = getBinaryCodeForInstr(MI, Fixups, STI); 94 size_t WordCount = Size / 2; 95 96 while (WordCount--) { 97 support::endian::write(CB, (uint16_t)BinaryOpCode, 98 llvm::endianness::little); 99 BinaryOpCode >>= 16; 100 } 101 } 102 103 unsigned MSP430MCCodeEmitter::getMachineOpValue(const MCInst &MI, 104 const MCOperand &MO, 105 SmallVectorImpl<MCFixup> &Fixups, 106 const MCSubtargetInfo &STI) const { 107 if (MO.isReg()) 108 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 109 110 if (MO.isImm()) { 111 Offset += 2; 112 return MO.getImm(); 113 } 114 115 assert(MO.isExpr() && "Expected expr operand"); 116 Fixups.push_back(MCFixup::create(Offset, MO.getExpr(), 117 static_cast<MCFixupKind>(MSP430::fixup_16_byte), MI.getLoc())); 118 Offset += 2; 119 return 0; 120 } 121 122 unsigned MSP430MCCodeEmitter::getMemOpValue(const MCInst &MI, unsigned Op, 123 SmallVectorImpl<MCFixup> &Fixups, 124 const MCSubtargetInfo &STI) const { 125 const MCOperand &MO1 = MI.getOperand(Op); 126 assert(MO1.isReg() && "Register operand expected"); 127 unsigned Reg = Ctx.getRegisterInfo()->getEncodingValue(MO1.getReg()); 128 129 const MCOperand &MO2 = MI.getOperand(Op + 1); 130 if (MO2.isImm()) { 131 Offset += 2; 132 return ((unsigned)MO2.getImm() << 4) | Reg; 133 } 134 135 assert(MO2.isExpr() && "Expr operand expected"); 136 MSP430::Fixups FixupKind; 137 switch (Reg) { 138 case 0: 139 FixupKind = MSP430::fixup_16_pcrel_byte; 140 break; 141 case 2: 142 FixupKind = MSP430::fixup_16_byte; 143 break; 144 default: 145 FixupKind = MSP430::fixup_16_byte; 146 break; 147 } 148 Fixups.push_back(MCFixup::create(Offset, MO2.getExpr(), 149 static_cast<MCFixupKind>(FixupKind), MI.getLoc())); 150 Offset += 2; 151 return Reg; 152 } 153 154 unsigned MSP430MCCodeEmitter::getPCRelImmOpValue(const MCInst &MI, unsigned Op, 155 SmallVectorImpl<MCFixup> &Fixups, 156 const MCSubtargetInfo &STI) const { 157 const MCOperand &MO = MI.getOperand(Op); 158 if (MO.isImm()) 159 return MO.getImm(); 160 161 assert(MO.isExpr() && "Expr operand expected"); 162 Fixups.push_back(MCFixup::create(0, MO.getExpr(), 163 static_cast<MCFixupKind>(MSP430::fixup_10_pcrel), MI.getLoc())); 164 return 0; 165 } 166 167 unsigned MSP430MCCodeEmitter::getCGImmOpValue(const MCInst &MI, unsigned Op, 168 SmallVectorImpl<MCFixup> &Fixups, 169 const MCSubtargetInfo &STI) const { 170 const MCOperand &MO = MI.getOperand(Op); 171 assert(MO.isImm() && "Expr operand expected"); 172 173 int64_t Imm = MO.getImm(); 174 switch (Imm) { 175 default: 176 llvm_unreachable("Invalid immediate value"); 177 case 4: return 0x22; 178 case 8: return 0x32; 179 case 0: return 0x03; 180 case 1: return 0x13; 181 case 2: return 0x23; 182 case -1: return 0x33; 183 } 184 } 185 186 unsigned MSP430MCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned Op, 187 SmallVectorImpl<MCFixup> &Fixups, 188 const MCSubtargetInfo &STI) const { 189 const MCOperand &MO = MI.getOperand(Op); 190 assert(MO.isImm() && "Immediate operand expected"); 191 switch (MO.getImm()) { 192 case MSP430CC::COND_NE: return 0; 193 case MSP430CC::COND_E: return 1; 194 case MSP430CC::COND_LO: return 2; 195 case MSP430CC::COND_HS: return 3; 196 case MSP430CC::COND_N: return 4; 197 case MSP430CC::COND_GE: return 5; 198 case MSP430CC::COND_L: return 6; 199 default: 200 llvm_unreachable("Unknown condition code"); 201 } 202 } 203 204 MCCodeEmitter *createMSP430MCCodeEmitter(const MCInstrInfo &MCII, 205 MCContext &Ctx) { 206 return new MSP430MCCodeEmitter(Ctx, MCII); 207 } 208 209 #include "MSP430GenMCCodeEmitter.inc" 210 211 } // end of namespace llvm 212