LLVM API Documentation
00001 //=- AArch64/AArch64MCCodeEmitter.cpp - Convert AArch64 code to machine code-=// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the AArch64MCCodeEmitter class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "MCTargetDesc/AArch64AddressingModes.h" 00015 #include "MCTargetDesc/AArch64FixupKinds.h" 00016 #include "MCTargetDesc/AArch64MCExpr.h" 00017 #include "Utils/AArch64BaseInfo.h" 00018 #include "llvm/ADT/Statistic.h" 00019 #include "llvm/MC/MCCodeEmitter.h" 00020 #include "llvm/MC/MCContext.h" 00021 #include "llvm/MC/MCInst.h" 00022 #include "llvm/MC/MCInstrInfo.h" 00023 #include "llvm/MC/MCRegisterInfo.h" 00024 #include "llvm/MC/MCSubtargetInfo.h" 00025 #include "llvm/Support/raw_ostream.h" 00026 using namespace llvm; 00027 00028 #define DEBUG_TYPE "mccodeemitter" 00029 00030 STATISTIC(MCNumEmitted, "Number of MC instructions emitted."); 00031 STATISTIC(MCNumFixups, "Number of MC fixups created."); 00032 00033 namespace { 00034 00035 class AArch64MCCodeEmitter : public MCCodeEmitter { 00036 MCContext &Ctx; 00037 00038 AArch64MCCodeEmitter(const AArch64MCCodeEmitter &); // DO NOT IMPLEMENT 00039 void operator=(const AArch64MCCodeEmitter &); // DO NOT IMPLEMENT 00040 public: 00041 AArch64MCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, 00042 MCContext &ctx) 00043 : Ctx(ctx) {} 00044 00045 ~AArch64MCCodeEmitter() {} 00046 00047 // getBinaryCodeForInstr - TableGen'erated function for getting the 00048 // binary encoding for an instruction. 00049 uint64_t getBinaryCodeForInstr(const MCInst &MI, 00050 SmallVectorImpl<MCFixup> &Fixups, 00051 const MCSubtargetInfo &STI) const; 00052 00053 /// getMachineOpValue - Return binary encoding of operand. If the machine 00054 /// operand requires relocation, record the relocation and return zero. 00055 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 00056 SmallVectorImpl<MCFixup> &Fixups, 00057 const MCSubtargetInfo &STI) const; 00058 00059 /// getLdStUImm12OpValue - Return encoding info for 12-bit unsigned immediate 00060 /// attached to a load, store or prfm instruction. If operand requires a 00061 /// relocation, record it and return zero in that part of the encoding. 00062 template <uint32_t FixupKind> 00063 uint32_t getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx, 00064 SmallVectorImpl<MCFixup> &Fixups, 00065 const MCSubtargetInfo &STI) const; 00066 00067 /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label 00068 /// target. 00069 uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 00070 SmallVectorImpl<MCFixup> &Fixups, 00071 const MCSubtargetInfo &STI) const; 00072 00073 /// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and 00074 /// the 2-bit shift field. 00075 uint32_t getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx, 00076 SmallVectorImpl<MCFixup> &Fixups, 00077 const MCSubtargetInfo &STI) const; 00078 00079 /// getCondBranchTargetOpValue - Return the encoded value for a conditional 00080 /// branch target. 00081 uint32_t getCondBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 00082 SmallVectorImpl<MCFixup> &Fixups, 00083 const MCSubtargetInfo &STI) const; 00084 00085 /// getLoadLiteralOpValue - Return the encoded value for a load-literal 00086 /// pc-relative address. 00087 uint32_t getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx, 00088 SmallVectorImpl<MCFixup> &Fixups, 00089 const MCSubtargetInfo &STI) const; 00090 00091 /// getMemExtendOpValue - Return the encoded value for a reg-extend load/store 00092 /// instruction: bit 0 is whether a shift is present, bit 1 is whether the 00093 /// operation is a sign extend (as opposed to a zero extend). 00094 uint32_t getMemExtendOpValue(const MCInst &MI, unsigned OpIdx, 00095 SmallVectorImpl<MCFixup> &Fixups, 00096 const MCSubtargetInfo &STI) const; 00097 00098 /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and- 00099 /// branch target. 00100 uint32_t getTestBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 00101 SmallVectorImpl<MCFixup> &Fixups, 00102 const MCSubtargetInfo &STI) const; 00103 00104 /// getBranchTargetOpValue - Return the encoded value for an unconditional 00105 /// branch target. 00106 uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 00107 SmallVectorImpl<MCFixup> &Fixups, 00108 const MCSubtargetInfo &STI) const; 00109 00110 /// getMoveWideImmOpValue - Return the encoded value for the immediate operand 00111 /// of a MOVZ or MOVK instruction. 00112 uint32_t getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx, 00113 SmallVectorImpl<MCFixup> &Fixups, 00114 const MCSubtargetInfo &STI) const; 00115 00116 /// getVecShifterOpValue - Return the encoded value for the vector shifter. 00117 uint32_t getVecShifterOpValue(const MCInst &MI, unsigned OpIdx, 00118 SmallVectorImpl<MCFixup> &Fixups, 00119 const MCSubtargetInfo &STI) const; 00120 00121 /// getMoveVecShifterOpValue - Return the encoded value for the vector move 00122 /// shifter (MSL). 00123 uint32_t getMoveVecShifterOpValue(const MCInst &MI, unsigned OpIdx, 00124 SmallVectorImpl<MCFixup> &Fixups, 00125 const MCSubtargetInfo &STI) const; 00126 00127 /// getFixedPointScaleOpValue - Return the encoded value for the 00128 // FP-to-fixed-point scale factor. 00129 uint32_t getFixedPointScaleOpValue(const MCInst &MI, unsigned OpIdx, 00130 SmallVectorImpl<MCFixup> &Fixups, 00131 const MCSubtargetInfo &STI) const; 00132 00133 uint32_t getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx, 00134 SmallVectorImpl<MCFixup> &Fixups, 00135 const MCSubtargetInfo &STI) const; 00136 uint32_t getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx, 00137 SmallVectorImpl<MCFixup> &Fixups, 00138 const MCSubtargetInfo &STI) const; 00139 uint32_t getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx, 00140 SmallVectorImpl<MCFixup> &Fixups, 00141 const MCSubtargetInfo &STI) const; 00142 uint32_t getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx, 00143 SmallVectorImpl<MCFixup> &Fixups, 00144 const MCSubtargetInfo &STI) const; 00145 uint32_t getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx, 00146 SmallVectorImpl<MCFixup> &Fixups, 00147 const MCSubtargetInfo &STI) const; 00148 uint32_t getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx, 00149 SmallVectorImpl<MCFixup> &Fixups, 00150 const MCSubtargetInfo &STI) const; 00151 uint32_t getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx, 00152 SmallVectorImpl<MCFixup> &Fixups, 00153 const MCSubtargetInfo &STI) const; 00154 uint32_t getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx, 00155 SmallVectorImpl<MCFixup> &Fixups, 00156 const MCSubtargetInfo &STI) const; 00157 00158 /// getSIMDShift64OpValue - Return the encoded value for the 00159 // shift-by-immediate AdvSIMD instructions. 00160 uint32_t getSIMDShift64OpValue(const MCInst &MI, unsigned OpIdx, 00161 SmallVectorImpl<MCFixup> &Fixups, 00162 const MCSubtargetInfo &STI) const; 00163 00164 uint32_t getSIMDShift64_32OpValue(const MCInst &MI, unsigned OpIdx, 00165 SmallVectorImpl<MCFixup> &Fixups, 00166 const MCSubtargetInfo &STI) const; 00167 00168 uint32_t getSIMDShift32OpValue(const MCInst &MI, unsigned OpIdx, 00169 SmallVectorImpl<MCFixup> &Fixups, 00170 const MCSubtargetInfo &STI) const; 00171 00172 uint32_t getSIMDShift16OpValue(const MCInst &MI, unsigned OpIdx, 00173 SmallVectorImpl<MCFixup> &Fixups, 00174 const MCSubtargetInfo &STI) const; 00175 00176 unsigned fixMOVZ(const MCInst &MI, unsigned EncodedValue, 00177 const MCSubtargetInfo &STI) const; 00178 00179 void EmitByte(unsigned char C, raw_ostream &OS) const { OS << (char)C; } 00180 00181 void EmitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) const { 00182 // Output the constant in little endian byte order. 00183 for (unsigned i = 0; i != Size; ++i) { 00184 EmitByte(Val & 255, OS); 00185 Val >>= 8; 00186 } 00187 } 00188 00189 void EncodeInstruction(const MCInst &MI, raw_ostream &OS, 00190 SmallVectorImpl<MCFixup> &Fixups, 00191 const MCSubtargetInfo &STI) const override; 00192 00193 unsigned fixMulHigh(const MCInst &MI, unsigned EncodedValue, 00194 const MCSubtargetInfo &STI) const; 00195 00196 template<int hasRs, int hasRt2> unsigned 00197 fixLoadStoreExclusive(const MCInst &MI, unsigned EncodedValue, 00198 const MCSubtargetInfo &STI) const; 00199 00200 unsigned fixOneOperandFPComparison(const MCInst &MI, unsigned EncodedValue, 00201 const MCSubtargetInfo &STI) const; 00202 }; 00203 00204 } // end anonymous namespace 00205 00206 MCCodeEmitter *llvm::createAArch64MCCodeEmitter(const MCInstrInfo &MCII, 00207 const MCRegisterInfo &MRI, 00208 const MCSubtargetInfo &STI, 00209 MCContext &Ctx) { 00210 return new AArch64MCCodeEmitter(MCII, STI, Ctx); 00211 } 00212 00213 /// getMachineOpValue - Return binary encoding of operand. If the machine 00214 /// operand requires relocation, record the relocation and return zero. 00215 unsigned 00216 AArch64MCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 00217 SmallVectorImpl<MCFixup> &Fixups, 00218 const MCSubtargetInfo &STI) const { 00219 if (MO.isReg()) 00220 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 00221 00222 assert(MO.isImm() && "did not expect relocated expression"); 00223 return static_cast<unsigned>(MO.getImm()); 00224 } 00225 00226 template<unsigned FixupKind> uint32_t 00227 AArch64MCCodeEmitter::getLdStUImm12OpValue(const MCInst &MI, unsigned OpIdx, 00228 SmallVectorImpl<MCFixup> &Fixups, 00229 const MCSubtargetInfo &STI) const { 00230 const MCOperand &MO = MI.getOperand(OpIdx); 00231 uint32_t ImmVal = 0; 00232 00233 if (MO.isImm()) 00234 ImmVal = static_cast<uint32_t>(MO.getImm()); 00235 else { 00236 assert(MO.isExpr() && "unable to encode load/store imm operand"); 00237 MCFixupKind Kind = MCFixupKind(FixupKind); 00238 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc())); 00239 ++MCNumFixups; 00240 } 00241 00242 return ImmVal; 00243 } 00244 00245 /// getAdrLabelOpValue - Return encoding info for 21-bit immediate ADR label 00246 /// target. 00247 uint32_t 00248 AArch64MCCodeEmitter::getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 00249 SmallVectorImpl<MCFixup> &Fixups, 00250 const MCSubtargetInfo &STI) const { 00251 const MCOperand &MO = MI.getOperand(OpIdx); 00252 00253 // If the destination is an immediate, we have nothing to do. 00254 if (MO.isImm()) 00255 return MO.getImm(); 00256 assert(MO.isExpr() && "Unexpected target type!"); 00257 const MCExpr *Expr = MO.getExpr(); 00258 00259 MCFixupKind Kind = MI.getOpcode() == AArch64::ADR 00260 ? MCFixupKind(AArch64::fixup_aarch64_pcrel_adr_imm21) 00261 : MCFixupKind(AArch64::fixup_aarch64_pcrel_adrp_imm21); 00262 Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); 00263 00264 MCNumFixups += 1; 00265 00266 // All of the information is in the fixup. 00267 return 0; 00268 } 00269 00270 /// getAddSubImmOpValue - Return encoding for the 12-bit immediate value and 00271 /// the 2-bit shift field. The shift field is stored in bits 13-14 of the 00272 /// return value. 00273 uint32_t 00274 AArch64MCCodeEmitter::getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx, 00275 SmallVectorImpl<MCFixup> &Fixups, 00276 const MCSubtargetInfo &STI) const { 00277 // Suboperands are [imm, shifter]. 00278 const MCOperand &MO = MI.getOperand(OpIdx); 00279 const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 00280 assert(AArch64_AM::getShiftType(MO1.getImm()) == AArch64_AM::LSL && 00281 "unexpected shift type for add/sub immediate"); 00282 unsigned ShiftVal = AArch64_AM::getShiftValue(MO1.getImm()); 00283 assert((ShiftVal == 0 || ShiftVal == 12) && 00284 "unexpected shift value for add/sub immediate"); 00285 if (MO.isImm()) 00286 return MO.getImm() | (ShiftVal == 0 ? 0 : (1 << 12)); 00287 assert(MO.isExpr() && "Unable to encode MCOperand!"); 00288 const MCExpr *Expr = MO.getExpr(); 00289 00290 // Encode the 12 bits of the fixup. 00291 MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_add_imm12); 00292 Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); 00293 00294 ++MCNumFixups; 00295 00296 return 0; 00297 } 00298 00299 /// getCondBranchTargetOpValue - Return the encoded value for a conditional 00300 /// branch target. 00301 uint32_t AArch64MCCodeEmitter::getCondBranchTargetOpValue( 00302 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 00303 const MCSubtargetInfo &STI) const { 00304 const MCOperand &MO = MI.getOperand(OpIdx); 00305 00306 // If the destination is an immediate, we have nothing to do. 00307 if (MO.isImm()) 00308 return MO.getImm(); 00309 assert(MO.isExpr() && "Unexpected target type!"); 00310 00311 MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch19); 00312 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc())); 00313 00314 ++MCNumFixups; 00315 00316 // All of the information is in the fixup. 00317 return 0; 00318 } 00319 00320 /// getLoadLiteralOpValue - Return the encoded value for a load-literal 00321 /// pc-relative address. 00322 uint32_t 00323 AArch64MCCodeEmitter::getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx, 00324 SmallVectorImpl<MCFixup> &Fixups, 00325 const MCSubtargetInfo &STI) const { 00326 const MCOperand &MO = MI.getOperand(OpIdx); 00327 00328 // If the destination is an immediate, we have nothing to do. 00329 if (MO.isImm()) 00330 return MO.getImm(); 00331 assert(MO.isExpr() && "Unexpected target type!"); 00332 00333 MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_ldr_pcrel_imm19); 00334 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc())); 00335 00336 ++MCNumFixups; 00337 00338 // All of the information is in the fixup. 00339 return 0; 00340 } 00341 00342 uint32_t 00343 AArch64MCCodeEmitter::getMemExtendOpValue(const MCInst &MI, unsigned OpIdx, 00344 SmallVectorImpl<MCFixup> &Fixups, 00345 const MCSubtargetInfo &STI) const { 00346 unsigned SignExtend = MI.getOperand(OpIdx).getImm(); 00347 unsigned DoShift = MI.getOperand(OpIdx + 1).getImm(); 00348 return (SignExtend << 1) | DoShift; 00349 } 00350 00351 uint32_t 00352 AArch64MCCodeEmitter::getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx, 00353 SmallVectorImpl<MCFixup> &Fixups, 00354 const MCSubtargetInfo &STI) const { 00355 const MCOperand &MO = MI.getOperand(OpIdx); 00356 00357 if (MO.isImm()) 00358 return MO.getImm(); 00359 assert(MO.isExpr() && "Unexpected movz/movk immediate"); 00360 00361 Fixups.push_back(MCFixup::Create( 00362 0, MO.getExpr(), MCFixupKind(AArch64::fixup_aarch64_movw), MI.getLoc())); 00363 00364 ++MCNumFixups; 00365 00366 return 0; 00367 } 00368 00369 /// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and- 00370 /// branch target. 00371 uint32_t AArch64MCCodeEmitter::getTestBranchTargetOpValue( 00372 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 00373 const MCSubtargetInfo &STI) const { 00374 const MCOperand &MO = MI.getOperand(OpIdx); 00375 00376 // If the destination is an immediate, we have nothing to do. 00377 if (MO.isImm()) 00378 return MO.getImm(); 00379 assert(MO.isExpr() && "Unexpected ADR target type!"); 00380 00381 MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch14); 00382 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc())); 00383 00384 ++MCNumFixups; 00385 00386 // All of the information is in the fixup. 00387 return 0; 00388 } 00389 00390 /// getBranchTargetOpValue - Return the encoded value for an unconditional 00391 /// branch target. 00392 uint32_t 00393 AArch64MCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 00394 SmallVectorImpl<MCFixup> &Fixups, 00395 const MCSubtargetInfo &STI) const { 00396 const MCOperand &MO = MI.getOperand(OpIdx); 00397 00398 // If the destination is an immediate, we have nothing to do. 00399 if (MO.isImm()) 00400 return MO.getImm(); 00401 assert(MO.isExpr() && "Unexpected ADR target type!"); 00402 00403 MCFixupKind Kind = MI.getOpcode() == AArch64::BL 00404 ? MCFixupKind(AArch64::fixup_aarch64_pcrel_call26) 00405 : MCFixupKind(AArch64::fixup_aarch64_pcrel_branch26); 00406 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc())); 00407 00408 ++MCNumFixups; 00409 00410 // All of the information is in the fixup. 00411 return 0; 00412 } 00413 00414 /// getVecShifterOpValue - Return the encoded value for the vector shifter: 00415 /// 00416 /// 00 -> 0 00417 /// 01 -> 8 00418 /// 10 -> 16 00419 /// 11 -> 24 00420 uint32_t 00421 AArch64MCCodeEmitter::getVecShifterOpValue(const MCInst &MI, unsigned OpIdx, 00422 SmallVectorImpl<MCFixup> &Fixups, 00423 const MCSubtargetInfo &STI) const { 00424 const MCOperand &MO = MI.getOperand(OpIdx); 00425 assert(MO.isImm() && "Expected an immediate value for the shift amount!"); 00426 00427 switch (MO.getImm()) { 00428 default: 00429 break; 00430 case 0: 00431 return 0; 00432 case 8: 00433 return 1; 00434 case 16: 00435 return 2; 00436 case 24: 00437 return 3; 00438 } 00439 00440 assert(false && "Invalid value for vector shift amount!"); 00441 return 0; 00442 } 00443 00444 uint32_t 00445 AArch64MCCodeEmitter::getSIMDShift64OpValue(const MCInst &MI, unsigned OpIdx, 00446 SmallVectorImpl<MCFixup> &Fixups, 00447 const MCSubtargetInfo &STI) const { 00448 const MCOperand &MO = MI.getOperand(OpIdx); 00449 assert(MO.isImm() && "Expected an immediate value for the shift amount!"); 00450 return 64 - (MO.getImm()); 00451 } 00452 00453 uint32_t AArch64MCCodeEmitter::getSIMDShift64_32OpValue( 00454 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 00455 const MCSubtargetInfo &STI) const { 00456 const MCOperand &MO = MI.getOperand(OpIdx); 00457 assert(MO.isImm() && "Expected an immediate value for the shift amount!"); 00458 return 64 - (MO.getImm() | 32); 00459 } 00460 00461 uint32_t 00462 AArch64MCCodeEmitter::getSIMDShift32OpValue(const MCInst &MI, unsigned OpIdx, 00463 SmallVectorImpl<MCFixup> &Fixups, 00464 const MCSubtargetInfo &STI) const { 00465 const MCOperand &MO = MI.getOperand(OpIdx); 00466 assert(MO.isImm() && "Expected an immediate value for the shift amount!"); 00467 return 32 - (MO.getImm() | 16); 00468 } 00469 00470 uint32_t 00471 AArch64MCCodeEmitter::getSIMDShift16OpValue(const MCInst &MI, unsigned OpIdx, 00472 SmallVectorImpl<MCFixup> &Fixups, 00473 const MCSubtargetInfo &STI) const { 00474 const MCOperand &MO = MI.getOperand(OpIdx); 00475 assert(MO.isImm() && "Expected an immediate value for the shift amount!"); 00476 return 16 - (MO.getImm() | 8); 00477 } 00478 00479 /// getFixedPointScaleOpValue - Return the encoded value for the 00480 // FP-to-fixed-point scale factor. 00481 uint32_t AArch64MCCodeEmitter::getFixedPointScaleOpValue( 00482 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 00483 const MCSubtargetInfo &STI) const { 00484 const MCOperand &MO = MI.getOperand(OpIdx); 00485 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 00486 return 64 - MO.getImm(); 00487 } 00488 00489 uint32_t 00490 AArch64MCCodeEmitter::getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx, 00491 SmallVectorImpl<MCFixup> &Fixups, 00492 const MCSubtargetInfo &STI) const { 00493 const MCOperand &MO = MI.getOperand(OpIdx); 00494 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 00495 return 64 - MO.getImm(); 00496 } 00497 00498 uint32_t 00499 AArch64MCCodeEmitter::getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx, 00500 SmallVectorImpl<MCFixup> &Fixups, 00501 const MCSubtargetInfo &STI) const { 00502 const MCOperand &MO = MI.getOperand(OpIdx); 00503 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 00504 return 32 - MO.getImm(); 00505 } 00506 00507 uint32_t 00508 AArch64MCCodeEmitter::getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx, 00509 SmallVectorImpl<MCFixup> &Fixups, 00510 const MCSubtargetInfo &STI) const { 00511 const MCOperand &MO = MI.getOperand(OpIdx); 00512 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 00513 return 16 - MO.getImm(); 00514 } 00515 00516 uint32_t 00517 AArch64MCCodeEmitter::getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx, 00518 SmallVectorImpl<MCFixup> &Fixups, 00519 const MCSubtargetInfo &STI) const { 00520 const MCOperand &MO = MI.getOperand(OpIdx); 00521 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 00522 return 8 - MO.getImm(); 00523 } 00524 00525 uint32_t 00526 AArch64MCCodeEmitter::getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx, 00527 SmallVectorImpl<MCFixup> &Fixups, 00528 const MCSubtargetInfo &STI) const { 00529 const MCOperand &MO = MI.getOperand(OpIdx); 00530 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 00531 return MO.getImm() - 64; 00532 } 00533 00534 uint32_t 00535 AArch64MCCodeEmitter::getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx, 00536 SmallVectorImpl<MCFixup> &Fixups, 00537 const MCSubtargetInfo &STI) const { 00538 const MCOperand &MO = MI.getOperand(OpIdx); 00539 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 00540 return MO.getImm() - 32; 00541 } 00542 00543 uint32_t 00544 AArch64MCCodeEmitter::getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx, 00545 SmallVectorImpl<MCFixup> &Fixups, 00546 const MCSubtargetInfo &STI) const { 00547 const MCOperand &MO = MI.getOperand(OpIdx); 00548 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 00549 return MO.getImm() - 16; 00550 } 00551 00552 uint32_t 00553 AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx, 00554 SmallVectorImpl<MCFixup> &Fixups, 00555 const MCSubtargetInfo &STI) const { 00556 const MCOperand &MO = MI.getOperand(OpIdx); 00557 assert(MO.isImm() && "Expected an immediate value for the scale amount!"); 00558 return MO.getImm() - 8; 00559 } 00560 00561 /// getMoveVecShifterOpValue - Return the encoded value for the vector move 00562 /// shifter (MSL). 00563 uint32_t AArch64MCCodeEmitter::getMoveVecShifterOpValue( 00564 const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 00565 const MCSubtargetInfo &STI) const { 00566 const MCOperand &MO = MI.getOperand(OpIdx); 00567 assert(MO.isImm() && 00568 "Expected an immediate value for the move shift amount!"); 00569 unsigned ShiftVal = AArch64_AM::getShiftValue(MO.getImm()); 00570 assert((ShiftVal == 8 || ShiftVal == 16) && "Invalid shift amount!"); 00571 return ShiftVal == 8 ? 0 : 1; 00572 } 00573 00574 unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue, 00575 const MCSubtargetInfo &STI) const { 00576 // If one of the signed fixup kinds is applied to a MOVZ instruction, the 00577 // eventual result could be either a MOVZ or a MOVN. It's the MCCodeEmitter's 00578 // job to ensure that any bits possibly affected by this are 0. This means we 00579 // must zero out bit 30 (essentially emitting a MOVN). 00580 MCOperand UImm16MO = MI.getOperand(1); 00581 00582 // Nothing to do if there's no fixup. 00583 if (UImm16MO.isImm()) 00584 return EncodedValue; 00585 00586 const AArch64MCExpr *A64E = cast<AArch64MCExpr>(UImm16MO.getExpr()); 00587 switch (A64E->getKind()) { 00588 case AArch64MCExpr::VK_DTPREL_G2: 00589 case AArch64MCExpr::VK_DTPREL_G1: 00590 case AArch64MCExpr::VK_DTPREL_G0: 00591 case AArch64MCExpr::VK_GOTTPREL_G1: 00592 case AArch64MCExpr::VK_TPREL_G2: 00593 case AArch64MCExpr::VK_TPREL_G1: 00594 case AArch64MCExpr::VK_TPREL_G0: 00595 return EncodedValue & ~(1u << 30); 00596 default: 00597 // Nothing to do for an unsigned fixup. 00598 return EncodedValue; 00599 } 00600 00601 00602 return EncodedValue & ~(1u << 30); 00603 } 00604 00605 void AArch64MCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS, 00606 SmallVectorImpl<MCFixup> &Fixups, 00607 const MCSubtargetInfo &STI) const { 00608 if (MI.getOpcode() == AArch64::TLSDESCCALL) { 00609 // This is a directive which applies an R_AARCH64_TLSDESC_CALL to the 00610 // following (BLR) instruction. It doesn't emit any code itself so it 00611 // doesn't go through the normal TableGenerated channels. 00612 MCFixupKind Fixup = MCFixupKind(AArch64::fixup_aarch64_tlsdesc_call); 00613 Fixups.push_back(MCFixup::Create(0, MI.getOperand(0).getExpr(), Fixup)); 00614 return; 00615 } 00616 00617 uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI); 00618 EmitConstant(Binary, 4, OS); 00619 ++MCNumEmitted; // Keep track of the # of mi's emitted. 00620 } 00621 00622 unsigned 00623 AArch64MCCodeEmitter::fixMulHigh(const MCInst &MI, 00624 unsigned EncodedValue, 00625 const MCSubtargetInfo &STI) const { 00626 // The Ra field of SMULH and UMULH is unused: it should be assembled as 31 00627 // (i.e. all bits 1) but is ignored by the processor. 00628 EncodedValue |= 0x1f << 10; 00629 return EncodedValue; 00630 } 00631 00632 template<int hasRs, int hasRt2> unsigned 00633 AArch64MCCodeEmitter::fixLoadStoreExclusive(const MCInst &MI, 00634 unsigned EncodedValue, 00635 const MCSubtargetInfo &STI) const { 00636 if (!hasRs) EncodedValue |= 0x001F0000; 00637 if (!hasRt2) EncodedValue |= 0x00007C00; 00638 00639 return EncodedValue; 00640 } 00641 00642 unsigned AArch64MCCodeEmitter::fixOneOperandFPComparison( 00643 const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const { 00644 // The Rm field of FCMP and friends is unused - it should be assembled 00645 // as 0, but is ignored by the processor. 00646 EncodedValue &= ~(0x1f << 16); 00647 return EncodedValue; 00648 } 00649 00650 #include "AArch64GenMCCodeEmitter.inc"