1 //===-- LanaiMCCodeEmitter.cpp - Convert Lanai 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 LanaiMCCodeEmitter class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "Lanai.h" 15 #include "MCTargetDesc/LanaiBaseInfo.h" 16 #include "MCTargetDesc/LanaiFixupKinds.h" 17 #include "MCTargetDesc/LanaiMCExpr.h" 18 #include "MCTargetDesc/LanaiMCTargetDesc.h" 19 #include "llvm/ADT/Statistic.h" 20 #include "llvm/MC/MCCodeEmitter.h" 21 #include "llvm/MC/MCFixup.h" 22 #include "llvm/MC/MCInst.h" 23 #include "llvm/MC/MCInstrInfo.h" 24 #include "llvm/MC/MCRegisterInfo.h" 25 #include "llvm/MC/MCSubtargetInfo.h" 26 #include "llvm/MC/MCSymbol.h" 27 #include "llvm/Support/raw_ostream.h" 28 29 #define DEBUG_TYPE "mccodeemitter" 30 31 STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); 32 33 namespace llvm { 34 namespace { 35 class LanaiMCCodeEmitter : public MCCodeEmitter { 36 LanaiMCCodeEmitter(const LanaiMCCodeEmitter &); // DO NOT IMPLEMENT 37 void operator=(const LanaiMCCodeEmitter &); // DO NOT IMPLEMENT 38 const MCInstrInfo &InstrInfo; 39 MCContext &Context; 40 41 public: 42 LanaiMCCodeEmitter(const MCInstrInfo &MCII, MCContext &C) 43 : InstrInfo(MCII), Context(C) {} 44 45 ~LanaiMCCodeEmitter() override {} 46 47 // The functions below are called by TableGen generated functions for getting 48 // the binary encoding of instructions/opereands. 49 50 // getBinaryCodeForInstr - TableGen'erated function for getting the 51 // binary encoding for an instruction. 52 uint64_t getBinaryCodeForInstr(const MCInst &Inst, 53 SmallVectorImpl<MCFixup> &Fixups, 54 const MCSubtargetInfo &SubtargetInfo) const; 55 56 // getMachineOpValue - Return binary encoding of operand. If the machine 57 // operand requires relocation, record the relocation and return zero. 58 unsigned getMachineOpValue(const MCInst &Inst, const MCOperand &MCOp, 59 SmallVectorImpl<MCFixup> &Fixups, 60 const MCSubtargetInfo &SubtargetInfo) const; 61 62 unsigned getRiMemoryOpValue(const MCInst &Inst, unsigned OpNo, 63 SmallVectorImpl<MCFixup> &Fixups, 64 const MCSubtargetInfo &SubtargetInfo) const; 65 66 unsigned getRrMemoryOpValue(const MCInst &Inst, unsigned OpNo, 67 SmallVectorImpl<MCFixup> &Fixups, 68 const MCSubtargetInfo &SubtargetInfo) const; 69 70 unsigned getSplsOpValue(const MCInst &Inst, unsigned OpNo, 71 SmallVectorImpl<MCFixup> &Fixups, 72 const MCSubtargetInfo &SubtargetInfo) const; 73 74 unsigned getBranchTargetOpValue(const MCInst &Inst, unsigned OpNo, 75 SmallVectorImpl<MCFixup> &Fixups, 76 const MCSubtargetInfo &SubtargetInfo) const; 77 78 unsigned getCallTargetOpValue(const MCInst &Inst, unsigned OpNo, 79 SmallVectorImpl<MCFixup> &Fixups, 80 const MCSubtargetInfo &SubtargetInfo) const; 81 82 void encodeInstruction(const MCInst &Inst, raw_ostream &Ostream, 83 SmallVectorImpl<MCFixup> &Fixups, 84 const MCSubtargetInfo &SubtargetInfo) const override; 85 86 unsigned adjustPqBitsRmAndRrm(const MCInst &Inst, unsigned Value, 87 const MCSubtargetInfo &STI) const; 88 89 unsigned adjustPqBitsSpls(const MCInst &Inst, unsigned Value, 90 const MCSubtargetInfo &STI) const; 91 }; 92 93 Lanai::Fixups FixupKind(const MCExpr *Expr) { 94 if (isa<MCSymbolRefExpr>(Expr)) 95 return Lanai::FIXUP_LANAI_21; 96 if (const LanaiMCExpr *McExpr = dyn_cast<LanaiMCExpr>(Expr)) { 97 LanaiMCExpr::VariantKind ExprKind = McExpr->getKind(); 98 switch (ExprKind) { 99 case LanaiMCExpr::VK_Lanai_None: 100 return Lanai::FIXUP_LANAI_21; 101 case LanaiMCExpr::VK_Lanai_ABS_HI: 102 return Lanai::FIXUP_LANAI_HI16; 103 case LanaiMCExpr::VK_Lanai_ABS_LO: 104 return Lanai::FIXUP_LANAI_LO16; 105 } 106 } 107 return Lanai::Fixups(0); 108 } 109 110 // getMachineOpValue - Return binary encoding of operand. If the machine 111 // operand requires relocation, record the relocation and return zero. 112 unsigned LanaiMCCodeEmitter::getMachineOpValue( 113 const MCInst &Inst, const MCOperand &MCOp, SmallVectorImpl<MCFixup> &Fixups, 114 const MCSubtargetInfo &SubtargetInfo) const { 115 if (MCOp.isReg()) 116 return getLanaiRegisterNumbering(MCOp.getReg()); 117 if (MCOp.isImm()) 118 return static_cast<unsigned>(MCOp.getImm()); 119 120 // MCOp must be an expression 121 assert(MCOp.isExpr()); 122 const MCExpr *Expr = MCOp.getExpr(); 123 124 // Extract the symbolic reference side of a binary expression. 125 if (Expr->getKind() == MCExpr::Binary) { 126 const MCBinaryExpr *BinaryExpr = static_cast<const MCBinaryExpr *>(Expr); 127 Expr = BinaryExpr->getLHS(); 128 } 129 130 assert(isa<LanaiMCExpr>(Expr) || Expr->getKind() == MCExpr::SymbolRef); 131 // Push fixup (all info is contained within) 132 Fixups.push_back( 133 MCFixup::create(0, MCOp.getExpr(), MCFixupKind(FixupKind(Expr)))); 134 return 0; 135 } 136 137 // Helper function to adjust P and Q bits on load and store instructions. 138 unsigned adjustPqBits(const MCInst &Inst, unsigned Value, unsigned PBitShift, 139 unsigned QBitShift) { 140 const MCOperand AluOp = Inst.getOperand(3); 141 unsigned AluCode = AluOp.getImm(); 142 143 // Set the P bit to one iff the immediate is nonzero and not a post-op 144 // instruction. 145 const MCOperand Op2 = Inst.getOperand(2); 146 Value &= ~(1 << PBitShift); 147 if (!LPAC::isPostOp(AluCode) && 148 ((Op2.isImm() && Op2.getImm() != 0) || 149 (Op2.isReg() && Op2.getReg() != Lanai::R0) || (Op2.isExpr()))) 150 Value |= (1 << PBitShift); 151 152 // Set the Q bit to one iff it is a post- or pre-op instruction. 153 assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && 154 "Expected register operand."); 155 Value &= ~(1 << QBitShift); 156 if (LPAC::modifiesOp(AluCode) && ((Op2.isImm() && Op2.getImm() != 0) || 157 (Op2.isReg() && Op2.getReg() != Lanai::R0))) 158 Value |= (1 << QBitShift); 159 160 return Value; 161 } 162 163 unsigned 164 LanaiMCCodeEmitter::adjustPqBitsRmAndRrm(const MCInst &Inst, unsigned Value, 165 const MCSubtargetInfo &STI) const { 166 return adjustPqBits(Inst, Value, 17, 16); 167 } 168 169 unsigned 170 LanaiMCCodeEmitter::adjustPqBitsSpls(const MCInst &Inst, unsigned Value, 171 const MCSubtargetInfo &STI) const { 172 return adjustPqBits(Inst, Value, 11, 10); 173 } 174 175 void LanaiMCCodeEmitter::encodeInstruction( 176 const MCInst &Inst, raw_ostream &Ostream, SmallVectorImpl<MCFixup> &Fixups, 177 const MCSubtargetInfo &SubtargetInfo) const { 178 // Get instruction encoding and emit it 179 unsigned Value = getBinaryCodeForInstr(Inst, Fixups, SubtargetInfo); 180 ++MCNumEmitted; // Keep track of the number of emitted insns. 181 182 // Emit bytes in big-endian 183 for (int i = (4 - 1) * 8; i >= 0; i -= 8) 184 Ostream << static_cast<char>((Value >> i) & 0xff); 185 } 186 187 // Encode Lanai Memory Operand 188 unsigned LanaiMCCodeEmitter::getRiMemoryOpValue( 189 const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, 190 const MCSubtargetInfo &SubtargetInfo) const { 191 unsigned Encoding; 192 const MCOperand Op1 = Inst.getOperand(OpNo + 0); 193 const MCOperand Op2 = Inst.getOperand(OpNo + 1); 194 const MCOperand AluOp = Inst.getOperand(OpNo + 2); 195 196 assert(Op1.isReg() && "First operand is not register."); 197 assert((Op2.isImm() || Op2.isExpr()) && 198 "Second operand is neither an immediate nor an expression."); 199 assert((LPAC::getAluOp(AluOp.getImm()) == LPAC::ADD) && 200 "Register immediate only supports addition operator"); 201 202 Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 18); 203 if (Op2.isImm()) { 204 assert(isInt<16>(Op2.getImm()) && 205 "Constant value truncated (limited to 16-bit)"); 206 207 Encoding |= (Op2.getImm() & 0xffff); 208 if (Op2.getImm() != 0) { 209 if (LPAC::isPreOp(AluOp.getImm())) 210 Encoding |= (0x3 << 16); 211 if (LPAC::isPostOp(AluOp.getImm())) 212 Encoding |= (0x1 << 16); 213 } 214 } else 215 getMachineOpValue(Inst, Op2, Fixups, SubtargetInfo); 216 217 return Encoding; 218 } 219 220 unsigned LanaiMCCodeEmitter::getRrMemoryOpValue( 221 const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, 222 const MCSubtargetInfo &SubtargetInfo) const { 223 unsigned Encoding; 224 const MCOperand Op1 = Inst.getOperand(OpNo + 0); 225 const MCOperand Op2 = Inst.getOperand(OpNo + 1); 226 const MCOperand AluMCOp = Inst.getOperand(OpNo + 2); 227 228 assert(Op1.isReg() && "First operand is not register."); 229 Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 15); 230 assert(Op2.isReg() && "Second operand is not register."); 231 Encoding |= (getLanaiRegisterNumbering(Op2.getReg()) << 10); 232 233 assert(AluMCOp.isImm() && "Third operator is not immediate."); 234 // Set BBB 235 unsigned AluOp = AluMCOp.getImm(); 236 Encoding |= LPAC::encodeLanaiAluCode(AluOp) << 5; 237 // Set P and Q 238 if (LPAC::isPreOp(AluOp)) 239 Encoding |= (0x3 << 8); 240 if (LPAC::isPostOp(AluOp)) 241 Encoding |= (0x1 << 8); 242 // Set JJJJ 243 switch (LPAC::getAluOp(AluOp)) { 244 case LPAC::SHL: 245 case LPAC::SRL: 246 Encoding |= 0x10; 247 break; 248 case LPAC::SRA: 249 Encoding |= 0x18; 250 break; 251 default: 252 break; 253 } 254 255 return Encoding; 256 } 257 258 unsigned 259 LanaiMCCodeEmitter::getSplsOpValue(const MCInst &Inst, unsigned OpNo, 260 SmallVectorImpl<MCFixup> &Fixups, 261 const MCSubtargetInfo &SubtargetInfo) const { 262 unsigned Encoding; 263 const MCOperand Op1 = Inst.getOperand(OpNo + 0); 264 const MCOperand Op2 = Inst.getOperand(OpNo + 1); 265 const MCOperand AluOp = Inst.getOperand(OpNo + 2); 266 267 assert(Op1.isReg() && "First operand is not register."); 268 assert((Op2.isImm() || Op2.isExpr()) && 269 "Second operand is neither an immediate nor an expression."); 270 assert((LPAC::getAluOp(AluOp.getImm()) == LPAC::ADD) && 271 "Register immediate only supports addition operator"); 272 273 Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 12); 274 if (Op2.isImm()) { 275 assert(isInt<10>(Op2.getImm()) && 276 "Constant value truncated (limited to 10-bit)"); 277 278 Encoding |= (Op2.getImm() & 0x3ff); 279 if (Op2.getImm() != 0) { 280 if (LPAC::isPreOp(AluOp.getImm())) 281 Encoding |= (0x3 << 10); 282 if (LPAC::isPostOp(AluOp.getImm())) 283 Encoding |= (0x1 << 10); 284 } 285 } else 286 getMachineOpValue(Inst, Op2, Fixups, SubtargetInfo); 287 288 return Encoding; 289 } 290 291 unsigned LanaiMCCodeEmitter::getCallTargetOpValue( 292 const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, 293 const MCSubtargetInfo &SubtargetInfo) const { 294 const MCOperand &MCOp = Inst.getOperand(OpNo); 295 if (MCOp.isReg() || MCOp.isImm()) 296 return getMachineOpValue(Inst, MCOp, Fixups, SubtargetInfo); 297 298 Fixups.push_back(MCFixup::create( 299 0, MCOp.getExpr(), static_cast<MCFixupKind>(Lanai::FIXUP_LANAI_25))); 300 301 return 0; 302 } 303 304 unsigned LanaiMCCodeEmitter::getBranchTargetOpValue( 305 const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, 306 const MCSubtargetInfo &SubtargetInfo) const { 307 const MCOperand &MCOp = Inst.getOperand(OpNo); 308 if (MCOp.isReg() || MCOp.isImm()) 309 return getMachineOpValue(Inst, MCOp, Fixups, SubtargetInfo); 310 311 Fixups.push_back(MCFixup::create( 312 0, MCOp.getExpr(), static_cast<MCFixupKind>(Lanai::FIXUP_LANAI_25))); 313 314 return 0; 315 } 316 317 #include "LanaiGenMCCodeEmitter.inc" 318 } // namespace 319 } // namespace llvm 320 321 llvm::MCCodeEmitter * 322 llvm::createLanaiMCCodeEmitter(const MCInstrInfo &InstrInfo, 323 const MCRegisterInfo &MRI, MCContext &context) { 324 return new LanaiMCCodeEmitter(InstrInfo, context); 325 } 326