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