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