1 //===-- PPCMCCodeEmitter.cpp - Convert PPC 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 PPCMCCodeEmitter class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #define DEBUG_TYPE "mccodeemitter" 15 #include "MCTargetDesc/PPCMCTargetDesc.h" 16 #include "MCTargetDesc/PPCFixupKinds.h" 17 #include "llvm/ADT/Statistic.h" 18 #include "llvm/MC/MCCodeEmitter.h" 19 #include "llvm/MC/MCContext.h" 20 #include "llvm/MC/MCExpr.h" 21 #include "llvm/MC/MCInst.h" 22 #include "llvm/MC/MCInstrInfo.h" 23 #include "llvm/MC/MCSubtargetInfo.h" 24 #include "llvm/Support/ErrorHandling.h" 25 #include "llvm/Support/raw_ostream.h" 26 #include "llvm/Target/TargetOpcodes.h" 27 using namespace llvm; 28 29 STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); 30 31 namespace { 32 class PPCMCCodeEmitter : public MCCodeEmitter { 33 PPCMCCodeEmitter(const PPCMCCodeEmitter &) LLVM_DELETED_FUNCTION; 34 void operator=(const PPCMCCodeEmitter &) LLVM_DELETED_FUNCTION; 35 36 const MCContext &CTX; 37 38 public: 39 PPCMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) : CTX(ctx) { 40 } 41 42 ~PPCMCCodeEmitter() {} 43 44 unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo, 45 SmallVectorImpl<MCFixup> &Fixups, 46 const MCSubtargetInfo &STI) const; 47 unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo, 48 SmallVectorImpl<MCFixup> &Fixups, 49 const MCSubtargetInfo &STI) const; 50 unsigned getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo, 51 SmallVectorImpl<MCFixup> &Fixups, 52 const MCSubtargetInfo &STI) const; 53 unsigned getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo, 54 SmallVectorImpl<MCFixup> &Fixups, 55 const MCSubtargetInfo &STI) const; 56 unsigned getImm16Encoding(const MCInst &MI, unsigned OpNo, 57 SmallVectorImpl<MCFixup> &Fixups, 58 const MCSubtargetInfo &STI) const; 59 unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo, 60 SmallVectorImpl<MCFixup> &Fixups, 61 const MCSubtargetInfo &STI) const; 62 unsigned getMemRIXEncoding(const MCInst &MI, unsigned OpNo, 63 SmallVectorImpl<MCFixup> &Fixups, 64 const MCSubtargetInfo &STI) const; 65 unsigned getTLSRegEncoding(const MCInst &MI, unsigned OpNo, 66 SmallVectorImpl<MCFixup> &Fixups, 67 const MCSubtargetInfo &STI) const; 68 unsigned getTLSCallEncoding(const MCInst &MI, unsigned OpNo, 69 SmallVectorImpl<MCFixup> &Fixups, 70 const MCSubtargetInfo &STI) const; 71 unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo, 72 SmallVectorImpl<MCFixup> &Fixups, 73 const MCSubtargetInfo &STI) const; 74 75 /// getMachineOpValue - Return binary encoding of operand. If the machine 76 /// operand requires relocation, record the relocation and return zero. 77 unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, 78 SmallVectorImpl<MCFixup> &Fixups, 79 const MCSubtargetInfo &STI) const; 80 81 // getBinaryCodeForInstr - TableGen'erated function for getting the 82 // binary encoding for an instruction. 83 uint64_t getBinaryCodeForInstr(const MCInst &MI, 84 SmallVectorImpl<MCFixup> &Fixups, 85 const MCSubtargetInfo &STI) const; 86 void EncodeInstruction(const MCInst &MI, raw_ostream &OS, 87 SmallVectorImpl<MCFixup> &Fixups, 88 const MCSubtargetInfo &STI) const { 89 // For fast-isel, a float COPY_TO_REGCLASS can survive this long. 90 // It's just a nop to keep the register classes happy, so don't 91 // generate anything. 92 unsigned Opcode = MI.getOpcode(); 93 if (Opcode == TargetOpcode::COPY_TO_REGCLASS) 94 return; 95 96 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 97 98 // BL8_NOP etc. all have a size of 8 because of the following 'nop'. 99 unsigned Size = 4; // FIXME: Have Desc.getSize() return the correct value! 100 if (Opcode == PPC::BL8_NOP || Opcode == PPC::BLA8_NOP || 101 Opcode == PPC::BL8_NOP_TLS) 102 Size = 8; 103 104 // Output the constant in big endian byte order. 105 int ShiftValue = (Size * 8) - 8; 106 for (unsigned i = 0; i != Size; ++i) { 107 OS << (char)(Bits >> ShiftValue); 108 Bits <<= 8; 109 } 110 111 ++MCNumEmitted; // Keep track of the # of mi's emitted. 112 } 113 114 }; 115 116 } // end anonymous namespace 117 118 MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII, 119 const MCRegisterInfo &MRI, 120 const MCSubtargetInfo &STI, 121 MCContext &Ctx) { 122 return new PPCMCCodeEmitter(MCII, Ctx); 123 } 124 125 unsigned PPCMCCodeEmitter:: 126 getDirectBrEncoding(const MCInst &MI, unsigned OpNo, 127 SmallVectorImpl<MCFixup> &Fixups, 128 const MCSubtargetInfo &STI) const { 129 const MCOperand &MO = MI.getOperand(OpNo); 130 if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); 131 132 // Add a fixup for the branch target. 133 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), 134 (MCFixupKind)PPC::fixup_ppc_br24)); 135 return 0; 136 } 137 138 unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo, 139 SmallVectorImpl<MCFixup> &Fixups, 140 const MCSubtargetInfo &STI) const { 141 const MCOperand &MO = MI.getOperand(OpNo); 142 if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); 143 144 // Add a fixup for the branch target. 145 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), 146 (MCFixupKind)PPC::fixup_ppc_brcond14)); 147 return 0; 148 } 149 150 unsigned PPCMCCodeEmitter:: 151 getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo, 152 SmallVectorImpl<MCFixup> &Fixups, 153 const MCSubtargetInfo &STI) const { 154 const MCOperand &MO = MI.getOperand(OpNo); 155 if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); 156 157 // Add a fixup for the branch target. 158 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), 159 (MCFixupKind)PPC::fixup_ppc_br24abs)); 160 return 0; 161 } 162 163 unsigned PPCMCCodeEmitter:: 164 getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo, 165 SmallVectorImpl<MCFixup> &Fixups, 166 const MCSubtargetInfo &STI) const { 167 const MCOperand &MO = MI.getOperand(OpNo); 168 if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); 169 170 // Add a fixup for the branch target. 171 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), 172 (MCFixupKind)PPC::fixup_ppc_brcond14abs)); 173 return 0; 174 } 175 176 unsigned PPCMCCodeEmitter::getImm16Encoding(const MCInst &MI, unsigned OpNo, 177 SmallVectorImpl<MCFixup> &Fixups, 178 const MCSubtargetInfo &STI) const { 179 const MCOperand &MO = MI.getOperand(OpNo); 180 if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); 181 182 // Add a fixup for the immediate field. 183 Fixups.push_back(MCFixup::Create(2, MO.getExpr(), 184 (MCFixupKind)PPC::fixup_ppc_half16)); 185 return 0; 186 } 187 188 unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo, 189 SmallVectorImpl<MCFixup> &Fixups, 190 const MCSubtargetInfo &STI) const { 191 // Encode (imm, reg) as a memri, which has the low 16-bits as the 192 // displacement and the next 5 bits as the register #. 193 assert(MI.getOperand(OpNo+1).isReg()); 194 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 16; 195 196 const MCOperand &MO = MI.getOperand(OpNo); 197 if (MO.isImm()) 198 return (getMachineOpValue(MI, MO, Fixups, STI) & 0xFFFF) | RegBits; 199 200 // Add a fixup for the displacement field. 201 Fixups.push_back(MCFixup::Create(2, MO.getExpr(), 202 (MCFixupKind)PPC::fixup_ppc_half16)); 203 return RegBits; 204 } 205 206 207 unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo, 208 SmallVectorImpl<MCFixup> &Fixups, 209 const MCSubtargetInfo &STI) const { 210 // Encode (imm, reg) as a memrix, which has the low 14-bits as the 211 // displacement and the next 5 bits as the register #. 212 assert(MI.getOperand(OpNo+1).isReg()); 213 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 14; 214 215 const MCOperand &MO = MI.getOperand(OpNo); 216 if (MO.isImm()) 217 return ((getMachineOpValue(MI, MO, Fixups, STI) >> 2) & 0x3FFF) | RegBits; 218 219 // Add a fixup for the displacement field. 220 Fixups.push_back(MCFixup::Create(2, MO.getExpr(), 221 (MCFixupKind)PPC::fixup_ppc_half16ds)); 222 return RegBits; 223 } 224 225 226 unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo, 227 SmallVectorImpl<MCFixup> &Fixups, 228 const MCSubtargetInfo &STI) const { 229 const MCOperand &MO = MI.getOperand(OpNo); 230 if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups, STI); 231 232 // Add a fixup for the TLS register, which simply provides a relocation 233 // hint to the linker that this statement is part of a relocation sequence. 234 // Return the thread-pointer register's encoding. 235 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), 236 (MCFixupKind)PPC::fixup_ppc_nofixup)); 237 Triple TT(STI.getTargetTriple()); 238 bool isPPC64 = TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le; 239 return CTX.getRegisterInfo()->getEncodingValue(isPPC64 ? PPC::X13 : PPC::R2); 240 } 241 242 unsigned PPCMCCodeEmitter::getTLSCallEncoding(const MCInst &MI, unsigned OpNo, 243 SmallVectorImpl<MCFixup> &Fixups, 244 const MCSubtargetInfo &STI) const { 245 // For special TLS calls, we need two fixups; one for the branch target 246 // (__tls_get_addr), which we create via getDirectBrEncoding as usual, 247 // and one for the TLSGD or TLSLD symbol, which is emitted here. 248 const MCOperand &MO = MI.getOperand(OpNo+1); 249 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), 250 (MCFixupKind)PPC::fixup_ppc_nofixup)); 251 return getDirectBrEncoding(MI, OpNo, Fixups, STI); 252 } 253 254 unsigned PPCMCCodeEmitter:: 255 get_crbitm_encoding(const MCInst &MI, unsigned OpNo, 256 SmallVectorImpl<MCFixup> &Fixups, 257 const MCSubtargetInfo &STI) const { 258 const MCOperand &MO = MI.getOperand(OpNo); 259 assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 || 260 MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) && 261 (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7)); 262 return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 263 } 264 265 266 unsigned PPCMCCodeEmitter:: 267 getMachineOpValue(const MCInst &MI, const MCOperand &MO, 268 SmallVectorImpl<MCFixup> &Fixups, 269 const MCSubtargetInfo &STI) const { 270 if (MO.isReg()) { 271 // MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand. 272 // The GPR operand should come through here though. 273 assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 && 274 MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) || 275 MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7); 276 return CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 277 } 278 279 assert(MO.isImm() && 280 "Relocation required in an instruction that we cannot encode!"); 281 return MO.getImm(); 282 } 283 284 285 #include "PPCGenMCCodeEmitter.inc" 286