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