ARMCodeEmitter.cpp revision d5f8f75e62b9564890df9599eb916ea4bf68c307
18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//===-- ARM/ARMCodeEmitter.cpp - Convert ARM code to machine code ---------===// 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// The LLVM Compiler Infrastructure 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// This file is distributed under the University of Illinois Open Source 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// License. See LICENSE.TXT for details. 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//===----------------------------------------------------------------------===// 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// This file contains the pass that transforms the ARM machine instructions into 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// relocatable machine code. 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// 132d238fd9871687b1557f15b8878a6cf3e9634b57David 'Digit' Turner//===----------------------------------------------------------------------===// 14cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll 15353b3b1135563e2bcaf7797acfa35a2fe2d3a818Ot ten Thije#define DEBUG_TYPE "jit" 165ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner#include "ARM.h" 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "ARMAddressingModes.h" 185ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner#include "ARMConstantPoolValue.h" 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "ARMInstrInfo.h" 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "ARMRelocations.h" 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "ARMSubtarget.h" 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "ARMTargetMachine.h" 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "llvm/Constants.h" 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "llvm/DerivedTypes.h" 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "llvm/Function.h" 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "llvm/PassManager.h" 278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "llvm/CodeGen/JITCodeEmitter.h" 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "llvm/CodeGen/MachineConstantPool.h" 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "llvm/CodeGen/MachineFunctionPass.h" 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "llvm/CodeGen/MachineInstr.h" 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "llvm/CodeGen/MachineJumpTableInfo.h" 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "llvm/CodeGen/MachineModuleInfo.h" 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "llvm/CodeGen/Passes.h" 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "llvm/ADT/Statistic.h" 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "llvm/Support/Debug.h" 368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "llvm/Support/ErrorHandling.h" 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "llvm/Support/raw_ostream.h" 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef NDEBUG 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <iomanip> 408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectusing namespace llvm; 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectSTATISTIC(NumEmitted, "Number of machine instructions emitted"); 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectnamespace { 468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project class ARMCodeEmitter : public MachineFunctionPass { 488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARMJITInfo *JTI; 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const ARMInstrInfo *II; 508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const TargetData *TD; 518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const ARMSubtarget *Subtarget; 528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TargetMachine &TM; 538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project JITCodeEmitter &MCE; 548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project MachineModuleInfo *MMI; 558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const std::vector<MachineConstantPoolEntry> *MCPEs; 568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const std::vector<MachineJumpTableEntry> *MJTEs; 578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bool IsPIC; 588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bool IsThumb; 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void getAnalysisUsage(AnalysisUsage &AU) const { 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project AU.addRequired<MachineModuleInfo>(); 628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project MachineFunctionPass::getAnalysisUsage(AU); 638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project static char ID; 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project public: 678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARMCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce) 688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project : MachineFunctionPass(ID), JTI(0), 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project II((const ARMInstrInfo *)tm.getInstrInfo()), 7042074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner TD(tm.getTargetData()), TM(tm), 7142074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner MCE(mce), MCPEs(0), MJTEs(0), 7242074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner IsPIC(TM.getRelocationModel() == Reloc::PIC_), IsThumb(false) {} 7342074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner 7425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner /// getBinaryCodeForInstr - This function, generated by the 7542074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner /// CodeEmitterGenerator using TableGen, produces the binary encoding for 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /// machine instructions. 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getBinaryCodeForInstr(const MachineInstr &MI) const; 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bool runOnMachineFunction(MachineFunction &MF); 808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project virtual const char *getPassName() const { 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return "ARM Machine Code Emitter"; 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitInstruction(const MachineInstr &MI); 868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project private: 888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitWordLE(unsigned Binary); 908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitDWordLE(uint64_t Binary); 918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitConstantToMemory(unsigned CPI, const Constant *CV); 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitConstPoolInstruction(const MachineInstr &MI); 938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitMOVi32immInstruction(const MachineInstr &MI); 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitMOVi2piecesInstruction(const MachineInstr &MI); 958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitLEApcrelInstruction(const MachineInstr &MI); 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitLEApcrelJTInstruction(const MachineInstr &MI); 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitPseudoMoveInstruction(const MachineInstr &MI); 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void addPCLabel(unsigned LabelID); 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitPseudoInstruction(const MachineInstr &MI); 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getMachineSoRegOpValue(const MachineInstr &MI, 1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const TargetInstrDesc &TID, 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const MachineOperand &MO, 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned OpIdx); 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getMachineSoImmOpValue(unsigned SoImm); 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getAddrModeSBit(const MachineInstr &MI, 107dd90991bb911bc61c885f710a848692b593b72c3David 'Digit' Turner const TargetInstrDesc &TID) const; 1085ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitDataProcessingInstruction(const MachineInstr &MI, 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned ImplicitRd = 0, 1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned ImplicitRn = 0); 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitLoadStoreInstruction(const MachineInstr &MI, 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned ImplicitRd = 0, 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned ImplicitRn = 0); 1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner void emitMiscLoadStoreInstruction(const MachineInstr &MI, 11825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned ImplicitRn = 0); 11942074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner 1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitLoadStoreMultipleInstruction(const MachineInstr &MI); 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 122b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner void emitMulFrmInstruction(const MachineInstr &MI); 1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitExtendInstruction(const MachineInstr &MI); 12542074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitMiscArithInstruction(const MachineInstr &MI); 1275ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 1285ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner void emitSaturateInstruction(const MachineInstr &MI); 1295ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitBranchInstruction(const MachineInstr &MI); 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitInlineJumpTable(unsigned JTIndex); 1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitMiscBranchInstruction(const MachineInstr &MI); 1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitVFPArithInstruction(const MachineInstr &MI); 1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitVFPConversionInstruction(const MachineInstr &MI); 1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitVFPLoadStoreInstruction(const MachineInstr &MI); 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI); 1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitMiscInstruction(const MachineInstr &MI); 1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitNEONLaneInstruction(const MachineInstr &MI); 14742074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner void emitNEONDupInstruction(const MachineInstr &MI); 1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project void emitNEON1RegModImmInstruction(const MachineInstr &MI); 1495ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner void emitNEON2RegInstruction(const MachineInstr &MI); 1505ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner void emitNEON3RegInstruction(const MachineInstr &MI); 1515ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /// getMachineOpValue - Return binary encoding of operand. If the machine 1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /// operand requires relocation, record the relocation and return zero. 1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getMachineOpValue(const MachineInstr &MI, 1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const MachineOperand &MO) const; 1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getMachineOpValue(const MachineInstr &MI, unsigned OpIdx) const { 1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return getMachineOpValue(MI, MI.getOperand(OpIdx)); 1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // FIXME: The legacy JIT ARMCodeEmitter doesn't rely on the the 1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // TableGen'erated getBinaryCodeForInstr() function to encode any 16242074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner // operand values, instead querying getMachineOpValue() directly for 16342074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner // each operand it needs to encode. Thus, any of the new encoder 16442074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner // helper functions can simply return 0 as the values the return 165fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner // are already handled elsewhere. They are placeholders to allow this 166fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner // encoder to continue to function until the MC encoder is sufficiently 1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // far along that this one can be eliminated entirely. 1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned NEONThumb2DataIPostEncoder(const MachineInstr &MI, unsigned Val) 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned NEONThumb2LoadStorePostEncoder(const MachineInstr &MI,unsigned Val) 1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned NEONThumb2DupPostEncoder(const MachineInstr &MI,unsigned Val) 1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 1745ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner unsigned VFPThumb2PostEncoder(const MachineInstr&MI, unsigned Val) 1755ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner const { 1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IsThumb) { 1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Val &= 0x0FFFFFFF; 1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Val |= 0xE0000000; 1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return Val; 1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getAdrLabelOpValue(const MachineInstr &MI, unsigned Op) 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getThumbAdrLabelOpValue(const MachineInstr &MI, unsigned Op) 1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getThumbBLTargetOpValue(const MachineInstr &MI, unsigned Op) 1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getThumbBLXTargetOpValue(const MachineInstr &MI, unsigned Op) 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getThumbBRTargetOpValue(const MachineInstr &MI, unsigned Op) 1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getThumbBCCTargetOpValue(const MachineInstr &MI, unsigned Op) 1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getThumbCBTargetOpValue(const MachineInstr &MI, unsigned Op) 1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned Op) 1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getUnconditionalBranchTargetOpValue(const MachineInstr &MI, 1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned Op) const { return 0; } 2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getARMBranchTargetOpValue(const MachineInstr &MI, unsigned Op) 2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getCCOutOpValue(const MachineInstr &MI, unsigned Op) 2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 20425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getSOImmOpValue(const MachineInstr &MI, unsigned Op) 20525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 20625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getT2SOImmOpValue(const MachineInstr &MI, unsigned Op) 20725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getSORegOpValue(const MachineInstr &MI, unsigned Op) 2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getThumbAddrModeRegRegOpValue(const MachineInstr &MI, unsigned Op) 21125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 21225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getT2AddrModeImm12OpValue(const MachineInstr &MI, unsigned Op) 21325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 21425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getT2AddrModeImm8OpValue(const MachineInstr &MI, unsigned Op) 21525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 21625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getT2AddrModeImm8s4OpValue(const MachineInstr &MI, unsigned Op) 21725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 21825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getT2AddrModeImm8OffsetOpValue(const MachineInstr &MI, unsigned Op) 21925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 22025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getT2AddrModeImm12OffsetOpValue(const MachineInstr &MI,unsigned Op) 22125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 22225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getT2AddrModeSORegOpValue(const MachineInstr &MI, unsigned Op) 22325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 22425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getT2SORegOpValue(const MachineInstr &MI, unsigned Op) 22525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getRotImmOpValue(const MachineInstr &MI, unsigned Op) 2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getImmMinusOneOpValue(const MachineInstr &MI, unsigned Op) 2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 23025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getT2AdrLabelOpValue(const MachineInstr &MI, unsigned Op) 2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getAddrMode6AddressOpValue(const MachineInstr &MI, unsigned Op) 2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getAddrMode6DupAddressOpValue(const MachineInstr &MI, unsigned Op) 2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const { return 0; } 2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getAddrMode6OffsetOpValue(const MachineInstr &MI, unsigned Op) 23725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getBitfieldInvertedMaskOpValue(const MachineInstr &MI, 2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned Op) const { return 0; } 2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned getMsbOpValue(const MachineInstr &MI, 24125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned Op) const { return 0; } 2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t getLdStmModeOpValue(const MachineInstr &MI, unsigned OpIdx) 2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const {return 0; } 2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t getLdStSORegOpValue(const MachineInstr &MI, unsigned OpIdx) 24525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 24625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 24725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getAddrModeImm12OpValue(const MachineInstr &MI, unsigned Op) 24825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { 24925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // {17-13} = reg 25025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // {12} = (U)nsigned (add == '1', sub == '0') 25125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // {11-0} = imm12 25225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const MachineOperand &MO = MI.getOperand(Op); 25325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const MachineOperand &MO1 = MI.getOperand(Op + 1); 25425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (!MO.isReg()) { 25525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitConstPoolAddress(MO.getIndex(), ARM::reloc_arm_cp_entry); 25625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return 0; 25725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 25825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned Reg = getARMRegisterNumbering(MO.getReg()); 25925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner int32_t Imm12 = MO1.getImm(); 26025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner uint32_t Binary; 26125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary = Imm12 & 0xfff; 26225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (Imm12 >= 0) 26325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= (1 << 12); 26425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= (Reg << 13); 26525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return Binary; 26625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 26725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 26825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getHiLo16ImmOpValue(const MachineInstr &MI, unsigned Op) const { 26925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return 0; 27025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 27125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 27225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner uint32_t getAddrMode2OpValue(const MachineInstr &MI, unsigned OpIdx) 27325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0;} 27425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner uint32_t getAddrMode2OffsetOpValue(const MachineInstr &MI, unsigned OpIdx) 27525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0;} 27625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner uint32_t getAddrMode3OffsetOpValue(const MachineInstr &MI, unsigned OpIdx) 27725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0;} 27825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner uint32_t getAddrMode3OpValue(const MachineInstr &MI, unsigned Op) 27925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 28025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner uint32_t getAddrModeThumbSPOpValue(const MachineInstr &MI, unsigned Op) 28125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 28225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner uint32_t getAddrModeSOpValue(const MachineInstr &MI, unsigned Op) 28325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 28425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner uint32_t getAddrModeISOpValue(const MachineInstr &MI, unsigned Op) 28525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 28625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner uint32_t getAddrModePCOpValue(const MachineInstr &MI, unsigned Op) 28725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 28825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner uint32_t getAddrMode5OpValue(const MachineInstr &MI, unsigned Op) const { 28925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // {12-9} = reg 29025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // {8} = (U)nsigned (add == '1', sub == '0') 29125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // {7-0} = imm8 29225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner uint32_t Binary; 29325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const MachineOperand &MO = MI.getOperand(Op); 29425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner uint32_t Reg = getMachineOpValue(MI, MO); 29525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= (Reg << 9); 29625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 29725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // If there is a non-zero immediate offset, encode it. 29825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (MO.isReg()) { 29925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const MachineOperand &MO1 = MI.getOperand(Op + 1); 30025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (uint32_t ImmOffs = ARM_AM::getAM5Offset(MO1.getImm())) { 30125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (ARM_AM::getAM5Op(MO1.getImm()) == ARM_AM::add) 30225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= 1 << 8; 30325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= ImmOffs & 0xff; 30425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return Binary; 30525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 30625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 30725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 3082d238fd9871687b1557f15b8878a6cf3e9634b57David 'Digit' Turner // If immediate offset is omitted, default to +0. 30925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= 1 << 8; 31025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return Binary; 31125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 31225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getNEONVcvtImm32OpValue(const MachineInstr &MI, unsigned Op) 31325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 31425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 31540841b2d221273a08abfe20824e7631211ade31dDavid 'Digit' Turner unsigned getRegisterListOpValue(const MachineInstr &MI, unsigned Op) 31625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 31725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 31825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getNarrowShiftRight16Imm(const MachineInstr &MI, unsigned Op) 31925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 32025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getNarrowShiftRight32Imm(const MachineInstr &MI, unsigned Op) 32125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 32225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getNarrowShiftRight64Imm(const MachineInstr &MI, unsigned Op) 32325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const { return 0; } 32425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 32525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner /// getMovi32Value - Return binary encoding of operand for movw/movt. If the 32625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner /// machine operand requires relocation, record the relocation and return 32725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner /// zero. 32825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getMovi32Value(const MachineInstr &MI,const MachineOperand &MO, 32925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned Reloc); 33025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 33125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner /// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value. 33225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner /// 33325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned getShiftOp(unsigned Imm) const ; 33425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 33525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner /// Routines that handle operands which add machine relocations which are 33625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner /// fixed up by the relocation stage. 33725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner void emitGlobalAddress(const GlobalValue *GV, unsigned Reloc, 33825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner bool MayNeedFarStub, bool Indirect, 33925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner intptr_t ACPV = 0) const; 34025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner void emitExternalSymbolAddress(const char *ES, unsigned Reloc) const; 34125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner void emitConstPoolAddress(unsigned CPI, unsigned Reloc) const; 34225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const; 34325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc, 34425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner intptr_t JTBase = 0) const; 34525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner }; 34625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner} 34725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 34825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turnerchar ARMCodeEmitter::ID = 0; 34925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/// createARMJITCodeEmitterPass - Return a pass that emits the collected ARM 35125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner/// code to the specified MCE object. 35225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' TurnerFunctionPass *llvm::createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM, 35325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner JITCodeEmitter &JCE) { 35425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return new ARMCodeEmitter(TM, JCE); 35525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner} 35625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 35725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turnerbool ARMCodeEmitter::runOnMachineFunction(MachineFunction &MF) { 35825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner assert((MF.getTarget().getRelocationModel() != Reloc::Default || 35925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner MF.getTarget().getRelocationModel() != Reloc::Static) && 36025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner "JIT relocation model must be set to static or default!"); 36125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner JTI = ((ARMTargetMachine &)MF.getTarget()).getJITInfo(); 36225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner II = ((const ARMTargetMachine &)MF.getTarget()).getInstrInfo(); 36325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner TD = ((const ARMTargetMachine &)MF.getTarget()).getTargetData(); 36425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Subtarget = &TM.getSubtarget<ARMSubtarget>(); 36525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner MCPEs = &MF.getConstantPool()->getConstants(); 36625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner MJTEs = 0; 36725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (MF.getJumpTableInfo()) MJTEs = &MF.getJumpTableInfo()->getJumpTables(); 36825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner IsPIC = TM.getRelocationModel() == Reloc::PIC_; 36925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner IsThumb = MF.getInfo<ARMFunctionInfo>()->isThumbFunction(); 37025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner JTI->Initialize(MF, IsPIC); 37125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner MMI = &getAnalysis<MachineModuleInfo>(); 37225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner MCE.setModuleInfo(MMI); 37325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 37425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner do { 37525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner DEBUG(errs() << "JITTing function '" 37625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner << MF.getFunction()->getName() << "'\n"); 37725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner MCE.startFunction(MF); 37825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); 37925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner MBB != E; ++MBB) { 38025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner MCE.StartMachineBasicBlock(MBB); 38125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); 38225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner I != E; ++I) 38325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitInstruction(*I); 38425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 38525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } while (MCE.finishFunction(MF)); 38625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 38725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return false; 38825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner} 38925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 39025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner/// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value. 39125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner/// 39225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turnerunsigned ARMCodeEmitter::getShiftOp(unsigned Imm) const { 39325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner switch (ARM_AM::getAM2ShiftOpc(Imm)) { 39425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner default: llvm_unreachable("Unknown shift opc!"); 39525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARM_AM::asr: return 2; 39625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARM_AM::lsl: return 0; 39725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARM_AM::lsr: return 1; 39825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARM_AM::ror: 39925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARM_AM::rrx: return 3; 40025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 40125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return 0; 40225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner} 40325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 40425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner/// getMovi32Value - Return binary encoding of operand for movw/movt. If the 40525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner/// machine operand requires relocation, record the relocation and return zero. 40625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turnerunsigned ARMCodeEmitter::getMovi32Value(const MachineInstr &MI, 40725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const MachineOperand &MO, 40825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned Reloc) { 40925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner assert(((Reloc == ARM::reloc_arm_movt) || (Reloc == ARM::reloc_arm_movw)) 41025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner && "Relocation to this function should be for movt or movw"); 41125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 41225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (MO.isImm()) 41325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return static_cast<unsigned>(MO.getImm()); 41425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else if (MO.isGlobal()) 41525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitGlobalAddress(MO.getGlobal(), Reloc, true, false); 41625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else if (MO.isSymbol()) 41725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitExternalSymbolAddress(MO.getSymbolName(), Reloc); 41825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else if (MO.isMBB()) 41925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitMachineBasicBlock(MO.getMBB(), Reloc); 42025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else { 4212d238fd9871687b1557f15b8878a6cf3e9634b57David 'Digit' Turner#ifndef NDEBUG 42225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner errs() << MO; 42325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner#endif 42425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner llvm_unreachable("Unsupported operand type for movw/movt"); 42525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 42625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return 0; 42725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner} 42825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 42925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner/// getMachineOpValue - Return binary encoding of operand. If the machine 43025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner/// operand requires relocation, record the relocation and return zero. 43125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turnerunsigned ARMCodeEmitter::getMachineOpValue(const MachineInstr &MI, 43225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const MachineOperand &MO) const { 43325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (MO.isReg()) 4342d238fd9871687b1557f15b8878a6cf3e9634b57David 'Digit' Turner return getARMRegisterNumbering(MO.getReg()); 43525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else if (MO.isImm()) 43625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return static_cast<unsigned>(MO.getImm()); 43725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else if (MO.isFPImm()) 43825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return static_cast<unsigned>(MO.getFPImm()->getValueAPF() 43925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner .bitcastToAPInt().getHiBits(32).getLimitedValue()); 44025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else if (MO.isGlobal()) 44125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitGlobalAddress(MO.getGlobal(), ARM::reloc_arm_branch, true, false); 44225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else if (MO.isSymbol()) 44325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitExternalSymbolAddress(MO.getSymbolName(), ARM::reloc_arm_branch); 44425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else if (MO.isCPI()) { 44525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const TargetInstrDesc &TID = MI.getDesc(); 44625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // For VFP load, the immediate offset is multiplied by 4. 44725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned Reloc = ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPLdStFrm) 44825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner ? ARM::reloc_arm_vfp_cp_entry : ARM::reloc_arm_cp_entry; 44925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitConstPoolAddress(MO.getIndex(), Reloc); 45025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } else if (MO.isJTI()) 45125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitJumpTableAddress(MO.getIndex(), ARM::reloc_arm_relative); 45225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else if (MO.isMBB()) 45325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitMachineBasicBlock(MO.getMBB(), ARM::reloc_arm_branch); 45425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else 45525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner llvm_unreachable("Unable to encode MachineOperand!"); 45625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return 0; 45725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner} 45825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 45925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner/// emitGlobalAddress - Emit the specified address to the code stream. 46025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner/// 46125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turnervoid ARMCodeEmitter::emitGlobalAddress(const GlobalValue *GV, unsigned Reloc, 462cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll bool MayNeedFarStub, bool Indirect, 46325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner intptr_t ACPV) const { 464cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll MachineRelocation MR = Indirect 46525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner ? MachineRelocation::getIndirectSymbol(MCE.getCurrentPCOffset(), Reloc, 46625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const_cast<GlobalValue *>(GV), 46725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner ACPV, MayNeedFarStub) 468cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll : MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, 46925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const_cast<GlobalValue *>(GV), ACPV, 4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project MayNeedFarStub); 471cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll MCE.addRelocation(MR); 472cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll} 473cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll 474cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll/// emitExternalSymbolAddress - Arrange for the address of an external symbol to 475cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll/// be emitted to the current location in the function, and allow it to be PC 476cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll/// relative. 477cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Mollvoid ARMCodeEmitter:: 478cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael MollemitExternalSymbolAddress(const char *ES, unsigned Reloc) const { 479cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), 480cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll Reloc, ES)); 481cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll} 482cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll 483cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll/// emitConstPoolAddress - Arrange for the address of an constant pool 484cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll/// to be emitted to the current location in the function, and allow it to be PC 485cf9426292dc19d91bcf11f72d30613f83dbc3d6cRaphael Moll/// relative. 48625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turnervoid ARMCodeEmitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc) const { 48725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Tell JIT emitter we'll resolve the address. 48825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(), 48925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Reloc, CPI, 0, true)); 490b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner} 491b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner 492b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner/// emitJumpTableAddress - Arrange for the address of a jump table to 493b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner/// be emitted to the current location in the function, and allow it to be PC 494b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner/// relative. 495b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turnervoid ARMCodeEmitter:: 496b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' TurneremitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const { 497b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(), 498b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner Reloc, JTIndex, 0, true)); 499b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner} 500b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner 501b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner/// emitMachineBasicBlock - Emit the specified address basic block. 502b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turnervoid ARMCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB, 503b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner unsigned Reloc, 504b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner intptr_t JTBase) const { 505b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), 506b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner Reloc, BB, JTBase)); 507b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner} 508b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner 509b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turnervoid ARMCodeEmitter::emitWordLE(unsigned Binary) { 510b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner DEBUG(errs() << " 0x"; 511b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner errs().write_hex(Binary) << "\n"); 512b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner MCE.emitWordLE(Binary); 513b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner} 514b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner 515b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turnervoid ARMCodeEmitter::emitDWordLE(uint64_t Binary) { 516b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner DEBUG(errs() << " 0x"; 517b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner errs().write_hex(Binary) << "\n"); 518b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner MCE.emitDWordLE(Binary); 519b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner} 520b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner 521b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turnervoid ARMCodeEmitter::emitInstruction(const MachineInstr &MI) { 522b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner DEBUG(errs() << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << MI); 523b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner 524b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner MCE.processDebugLoc(MI.getDebugLoc(), true); 525b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner 526b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner ++NumEmitted; // Keep track of the # of mi's emitted 527b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner switch (MI.getDesc().TSFlags & ARMII::FormMask) { 528b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner default: { 529b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner llvm_unreachable("Unhandled instruction encoding format!"); 530b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner break; 531b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner } 532b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner case ARMII::MiscFrm: 533b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner if (MI.getOpcode() == ARM::LEApcrelJT) { 534b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner // Materialize jumptable address. 535b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner emitLEApcrelJTInstruction(MI); 536b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner break; 537b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner } 538b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner llvm_unreachable("Unhandled instruction encoding!"); 539b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner break; 540b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner case ARMII::Pseudo: 541b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner emitPseudoInstruction(MI); 542b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner break; 543b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner case ARMII::DPFrm: 544b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner case ARMII::DPSoRegFrm: 545b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner emitDataProcessingInstruction(MI); 546b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner break; 547b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner case ARMII::LdFrm: 548b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner case ARMII::StFrm: 549b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner emitLoadStoreInstruction(MI); 550b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner break; 551b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner case ARMII::LdMiscFrm: 552b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner case ARMII::StMiscFrm: 553b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner emitMiscLoadStoreInstruction(MI); 554b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner break; 555b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner case ARMII::LdStMulFrm: 556b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner emitLoadStoreMultipleInstruction(MI); 557b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner break; 558b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner case ARMII::MulFrm: 559b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner emitMulFrmInstruction(MI); 56025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 56125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::ExtFrm: 56225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitExtendInstruction(MI); 56325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 56425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::ArithMiscFrm: 56525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitMiscArithInstruction(MI); 56625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARMII::SatFrm: 56825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitSaturateInstruction(MI); 56925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 57025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::BrFrm: 57125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitBranchInstruction(MI); 57225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 57325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::BrMiscFrm: 57425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitMiscBranchInstruction(MI); 57525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 57625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // VFP instructions. 57725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::VFPUnaryFrm: 57825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::VFPBinaryFrm: 57925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitVFPArithInstruction(MI); 58025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 58125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::VFPConv1Frm: 58225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::VFPConv2Frm: 58325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::VFPConv3Frm: 58425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::VFPConv4Frm: 58525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::VFPConv5Frm: 58625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitVFPConversionInstruction(MI); 58725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 58825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::VFPLdStFrm: 58925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitVFPLoadStoreInstruction(MI); 59025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 59125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::VFPLdStMulFrm: 59225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitVFPLoadStoreMultipleInstruction(MI); 59325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 59425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::VFPMiscFrm: 59525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitMiscInstruction(MI); 59625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 59725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // NEON instructions. 59825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::NGetLnFrm: 59925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::NSetLnFrm: 60025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitNEONLaneInstruction(MI); 60125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 60225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::NDupFrm: 60325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitNEONDupInstruction(MI); 60425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 60525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::N1RegModImmFrm: 60625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitNEON1RegModImmInstruction(MI); 60725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 60825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::N2RegFrm: 60925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitNEON2RegInstruction(MI); 61025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 61125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case ARMII::N3RegFrm: 61225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitNEON3RegInstruction(MI); 61325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 61425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 61525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner MCE.processDebugLoc(MI.getDebugLoc(), false); 61625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner} 61725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 61892c7311b1cb354745ec7b59b0e03910b3fe4c205The Android Open Source Projectvoid ARMCodeEmitter::emitConstantToMemory(unsigned CPI, const Constant *C) { 61992c7311b1cb354745ec7b59b0e03910b3fe4c205The Android Open Source Project DEBUG({ 62092c7311b1cb354745ec7b59b0e03910b3fe4c205The Android Open Source Project errs() << " ** Constant pool #" << CPI << " @ " 62192c7311b1cb354745ec7b59b0e03910b3fe4c205The Android Open Source Project << (void*)MCE.getCurrentPCValue() << " "; 6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (const Function *F = dyn_cast<Function>(C)) 62325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner errs() << F->getName(); 6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project errs() << *C; 62625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner errs() << '\n'; 62725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner }); 62825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 62925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner switch (C->getValueID()) { 63025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner default: { 63125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner llvm_unreachable("Unable to handle this constantpool entry!"); 63225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 63325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 63425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case Value::GlobalVariableVal: { 63525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitGlobalAddress(static_cast<const GlobalValue*>(C), 63625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner ARM::reloc_arm_absolute, isa<Function>(C), false); 63725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitWordLE(0); 63825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 63925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 64025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case Value::ConstantIntVal: { 64125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const ConstantInt *CI = static_cast<const ConstantInt*>(C); 64225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner uint32_t Val = *(uint32_t*)CI->getValue().getRawData(); 64325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitWordLE(Val); 64425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 64525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 64625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case Value::ConstantFPVal: { 64725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const ConstantFP *CFP = static_cast<const ConstantFP*>(C); 64825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (CFP->getType()->isFloatTy()) 64925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitWordLE(CFP->getValueAPF().bitcastToAPInt().getZExtValue()); 65025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else if (CFP->getType()->isDoubleTy()) 65125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitDWordLE(CFP->getValueAPF().bitcastToAPInt().getZExtValue()); 65225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else { 65325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner llvm_unreachable("Unable to handle this constantpool entry!"); 65425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 65725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case Value::ConstantArrayVal: { 65825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const ConstantArray *CA = static_cast<const ConstantArray*>(C); 6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) 66025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitConstantToMemory(CPI, CA->getOperand(i)); 66125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case Value::ConstantVectorVal:{ 6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project //FIXME:emit vector 66525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const ConstantVector *CV = static_cast<const ConstantVector*>(C); 66625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner break; 66725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 67025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return; 67125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner} 6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 67325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turnervoid ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) { 6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned CPI = MI.getOperand(0).getImm(); // CP instruction index. 6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned CPIndex = MI.getOperand(1).getIndex(); // Actual cp entry index. 67625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const MachineConstantPoolEntry &MCPE = (*MCPEs)[CPIndex]; 6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 67825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Remember the CONSTPOOL_ENTRY address for later relocation. 6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project JTI->addConstantPoolEntryAddr(CPI, MCE.getCurrentPCValue()); 68025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 68125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Emit constpool island entry. In most cases, the actual values will be 6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // resolved and relocated after code emission. 68325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (MCPE.isMachineConstantPoolEntry()) { 68425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner ARMConstantPoolValue *ACPV = 6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project static_cast<ARMConstantPoolValue*>(MCPE.Val.MachineCPVal); 68625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 68725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner DEBUG(errs() << " ** ARM constant pool #" << CPI << " @ " 68825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner << (void*)MCE.getCurrentPCValue() << " " << *ACPV << '\n'); 6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 69025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner assert(ACPV->isGlobalValue() && "unsupported constant pool value"); 6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const GlobalValue *GV = ACPV->getGV(); 6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (GV) { 69325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Reloc::Model RelocM = TM.getRelocationModel(); 69425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitGlobalAddress(GV, ARM::reloc_arm_machine_cp_entry, 69525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner isa<Function>(GV), 69625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Subtarget->GVIsIndirectSymbol(GV, RelocM), 69725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner (intptr_t)ACPV); 69825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } else { 69925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitExternalSymbolAddress(ACPV->getSymbol(), ARM::reloc_arm_absolute); 70025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 70125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitWordLE(0); 70225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } else { 70325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitConstantToMemory(CPI, MCPE.Val.ConstVal); 7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 70625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid ARMCodeEmitter::emitMOVi32immInstruction(const MachineInstr &MI) { 7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const MachineOperand &MO0 = MI.getOperand(0); 7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const MachineOperand &MO1 = MI.getOperand(1); 7105ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 7115ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // Emit the 'movw' instruction. 7125ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner unsigned Binary = 0x30 << 20; // mov: Insts{27-20} = 0b00110000 7135ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 7145ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner unsigned Lo16 = getMovi32Value(MI, MO1, ARM::reloc_arm_movw) & 0xFFFF; 7155ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 7165ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // Set the conditional execution predicate. 7175ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner Binary |= II->getPredicate(&MI) << ARMII::CondShift; 7185ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 7195ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // Encode Rd. 7205ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift; 7215ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 7225ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // Encode imm16 as imm4:imm12 7235ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner Binary |= Lo16 & 0xFFF; // Insts{11-0} = imm12 7245ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner Binary |= ((Lo16 >> 12) & 0xF) << 16; // Insts{19-16} = imm4 7255ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner emitWordLE(Binary); 7265ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 7275ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner unsigned Hi16 = getMovi32Value(MI, MO1, ARM::reloc_arm_movt) >> 16; 7285ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // Emit the 'movt' instruction. 7295ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner Binary = 0x34 << 20; // movt: Insts{27-20} = 0b00110100 7305ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 7315ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // Set the conditional execution predicate. 7325ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner Binary |= II->getPredicate(&MI) << ARMII::CondShift; 7335ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 7345ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // Encode Rd. 7355ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift; 7365ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 7375ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // Encode imm16 as imm4:imm1, same as movw above. 7385ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner Binary |= Hi16 & 0xFFF; 7395ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner Binary |= ((Hi16 >> 12) & 0xF) << 16; 7405ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner emitWordLE(Binary); 7415ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner} 7425ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 7435ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turnervoid ARMCodeEmitter::emitMOVi2piecesInstruction(const MachineInstr &MI) { 7445ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner const MachineOperand &MO0 = MI.getOperand(0); 7455ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner const MachineOperand &MO1 = MI.getOperand(1); 7465ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner assert(MO1.isImm() && ARM_AM::isSOImmTwoPartVal(MO1.getImm()) && 7475ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner "Not a valid so_imm value!"); 7485ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO1.getImm()); 7495ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO1.getImm()); 7505ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 7515ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // Emit the 'mov' instruction. 7525ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner unsigned Binary = 0xd << 21; // mov: Insts{24-21} = 0b1101 7535ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 7545ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // Set the conditional execution predicate. 7555ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner Binary |= II->getPredicate(&MI) << ARMII::CondShift; 7565ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 7575ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // Encode Rd. 7585ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift; 7595ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 7605ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // Encode so_imm. 7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Set bit I(25) to identify this is the immediate form of <shifter_op> 7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= 1 << ARMII::I_BitShift; 7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= getMachineSoImmOpValue(V1); 7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project emitWordLE(Binary); 7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Now the 'orr' instruction. 7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary = 0xc << 21; // orr: Insts{24-21} = 0b1100 7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Set the conditional execution predicate. 7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= II->getPredicate(&MI) << ARMII::CondShift; 7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Encode Rd. 7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift; 7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Encode Rn. 7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRnShift; 77725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 77825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Encode so_imm. 77925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Set bit I(25) to identify this is the immediate form of <shifter_op> 78025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= 1 << ARMII::I_BitShift; 78125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= getMachineSoImmOpValue(V2); 7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project emitWordLE(Binary); 7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 784b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner 785b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turnervoid ARMCodeEmitter::emitLEApcrelInstruction(const MachineInstr &MI) { 7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // It's basically add r, pc, (LCPI - $+8) 7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const TargetInstrDesc &TID = MI.getDesc(); 7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 78925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned Binary = 0; 7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7915ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // Set the conditional execution predicate 7925ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner Binary |= II->getPredicate(&MI) << ARMII::CondShift; 7935ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 7945ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // Encode S bit if MI modifies CPSR. 7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= getAddrModeSBit(MI, TID); 7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Encode Rd. 7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift; 7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Encode Rn which is PC. 8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= getARMRegisterNumbering(ARM::PC) << ARMII::RegRnShift; 8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Encode the displacement which is a so_imm. 8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Set bit I(25) to identify this is the immediate form of <shifter_op> 8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= 1 << ARMII::I_BitShift; 8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project emitConstPoolAddress(MI.getOperand(1).getIndex(), ARM::reloc_arm_so_imm_cp_entry); 8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project emitWordLE(Binary); 8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid ARMCodeEmitter::emitLEApcrelJTInstruction(const MachineInstr &MI) { 8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // It's basically add r, pc, (LJTI - $+8) 8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const TargetInstrDesc &TID = MI.getDesc(); 8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Emit the 'add' instruction. 8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned Binary = 0x4 << 21; // add: Insts{24-21} = 0b0100 8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Set the conditional execution predicate 8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= II->getPredicate(&MI) << ARMII::CondShift; 8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Encode S bit if MI modifies CPSR. 8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= getAddrModeSBit(MI, TID); 8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Encode Rd. 8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift; 82792c7311b1cb354745ec7b59b0e03910b3fe4c205The Android Open Source Project 8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Encode Rn which is PC. 8298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= getARMRegisterNumbering(ARM::PC) << ARMII::RegRnShift; 830fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner 831fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner // Encode the displacement. 83225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= 1 << ARMII::I_BitShift; 833fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner emitJumpTableAddress(MI.getOperand(1).getIndex(), ARM::reloc_arm_jt_base); 83425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 83525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitWordLE(Binary); 836fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner} 83725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 83825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turnervoid ARMCodeEmitter::emitPseudoMoveInstruction(const MachineInstr &MI) { 839fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner unsigned Opcode = MI.getDesc().Opcode; 840fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner 841689d1147b1994be1d8e33ee4d1a8ec76742bb4a6Xavier Ducrohet // Part of binary is determined by TableGn. 842689d1147b1994be1d8e33ee4d1a8ec76742bb4a6Xavier Ducrohet unsigned Binary = getBinaryCodeForInstr(MI); 843689d1147b1994be1d8e33ee4d1a8ec76742bb4a6Xavier Ducrohet 844689d1147b1994be1d8e33ee4d1a8ec76742bb4a6Xavier Ducrohet // Set the conditional execution predicate 845689d1147b1994be1d8e33ee4d1a8ec76742bb4a6Xavier Ducrohet Binary |= II->getPredicate(&MI) << ARMII::CondShift; 846689d1147b1994be1d8e33ee4d1a8ec76742bb4a6Xavier Ducrohet 847689d1147b1994be1d8e33ee4d1a8ec76742bb4a6Xavier Ducrohet // Encode S bit if MI modifies CPSR. 848689d1147b1994be1d8e33ee4d1a8ec76742bb4a6Xavier Ducrohet if (Opcode == ARM::MOVsrl_flag || Opcode == ARM::MOVsra_flag) 849689d1147b1994be1d8e33ee4d1a8ec76742bb4a6Xavier Ducrohet Binary |= 1 << ARMII::S_BitShift; 850689d1147b1994be1d8e33ee4d1a8ec76742bb4a6Xavier Ducrohet 851689d1147b1994be1d8e33ee4d1a8ec76742bb4a6Xavier Ducrohet // Encode register def if there is one. 852689d1147b1994be1d8e33ee4d1a8ec76742bb4a6Xavier Ducrohet Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift; 85325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 854fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner // Encode the shift operation. 85525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner switch (Opcode) { 856fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner default: break; 857fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner case ARM::RRX: 858fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner // rrx 859fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner Binary |= 0x6 << 4; 860689d1147b1994be1d8e33ee4d1a8ec76742bb4a6Xavier Ducrohet break; 861689d1147b1994be1d8e33ee4d1a8ec76742bb4a6Xavier Ducrohet case ARM::MOVsrl_flag: 86242074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner // lsr #1 86342074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner Binary |= (0x2 << 4) | (1 << 7); 864fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner break; 865fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner case ARM::MOVsra_flag: 866fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner // asr #1 867fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner Binary |= (0x4 << 4) | (1 << 7); 868fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner break; 8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Encode register Rm. 8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= getMachineOpValue(MI, 1); 8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project emitWordLE(Binary); 8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid ARMCodeEmitter::addPCLabel(unsigned LabelID) { 8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG(errs() << " ** LPC" << LabelID << " @ " 8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project << (void*)MCE.getCurrentPCValue() << '\n'); 8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project JTI->addPCLabelAddr(LabelID, MCE.getCurrentPCValue()); 8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8825ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 8835ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turnervoid ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) { 8845ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner unsigned Opcode = MI.getDesc().Opcode; 8855ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner switch (Opcode) { 8865ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner default: 8875ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner llvm_unreachable("ARMCodeEmitter::emitPseudoInstruction"); 8885ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner case ARM::BX_CALL: 8895ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner case ARM::BMOVPCRX_CALL: 8905ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner case ARM::BXr9_CALL: 8915ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner case ARM::BMOVPCRXr9_CALL: { 8925ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // First emit mov lr, pc 8935ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner unsigned Binary = 0x01a0e00f; 8945ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner Binary |= II->getPredicate(&MI) << ARMII::CondShift; 8955ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner emitWordLE(Binary); 896c005246ed03de874fdc432073ba8e5e8ebfed922David 'Digit' Turner 8975ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // and then emit the branch. 8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project emitMiscBranchInstruction(MI); 8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TargetOpcode::INLINEASM: { 90225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // We allow inline assembler nodes with empty bodies - they can 90325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // implicitly define registers, which is ok for JIT. 90425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (MI.getOperand(0).getSymbolName()[0]) { 905fd59c330bec77e7b9241e478efb1e1c508480d1dDavid 'Digit' Turner report_fatal_error("JIT does not support inline asm!"); 9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 90825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 90925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner case TargetOpcode::PROLOG_LABEL: 9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TargetOpcode::EH_LABEL: 9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project MCE.emitLabel(MI.getOperand(0).getMCSymbol()); 9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TargetOpcode::IMPLICIT_DEF: 9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case TargetOpcode::KILL: 9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Do nothing. 9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM::CONSTPOOL_ENTRY: 9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project emitConstPoolInstruction(MI); 9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM::PICADD: { 9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Remember of the address of the PC label for relocation later. 9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addPCLabel(MI.getOperand(2).getImm()); 9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // PICADD is just an add instruction that implicitly read pc. 9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project emitDataProcessingInstruction(MI, 0, ARM::PC); 9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM::PICLDR: 9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM::PICLDRB: 9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM::PICSTR: 9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM::PICSTRB: { 9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Remember of the address of the PC label for relocation later. 9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addPCLabel(MI.getOperand(2).getImm()); 933cd059b15f2c7df69f4a087bd66900eb172e41d1cDavid 'Digit' Turner // These are just load / store instructions that implicitly read pc. 934cd059b15f2c7df69f4a087bd66900eb172e41d1cDavid 'Digit' Turner emitLoadStoreInstruction(MI, 0, ARM::PC); 935cd059b15f2c7df69f4a087bd66900eb172e41d1cDavid 'Digit' Turner break; 936cd059b15f2c7df69f4a087bd66900eb172e41d1cDavid 'Digit' Turner } 937cd059b15f2c7df69f4a087bd66900eb172e41d1cDavid 'Digit' Turner case ARM::PICLDRH: 938cd059b15f2c7df69f4a087bd66900eb172e41d1cDavid 'Digit' Turner case ARM::PICLDRSH: 939cd059b15f2c7df69f4a087bd66900eb172e41d1cDavid 'Digit' Turner case ARM::PICLDRSB: 940cd059b15f2c7df69f4a087bd66900eb172e41d1cDavid 'Digit' Turner case ARM::PICSTRH: { 941cd059b15f2c7df69f4a087bd66900eb172e41d1cDavid 'Digit' Turner // Remember of the address of the PC label for relocation later. 942cd059b15f2c7df69f4a087bd66900eb172e41d1cDavid 'Digit' Turner addPCLabel(MI.getOperand(2).getImm()); 943cd059b15f2c7df69f4a087bd66900eb172e41d1cDavid 'Digit' Turner // These are just load / store instructions that implicitly read pc. 944cd059b15f2c7df69f4a087bd66900eb172e41d1cDavid 'Digit' Turner emitMiscLoadStoreInstruction(MI, ARM::PC); 945cd059b15f2c7df69f4a087bd66900eb172e41d1cDavid 'Digit' Turner break; 946cd059b15f2c7df69f4a087bd66900eb172e41d1cDavid 'Digit' Turner } 947cd059b15f2c7df69f4a087bd66900eb172e41d1cDavid 'Digit' Turner 9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM::MOVi32imm: 9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Two instructions to materialize a constant. 9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (Subtarget->hasV6T2Ops()) 9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project emitMOVi32immInstruction(MI); 9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project emitMOVi2piecesInstruction(MI); 9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM::LEApcrel: 9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Materialize constantpool index address. 9570b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner emitLEApcrelInstruction(MI); 9580b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner break; 9590b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner case ARM::LEApcrelJT: 9600b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner // Materialize jumptable address. 9610b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner emitLEApcrelJTInstruction(MI); 9620b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner break; 9630b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner case ARM::RRX: 9645ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner case ARM::MOVsrl_flag: 9655ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner case ARM::MOVsra_flag: 9665ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner emitPseudoMoveInstruction(MI); 9675ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner break; 9680b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner } 9690b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner} 9700b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner 9710b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turnerunsigned ARMCodeEmitter::getMachineSoRegOpValue(const MachineInstr &MI, 9722ed457ee5259b236bf39701404897f4c486326e8David 'Digit' Turner const TargetInstrDesc &TID, 9732ed457ee5259b236bf39701404897f4c486326e8David 'Digit' Turner const MachineOperand &MO, 9745ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner unsigned OpIdx) { 9755ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner unsigned Binary = getMachineOpValue(MI, MO); 9765ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 9775ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner const MachineOperand &MO1 = MI.getOperand(OpIdx + 1); 9782ed457ee5259b236bf39701404897f4c486326e8David 'Digit' Turner const MachineOperand &MO2 = MI.getOperand(OpIdx + 2); 9792ed457ee5259b236bf39701404897f4c486326e8David 'Digit' Turner ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm()); 9800b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner 981c6e0caedac5585546cb68605418eedc9e726b44bDavid 'Digit' Turner // Encode the shift opcode. 982c6e0caedac5585546cb68605418eedc9e726b44bDavid 'Digit' Turner unsigned SBits = 0; 983c6e0caedac5585546cb68605418eedc9e726b44bDavid 'Digit' Turner unsigned Rs = MO1.getReg(); 984c6e0caedac5585546cb68605418eedc9e726b44bDavid 'Digit' Turner if (Rs) { 985c6e0caedac5585546cb68605418eedc9e726b44bDavid 'Digit' Turner // Set shift operand (bit[7:4]). 986c6e0caedac5585546cb68605418eedc9e726b44bDavid 'Digit' Turner // LSL - 0001 98718006f77ef9e760c225d1aa0dbbbe9cf5401aa8eJean-Baptiste Queru // LSR - 0011 9882ed457ee5259b236bf39701404897f4c486326e8David 'Digit' Turner // ASR - 0101 9890b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner // ROR - 0111 9900b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner // RRX - 0110 and bit[11:8] clear. 9910b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner switch (SOpc) { 9920b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner default: llvm_unreachable("Unknown shift opc!"); 9930b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner case ARM_AM::lsl: SBits = 0x1; break; 9945ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner case ARM_AM::lsr: SBits = 0x3; break; 9955ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner case ARM_AM::asr: SBits = 0x5; break; 9965ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner case ARM_AM::ror: SBits = 0x7; break; 9970b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner case ARM_AM::rrx: SBits = 0x6; break; 9980b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner } 9990b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner } else { 10000b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner // Set shift operand (bit[6:4]). 10010b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner // LSL - 000 10020b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner // LSR - 010 10030b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner // ASR - 100 10040b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner // ROR - 110 10050b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner switch (SOpc) { 10060b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner default: llvm_unreachable("Unknown shift opc!"); 10070b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner case ARM_AM::lsl: SBits = 0x0; break; 1008c480cca8d2007f5df62a7431beda310911b963e6David 'Digit' Turner case ARM_AM::lsr: SBits = 0x2; break; 1009c480cca8d2007f5df62a7431beda310911b963e6David 'Digit' Turner case ARM_AM::asr: SBits = 0x4; break; 1010c480cca8d2007f5df62a7431beda310911b963e6David 'Digit' Turner case ARM_AM::ror: SBits = 0x6; break; 1011c480cca8d2007f5df62a7431beda310911b963e6David 'Digit' Turner } 1012c480cca8d2007f5df62a7431beda310911b963e6David 'Digit' Turner } 1013c480cca8d2007f5df62a7431beda310911b963e6David 'Digit' Turner Binary |= SBits << 4; 1014c480cca8d2007f5df62a7431beda310911b963e6David 'Digit' Turner if (SOpc == ARM_AM::rrx) 1015c480cca8d2007f5df62a7431beda310911b963e6David 'Digit' Turner return Binary; 1016c480cca8d2007f5df62a7431beda310911b963e6David 'Digit' Turner 1017c480cca8d2007f5df62a7431beda310911b963e6David 'Digit' Turner // Encode the shift operation Rs or shift_imm (except rrx). 1018c480cca8d2007f5df62a7431beda310911b963e6David 'Digit' Turner if (Rs) { 1019c480cca8d2007f5df62a7431beda310911b963e6David 'Digit' Turner // Encode Rs bit[11:8]. 102048a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0); 102148a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner return Binary | (getARMRegisterNumbering(Rs) << ARMII::RegRsShift); 102248a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner } 102348a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner 102448a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner // Encode shift_imm bit[11:7]. 102548a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7; 102648a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner} 102748a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner 102848a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turnerunsigned ARMCodeEmitter::getMachineSoImmOpValue(unsigned SoImm) { 102948a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner int SoImmVal = ARM_AM::getSOImmVal(SoImm); 103048a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner assert(SoImmVal != -1 && "Not a valid so_imm value!"); 103148a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner 103248a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner // Encode rotate_imm. 103348a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner unsigned Binary = (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1) 103448a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner << ARMII::SoRotImmShift; 103548a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner 103648a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner // Encode immed_8. 103748a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal); 103848a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner return Binary; 103948a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner} 104048a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner 104148a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turnerunsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI, 104248a3c66361158678f476fc7c2eca2bef025eae62David 'Digit' Turner const TargetInstrDesc &TID) const { 10430b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner for (unsigned i = MI.getNumOperands(), e = TID.getNumOperands(); i >= e; --i){ 10445f64b873605baa5519211b0d47a53c93df9d4868David 'Digit' Turner const MachineOperand &MO = MI.getOperand(i-1); 10455f64b873605baa5519211b0d47a53c93df9d4868David 'Digit' Turner if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR) 10465f64b873605baa5519211b0d47a53c93df9d4868David 'Digit' Turner return 1 << ARMII::S_BitShift; 10475f64b873605baa5519211b0d47a53c93df9d4868David 'Digit' Turner } 10485f64b873605baa5519211b0d47a53c93df9d4868David 'Digit' Turner return 0; 10495f64b873605baa5519211b0d47a53c93df9d4868David 'Digit' Turner} 10505f64b873605baa5519211b0d47a53c93df9d4868David 'Digit' Turner 105140841b2d221273a08abfe20824e7631211ade31dDavid 'Digit' Turnervoid ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, 105240841b2d221273a08abfe20824e7631211ade31dDavid 'Digit' Turner unsigned ImplicitRd, 105340841b2d221273a08abfe20824e7631211ade31dDavid 'Digit' Turner unsigned ImplicitRn) { 105440841b2d221273a08abfe20824e7631211ade31dDavid 'Digit' Turner const TargetInstrDesc &TID = MI.getDesc(); 105540841b2d221273a08abfe20824e7631211ade31dDavid 'Digit' Turner 105640841b2d221273a08abfe20824e7631211ade31dDavid 'Digit' Turner // Part of binary is determined by TableGn. 105740841b2d221273a08abfe20824e7631211ade31dDavid 'Digit' Turner unsigned Binary = getBinaryCodeForInstr(MI); 10580b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner 10590b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner // Set the conditional execution predicate 10600b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner Binary |= II->getPredicate(&MI) << ARMII::CondShift; 10610b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner 10620b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner // Encode S bit if MI modifies CPSR. 10630b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner Binary |= getAddrModeSBit(MI, TID); 10640b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner 1065fd59c330bec77e7b9241e478efb1e1c508480d1dDavid 'Digit' Turner // Encode register def if there is one. 1066fd59c330bec77e7b9241e478efb1e1c508480d1dDavid 'Digit' Turner unsigned NumDefs = TID.getNumDefs(); 1067fd59c330bec77e7b9241e478efb1e1c508480d1dDavid 'Digit' Turner unsigned OpIdx = 0; 1068fd59c330bec77e7b9241e478efb1e1c508480d1dDavid 'Digit' Turner if (NumDefs) 1069fd59c330bec77e7b9241e478efb1e1c508480d1dDavid 'Digit' Turner Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; 1070fd59c330bec77e7b9241e478efb1e1c508480d1dDavid 'Digit' Turner else if (ImplicitRd) 1071fd59c330bec77e7b9241e478efb1e1c508480d1dDavid 'Digit' Turner // Special handling for implicit use (e.g. PC). 1072fd59c330bec77e7b9241e478efb1e1c508480d1dDavid 'Digit' Turner Binary |= (getARMRegisterNumbering(ImplicitRd) << ARMII::RegRdShift); 1073fd59c330bec77e7b9241e478efb1e1c508480d1dDavid 'Digit' Turner 1074fd59c330bec77e7b9241e478efb1e1c508480d1dDavid 'Digit' Turner if (TID.Opcode == ARM::MOVi16) { 1075fd59c330bec77e7b9241e478efb1e1c508480d1dDavid 'Digit' Turner // Get immediate from MI. 1076fd59c330bec77e7b9241e478efb1e1c508480d1dDavid 'Digit' Turner unsigned Lo16 = getMovi32Value(MI, MI.getOperand(OpIdx), 1077fd59c330bec77e7b9241e478efb1e1c508480d1dDavid 'Digit' Turner ARM::reloc_arm_movw); 1078fd59c330bec77e7b9241e478efb1e1c508480d1dDavid 'Digit' Turner // Encode imm which is the same as in emitMOVi32immInstruction(). 10790b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner Binary |= Lo16 & 0xFFF; 10800b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner Binary |= ((Lo16 >> 12) & 0xF) << 16; 10810b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner emitWordLE(Binary); 10820b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner return; 10830b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner } else if(TID.Opcode == ARM::MOVTi16) { 10840b0194940523fa3f318c380d0693907bd522241cDavid 'Digit' Turner unsigned Hi16 = (getMovi32Value(MI, MI.getOperand(OpIdx), 10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARM::reloc_arm_movt) >> 16); 1086b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner Binary |= Hi16 & 0xFFF; 10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= ((Hi16 >> 12) & 0xF) << 16; 1088b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner emitWordLE(Binary); 10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 1090b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner } else if ((TID.Opcode == ARM::BFC) || (TID.Opcode == ARM::BFI)) { 10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t v = ~MI.getOperand(2).getImm(); 1092b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner int32_t lsb = CountTrailingZeros_32(v); 1093b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner int32_t msb = (32 - CountLeadingZeros_32(v)) - 1; 1094b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner // Instr{20-16} = msb, Instr{11-7} = lsb 1095b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner Binary |= (msb & 0x1F) << 16; 10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= (lsb & 0x1F) << 7; 1097b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner emitWordLE(Binary); 109842074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner return; 109942074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner } else if ((TID.Opcode == ARM::UBFX) || (TID.Opcode == ARM::SBFX)) { 1100fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner // Encode Rn in Instr{0-3} 1101fbcab322c2a12bfe49d0faaef91fccdc7bb97d4eDavid 'Digit' Turner Binary |= getMachineOpValue(MI, OpIdx++); 1102b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner 1103b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner uint32_t lsb = MI.getOperand(OpIdx++).getImm(); 11042f7bb38681802b4cf6f83ea97fddcab469224f93David Turner uint32_t widthm1 = MI.getOperand(OpIdx++).getImm() - 1; 1105b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner 1106b64325d15d9e767c652491414c95f4fc148b0211David 'Digit' Turner // Instr{20-16} = widthm1, Instr{11-7} = lsb 11072f7bb38681802b4cf6f83ea97fddcab469224f93David Turner Binary |= (widthm1 & 0x1F) << 16; 11082f7bb38681802b4cf6f83ea97fddcab469224f93David Turner Binary |= (lsb & 0x1F) << 7; 11092f7bb38681802b4cf6f83ea97fddcab469224f93David Turner emitWordLE(Binary); 11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // If this is a two-address operand, skip it. e.g. MOVCCr operand 1. 11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) 11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ++OpIdx; 11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Encode first non-shifter register operand if there is one. 11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bool isUnary = TID.TSFlags & ARMII::UnaryDP; 11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!isUnary) { 11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ImplicitRn) 11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Special handling for implicit use (e.g. PC). 11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= (getARMRegisterNumbering(ImplicitRn) << ARMII::RegRnShift); 11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else { 11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRnShift; 11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ++OpIdx; 11262ed457ee5259b236bf39701404897f4c486326e8David 'Digit' Turner } 11272ed457ee5259b236bf39701404897f4c486326e8David 'Digit' Turner } 11282ed457ee5259b236bf39701404897f4c486326e8David 'Digit' Turner 11295ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // Encode shifter operand. 11302ed457ee5259b236bf39701404897f4c486326e8David 'Digit' Turner const MachineOperand &MO = MI.getOperand(OpIdx); 11312ed457ee5259b236bf39701404897f4c486326e8David 'Digit' Turner if ((TID.TSFlags & ARMII::FormMask) == ARMII::DPSoRegFrm) { 11322ed457ee5259b236bf39701404897f4c486326e8David 'Digit' Turner // Encode SoReg. 11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project emitWordLE(Binary | getMachineSoRegOpValue(MI, TID, MO, OpIdx)); 11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (MO.isReg()) { 11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Encode register Rm. 11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project emitWordLE(Binary | getARMRegisterNumbering(MO.getReg())); 11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project // Encode so_imm. 11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Binary |= getMachineSoImmOpValue((unsigned)MO.getImm()); 11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project emitWordLE(Binary); 11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 114942074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turnervoid ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI, 115042074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner unsigned ImplicitRd, 115142074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner unsigned ImplicitRn) { 115242074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner const TargetInstrDesc &TID = MI.getDesc(); 115342074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner unsigned Form = TID.TSFlags & ARMII::FormMask; 115442074e5e184aed78dee0efb14d7376325516c070David 'Digit' Turner bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0; 115525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 115625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Part of binary is determined by TableGn. 115725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned Binary = getBinaryCodeForInstr(MI); 115825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 115925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // If this is an LDRi12, STRi12 or LDRcp, nothing more needs be done. 116025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (MI.getOpcode() == ARM::LDRi12 || MI.getOpcode() == ARM::LDRcp || 116125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner MI.getOpcode() == ARM::STRi12 || MI.getOpcode() == ARM::LDRBi12 || 116225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner MI.getOpcode() == ARM::STRBi12) { 116325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitWordLE(Binary); 116425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return; 116525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 116625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 116725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Set the conditional execution predicate 116825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= II->getPredicate(&MI) << ARMII::CondShift; 116925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 1170689d1147b1994be1d8e33ee4d1a8ec76742bb4a6Xavier Ducrohet unsigned OpIdx = 0; 117125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 117225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Operand 0 of a pre- and post-indexed store is the address base 117325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // writeback. Skip it. 117425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner bool Skipped = false; 117525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (IsPrePost && Form == ARMII::StFrm) { 117625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner ++OpIdx; 117725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Skipped = true; 117825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 117925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 118025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Set first operand 118125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (ImplicitRd) 118225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Special handling for implicit use (e.g. PC). 118325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= (getARMRegisterNumbering(ImplicitRd) << ARMII::RegRdShift); 118425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else 118525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; 118625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 118725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Set second operand 118825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (ImplicitRn) 118925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Special handling for implicit use (e.g. PC). 119025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= (getARMRegisterNumbering(ImplicitRn) << ARMII::RegRnShift); 119125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else 119225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; 119325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 119425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // If this is a two-address operand, skip it. e.g. LDR_PRE. 119525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) 119625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner ++OpIdx; 119725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 119825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const MachineOperand &MO2 = MI.getOperand(OpIdx); 119925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned AM2Opc = (ImplicitRn == ARM::PC) 120025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner ? 0 : MI.getOperand(OpIdx+1).getImm(); 120125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 120225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Set bit U(23) according to sign of immed value (positive or negative). 120325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= ((ARM_AM::getAM2Op(AM2Opc) == ARM_AM::add ? 1 : 0) << 120425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner ARMII::U_BitShift); 120525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (!MO2.getReg()) { // is immediate 120625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (ARM_AM::getAM2Offset(AM2Opc)) 120725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Set the value of offset_12 field 120825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= ARM_AM::getAM2Offset(AM2Opc); 120925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner emitWordLE(Binary); 121025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner return; 121125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 121225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 121325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Set bit I(25), because this is not in immediate encoding. 121425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= 1 << ARMII::I_BitShift; 121525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner assert(TargetRegisterInfo::isPhysicalRegister(MO2.getReg())); 121625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Set bit[3:0] to the corresponding Rm register 121725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= getARMRegisterNumbering(MO2.getReg()); 121825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 121925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // If this instr is in scaled register offset/index instruction, set 122025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // shift_immed(bit[11:7]) and shift(bit[6:5]) fields. 122125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (unsigned ShImm = ARM_AM::getAM2Offset(AM2Opc)) { 122225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= getShiftOp(AM2Opc) << ARMII::ShiftImmShift; // shift 122325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= ShImm << ARMII::ShiftShift; // shift_immed 122425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 122525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 1226adc34fb9e9ad0700e9752ca67174c68925ca0c71David 'Digit' Turner emitWordLE(Binary); 1227adc34fb9e9ad0700e9752ca67174c68925ca0c71David 'Digit' Turner} 1228adc34fb9e9ad0700e9752ca67174c68925ca0c71David 'Digit' Turner 1229adc34fb9e9ad0700e9752ca67174c68925ca0c71David 'Digit' Turnervoid ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI, 1230adc34fb9e9ad0700e9752ca67174c68925ca0c71David 'Digit' Turner unsigned ImplicitRn) { 1231adc34fb9e9ad0700e9752ca67174c68925ca0c71David 'Digit' Turner const TargetInstrDesc &TID = MI.getDesc(); 1232adc34fb9e9ad0700e9752ca67174c68925ca0c71David 'Digit' Turner unsigned Form = TID.TSFlags & ARMII::FormMask; 1233adc34fb9e9ad0700e9752ca67174c68925ca0c71David 'Digit' Turner bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0; 1234adc34fb9e9ad0700e9752ca67174c68925ca0c71David 'Digit' Turner 1235adc34fb9e9ad0700e9752ca67174c68925ca0c71David 'Digit' Turner // Part of binary is determined by TableGn. 1236adc34fb9e9ad0700e9752ca67174c68925ca0c71David 'Digit' Turner unsigned Binary = getBinaryCodeForInstr(MI); 123725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 123825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Set the conditional execution predicate 123925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= II->getPredicate(&MI) << ARMII::CondShift; 124025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 124125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned OpIdx = 0; 124225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 124325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Operand 0 of a pre- and post-indexed store is the address base 124425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // writeback. Skip it. 124525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner bool Skipped = false; 124625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (IsPrePost && Form == ARMII::StMiscFrm) { 124725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner ++OpIdx; 124825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Skipped = true; 124925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner } 125025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 125125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Set first operand 125225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; 125325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 125425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Skip LDRD and STRD's second operand. 125525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (TID.Opcode == ARM::LDRD || TID.Opcode == ARM::STRD) 125625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner ++OpIdx; 1257adc34fb9e9ad0700e9752ca67174c68925ca0c71David 'Digit' Turner 125825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Set second operand 125925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (ImplicitRn) 126025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // Special handling for implicit use (e.g. PC). 126125eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= (getARMRegisterNumbering(ImplicitRn) << ARMII::RegRnShift); 126225eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner else 126325eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; 126425eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 126525eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner // If this is a two-address operand, skip it. e.g. LDRH_POST. 126625eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) 126725eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner ++OpIdx; 126825eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner 126925eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner const MachineOperand &MO2 = MI.getOperand(OpIdx); 127025eb6557b94da066d6e137c07aeced39badf5aa6David 'Digit' Turner unsigned AM3Opc = (ImplicitRn == ARM::PC) 127172d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet ? 0 : MI.getOperand(OpIdx+1).getImm(); 1272d899918690d5e392897e001abfb00b151ba2b13eSiva Velusamy 1273d899918690d5e392897e001abfb00b151ba2b13eSiva Velusamy // Set bit U(23) according to sign of immed value (positive or negative) 1274d899918690d5e392897e001abfb00b151ba2b13eSiva Velusamy Binary |= ((ARM_AM::getAM3Op(AM3Opc) == ARM_AM::add ? 1 : 0) << 1275d899918690d5e392897e001abfb00b151ba2b13eSiva Velusamy ARMII::U_BitShift); 1276d899918690d5e392897e001abfb00b151ba2b13eSiva Velusamy 1277d899918690d5e392897e001abfb00b151ba2b13eSiva Velusamy // If this instr is in register offset/index encoding, set bit[3:0] 1278d899918690d5e392897e001abfb00b151ba2b13eSiva Velusamy // to the corresponding Rm register. 1279d899918690d5e392897e001abfb00b151ba2b13eSiva Velusamy if (MO2.getReg()) { 128072d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet Binary |= getARMRegisterNumbering(MO2.getReg()); 128172d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet emitWordLE(Binary); 128272d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet return; 128372d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet } 128472d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet 128572d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet // This instr is in immediate offset/index encoding, set bit 22 to 1. 128672d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet Binary |= 1 << ARMII::AM3_I_BitShift; 128772d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet if (unsigned ImmOffs = ARM_AM::getAM3Offset(AM3Opc)) { 128872d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet // Set operands 128972d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet Binary |= (ImmOffs >> 4) << ARMII::ImmHiShift; // immedH 129072d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet Binary |= (ImmOffs & 0xF); // immedL 129172d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet } 129272d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet 129372d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet emitWordLE(Binary); 129472d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet} 129572d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet 129672d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohetstatic unsigned getAddrModeUPBits(unsigned Mode) { 129772d561178e62b74923cfe3bc0faa59bcb07c57c3Xavier Ducrohet unsigned Binary = 0; 1298d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine 1299d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine // Set addressing mode by modifying bits U(23) and P(24) 1300d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine // IA - Increment after - bit U = 1 and bit P = 0 13015ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner // IB - Increment before - bit U = 1 and bit P = 1 1302d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine // DA - Decrement after - bit U = 0 and bit P = 0 1303873c3cb5688092d2822837511cfb2b330d265801Vladimir Chtchetkine // DB - Decrement before - bit U = 0 and bit P = 1 1304873c3cb5688092d2822837511cfb2b330d265801Vladimir Chtchetkine switch (Mode) { 1305873c3cb5688092d2822837511cfb2b330d265801Vladimir Chtchetkine default: llvm_unreachable("Unknown addressing sub-mode!"); 1306873c3cb5688092d2822837511cfb2b330d265801Vladimir Chtchetkine case ARM_AM::da: break; 1307873c3cb5688092d2822837511cfb2b330d265801Vladimir Chtchetkine case ARM_AM::db: Binary |= 0x1 << ARMII::P_BitShift; break; 1308873c3cb5688092d2822837511cfb2b330d265801Vladimir Chtchetkine case ARM_AM::ia: Binary |= 0x1 << ARMII::U_BitShift; break; 1309873c3cb5688092d2822837511cfb2b330d265801Vladimir Chtchetkine case ARM_AM::ib: Binary |= 0x3 << ARMII::U_BitShift; break; 1310873c3cb5688092d2822837511cfb2b330d265801Vladimir Chtchetkine } 1311873c3cb5688092d2822837511cfb2b330d265801Vladimir Chtchetkine 13125ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner return Binary; 13135ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner} 13145ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turner 13155ea914899e5dbef4e8a7454b40a3c6648173f086David 'Digit' Turnervoid ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) { 1316 const TargetInstrDesc &TID = MI.getDesc(); 1317 bool IsUpdating = (TID.TSFlags & ARMII::IndexModeMask) != 0; 1318 1319 // Part of binary is determined by TableGn. 1320 unsigned Binary = getBinaryCodeForInstr(MI); 1321 1322 // Set the conditional execution predicate 1323 Binary |= II->getPredicate(&MI) << ARMII::CondShift; 1324 1325 // Skip operand 0 of an instruction with base register update. 1326 unsigned OpIdx = 0; 1327 if (IsUpdating) 1328 ++OpIdx; 1329 1330 // Set base address operand 1331 Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; 1332 1333 // Set addressing mode by modifying bits U(23) and P(24) 1334 ARM_AM::AMSubMode Mode = ARM_AM::getLoadStoreMultipleSubMode(MI.getOpcode()); 1335 Binary |= getAddrModeUPBits(ARM_AM::getAM4SubMode(Mode)); 1336 1337 // Set bit W(21) 1338 if (IsUpdating) 1339 Binary |= 0x1 << ARMII::W_BitShift; 1340 1341 // Set registers 1342 for (unsigned i = OpIdx+2, e = MI.getNumOperands(); i != e; ++i) { 1343 const MachineOperand &MO = MI.getOperand(i); 1344 if (!MO.isReg() || MO.isImplicit()) 1345 break; 1346 unsigned RegNum = getARMRegisterNumbering(MO.getReg()); 1347 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && 1348 RegNum < 16); 1349 Binary |= 0x1 << RegNum; 1350 } 1351 1352 emitWordLE(Binary); 1353} 1354 1355void ARMCodeEmitter::emitMulFrmInstruction(const MachineInstr &MI) { 1356 const TargetInstrDesc &TID = MI.getDesc(); 1357 1358 // Part of binary is determined by TableGn. 1359 unsigned Binary = getBinaryCodeForInstr(MI); 1360 1361 // Set the conditional execution predicate 1362 Binary |= II->getPredicate(&MI) << ARMII::CondShift; 1363 1364 // Encode S bit if MI modifies CPSR. 1365 Binary |= getAddrModeSBit(MI, TID); 1366 1367 // 32x32->64bit operations have two destination registers. The number 1368 // of register definitions will tell us if that's what we're dealing with. 1369 unsigned OpIdx = 0; 1370 if (TID.getNumDefs() == 2) 1371 Binary |= getMachineOpValue (MI, OpIdx++) << ARMII::RegRdLoShift; 1372 1373 // Encode Rd 1374 Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdHiShift; 1375 1376 // Encode Rm 1377 Binary |= getMachineOpValue(MI, OpIdx++); 1378 1379 // Encode Rs 1380 Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRsShift; 1381 1382 // Many multiple instructions (e.g. MLA) have three src operands. Encode 1383 // it as Rn (for multiply, that's in the same offset as RdLo. 1384 if (TID.getNumOperands() > OpIdx && 1385 !TID.OpInfo[OpIdx].isPredicate() && 1386 !TID.OpInfo[OpIdx].isOptionalDef()) 1387 Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRdLoShift; 1388 1389 emitWordLE(Binary); 1390} 1391 1392void ARMCodeEmitter::emitExtendInstruction(const MachineInstr &MI) { 1393 const TargetInstrDesc &TID = MI.getDesc(); 1394 1395 // Part of binary is determined by TableGn. 1396 unsigned Binary = getBinaryCodeForInstr(MI); 1397 1398 // Set the conditional execution predicate 1399 Binary |= II->getPredicate(&MI) << ARMII::CondShift; 1400 1401 unsigned OpIdx = 0; 1402 1403 // Encode Rd 1404 Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; 1405 1406 const MachineOperand &MO1 = MI.getOperand(OpIdx++); 1407 const MachineOperand &MO2 = MI.getOperand(OpIdx); 1408 if (MO2.isReg()) { 1409 // Two register operand form. 1410 // Encode Rn. 1411 Binary |= getMachineOpValue(MI, MO1) << ARMII::RegRnShift; 1412 1413 // Encode Rm. 1414 Binary |= getMachineOpValue(MI, MO2); 1415 ++OpIdx; 1416 } else { 1417 Binary |= getMachineOpValue(MI, MO1); 1418 } 1419 1420 // Encode rot imm (0, 8, 16, or 24) if it has a rotate immediate operand. 1421 if (MI.getOperand(OpIdx).isImm() && 1422 !TID.OpInfo[OpIdx].isPredicate() && 1423 !TID.OpInfo[OpIdx].isOptionalDef()) 1424 Binary |= (getMachineOpValue(MI, OpIdx) / 8) << ARMII::ExtRotImmShift; 1425 1426 emitWordLE(Binary); 1427} 1428 1429void ARMCodeEmitter::emitMiscArithInstruction(const MachineInstr &MI) { 1430 const TargetInstrDesc &TID = MI.getDesc(); 1431 1432 // Part of binary is determined by TableGn. 1433 unsigned Binary = getBinaryCodeForInstr(MI); 1434 1435 // Set the conditional execution predicate 1436 Binary |= II->getPredicate(&MI) << ARMII::CondShift; 1437 1438 unsigned OpIdx = 0; 1439 1440 // Encode Rd 1441 Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; 1442 1443 const MachineOperand &MO = MI.getOperand(OpIdx++); 1444 if (OpIdx == TID.getNumOperands() || 1445 TID.OpInfo[OpIdx].isPredicate() || 1446 TID.OpInfo[OpIdx].isOptionalDef()) { 1447 // Encode Rm and it's done. 1448 Binary |= getMachineOpValue(MI, MO); 1449 emitWordLE(Binary); 1450 return; 1451 } 1452 1453 // Encode Rn. 1454 Binary |= getMachineOpValue(MI, MO) << ARMII::RegRnShift; 1455 1456 // Encode Rm. 1457 Binary |= getMachineOpValue(MI, OpIdx++); 1458 1459 // Encode shift_imm. 1460 unsigned ShiftAmt = MI.getOperand(OpIdx).getImm(); 1461 if (TID.Opcode == ARM::PKHTB) { 1462 assert(ShiftAmt != 0 && "PKHTB shift_imm is 0!"); 1463 if (ShiftAmt == 32) 1464 ShiftAmt = 0; 1465 } 1466 assert(ShiftAmt < 32 && "shift_imm range is 0 to 31!"); 1467 Binary |= ShiftAmt << ARMII::ShiftShift; 1468 1469 emitWordLE(Binary); 1470} 1471 1472void ARMCodeEmitter::emitSaturateInstruction(const MachineInstr &MI) { 1473 const TargetInstrDesc &TID = MI.getDesc(); 1474 1475 // Part of binary is determined by TableGen. 1476 unsigned Binary = getBinaryCodeForInstr(MI); 1477 1478 // Set the conditional execution predicate 1479 Binary |= II->getPredicate(&MI) << ARMII::CondShift; 1480 1481 // Encode Rd 1482 Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift; 1483 1484 // Encode saturate bit position. 1485 unsigned Pos = MI.getOperand(1).getImm(); 1486 if (TID.Opcode == ARM::SSAT || TID.Opcode == ARM::SSAT16) 1487 Pos -= 1; 1488 assert((Pos < 16 || (Pos < 32 && 1489 TID.Opcode != ARM::SSAT16 && 1490 TID.Opcode != ARM::USAT16)) && 1491 "saturate bit position out of range"); 1492 Binary |= Pos << 16; 1493 1494 // Encode Rm 1495 Binary |= getMachineOpValue(MI, 2); 1496 1497 // Encode shift_imm. 1498 if (TID.getNumOperands() == 4) { 1499 unsigned ShiftOp = MI.getOperand(3).getImm(); 1500 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp); 1501 if (Opc == ARM_AM::asr) 1502 Binary |= (1 << 6); 1503 unsigned ShiftAmt = MI.getOperand(3).getImm(); 1504 if (ShiftAmt == 32 && Opc == ARM_AM::asr) 1505 ShiftAmt = 0; 1506 assert(ShiftAmt < 32 && "shift_imm range is 0 to 31!"); 1507 Binary |= ShiftAmt << ARMII::ShiftShift; 1508 } 1509 1510 emitWordLE(Binary); 1511} 1512 1513void ARMCodeEmitter::emitBranchInstruction(const MachineInstr &MI) { 1514 const TargetInstrDesc &TID = MI.getDesc(); 1515 1516 if (TID.Opcode == ARM::TPsoft) { 1517 llvm_unreachable("ARM::TPsoft FIXME"); // FIXME 1518 } 1519 1520 // Part of binary is determined by TableGn. 1521 unsigned Binary = getBinaryCodeForInstr(MI); 1522 1523 // Set the conditional execution predicate 1524 Binary |= II->getPredicate(&MI) << ARMII::CondShift; 1525 1526 // Set signed_immed_24 field 1527 Binary |= getMachineOpValue(MI, 0); 1528 1529 emitWordLE(Binary); 1530} 1531 1532void ARMCodeEmitter::emitInlineJumpTable(unsigned JTIndex) { 1533 // Remember the base address of the inline jump table. 1534 uintptr_t JTBase = MCE.getCurrentPCValue(); 1535 JTI->addJumpTableBaseAddr(JTIndex, JTBase); 1536 DEBUG(errs() << " ** Jump Table #" << JTIndex << " @ " << (void*)JTBase 1537 << '\n'); 1538 1539 // Now emit the jump table entries. 1540 const std::vector<MachineBasicBlock*> &MBBs = (*MJTEs)[JTIndex].MBBs; 1541 for (unsigned i = 0, e = MBBs.size(); i != e; ++i) { 1542 if (IsPIC) 1543 // DestBB address - JT base. 1544 emitMachineBasicBlock(MBBs[i], ARM::reloc_arm_pic_jt, JTBase); 1545 else 1546 // Absolute DestBB address. 1547 emitMachineBasicBlock(MBBs[i], ARM::reloc_arm_absolute); 1548 emitWordLE(0); 1549 } 1550} 1551 1552void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) { 1553 const TargetInstrDesc &TID = MI.getDesc(); 1554 1555 // Handle jump tables. 1556 if (TID.Opcode == ARM::BR_JTr || TID.Opcode == ARM::BR_JTadd) { 1557 // First emit a ldr pc, [] instruction. 1558 emitDataProcessingInstruction(MI, ARM::PC); 1559 1560 // Then emit the inline jump table. 1561 unsigned JTIndex = 1562 (TID.Opcode == ARM::BR_JTr) 1563 ? MI.getOperand(1).getIndex() : MI.getOperand(2).getIndex(); 1564 emitInlineJumpTable(JTIndex); 1565 return; 1566 } else if (TID.Opcode == ARM::BR_JTm) { 1567 // First emit a ldr pc, [] instruction. 1568 emitLoadStoreInstruction(MI, ARM::PC); 1569 1570 // Then emit the inline jump table. 1571 emitInlineJumpTable(MI.getOperand(3).getIndex()); 1572 return; 1573 } 1574 1575 // Part of binary is determined by TableGn. 1576 unsigned Binary = getBinaryCodeForInstr(MI); 1577 1578 // Set the conditional execution predicate 1579 Binary |= II->getPredicate(&MI) << ARMII::CondShift; 1580 1581 if (TID.Opcode == ARM::BX_RET || TID.Opcode == ARM::MOVPCLR) 1582 // The return register is LR. 1583 Binary |= getARMRegisterNumbering(ARM::LR); 1584 else 1585 // otherwise, set the return register 1586 Binary |= getMachineOpValue(MI, 0); 1587 1588 emitWordLE(Binary); 1589} 1590 1591static unsigned encodeVFPRd(const MachineInstr &MI, unsigned OpIdx) { 1592 unsigned RegD = MI.getOperand(OpIdx).getReg(); 1593 unsigned Binary = 0; 1594 bool isSPVFP = ARM::SPRRegisterClass->contains(RegD); 1595 RegD = getARMRegisterNumbering(RegD); 1596 if (!isSPVFP) { 1597 Binary |= (RegD & 0x0F) << ARMII::RegRdShift; 1598 Binary |= ((RegD & 0x10) >> 4) << ARMII::D_BitShift; 1599 } else { 1600 Binary |= ((RegD & 0x1E) >> 1) << ARMII::RegRdShift; 1601 Binary |= (RegD & 0x01) << ARMII::D_BitShift; 1602 } 1603 return Binary; 1604} 1605 1606static unsigned encodeVFPRn(const MachineInstr &MI, unsigned OpIdx) { 1607 unsigned RegN = MI.getOperand(OpIdx).getReg(); 1608 unsigned Binary = 0; 1609 bool isSPVFP = ARM::SPRRegisterClass->contains(RegN); 1610 RegN = getARMRegisterNumbering(RegN); 1611 if (!isSPVFP) { 1612 Binary |= (RegN & 0x0F) << ARMII::RegRnShift; 1613 Binary |= ((RegN & 0x10) >> 4) << ARMII::N_BitShift; 1614 } else { 1615 Binary |= ((RegN & 0x1E) >> 1) << ARMII::RegRnShift; 1616 Binary |= (RegN & 0x01) << ARMII::N_BitShift; 1617 } 1618 return Binary; 1619} 1620 1621static unsigned encodeVFPRm(const MachineInstr &MI, unsigned OpIdx) { 1622 unsigned RegM = MI.getOperand(OpIdx).getReg(); 1623 unsigned Binary = 0; 1624 bool isSPVFP = ARM::SPRRegisterClass->contains(RegM); 1625 RegM = getARMRegisterNumbering(RegM); 1626 if (!isSPVFP) { 1627 Binary |= (RegM & 0x0F); 1628 Binary |= ((RegM & 0x10) >> 4) << ARMII::M_BitShift; 1629 } else { 1630 Binary |= ((RegM & 0x1E) >> 1); 1631 Binary |= (RegM & 0x01) << ARMII::M_BitShift; 1632 } 1633 return Binary; 1634} 1635 1636void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) { 1637 const TargetInstrDesc &TID = MI.getDesc(); 1638 1639 // Part of binary is determined by TableGn. 1640 unsigned Binary = getBinaryCodeForInstr(MI); 1641 1642 // Set the conditional execution predicate 1643 Binary |= II->getPredicate(&MI) << ARMII::CondShift; 1644 1645 unsigned OpIdx = 0; 1646 1647 // Encode Dd / Sd. 1648 Binary |= encodeVFPRd(MI, OpIdx++); 1649 1650 // If this is a two-address operand, skip it, e.g. FMACD. 1651 if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) 1652 ++OpIdx; 1653 1654 // Encode Dn / Sn. 1655 if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPBinaryFrm) 1656 Binary |= encodeVFPRn(MI, OpIdx++); 1657 1658 if (OpIdx == TID.getNumOperands() || 1659 TID.OpInfo[OpIdx].isPredicate() || 1660 TID.OpInfo[OpIdx].isOptionalDef()) { 1661 // FCMPEZD etc. has only one operand. 1662 emitWordLE(Binary); 1663 return; 1664 } 1665 1666 // Encode Dm / Sm. 1667 Binary |= encodeVFPRm(MI, OpIdx); 1668 1669 emitWordLE(Binary); 1670} 1671 1672void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) { 1673 const TargetInstrDesc &TID = MI.getDesc(); 1674 unsigned Form = TID.TSFlags & ARMII::FormMask; 1675 1676 // Part of binary is determined by TableGn. 1677 unsigned Binary = getBinaryCodeForInstr(MI); 1678 1679 // Set the conditional execution predicate 1680 Binary |= II->getPredicate(&MI) << ARMII::CondShift; 1681 1682 switch (Form) { 1683 default: break; 1684 case ARMII::VFPConv1Frm: 1685 case ARMII::VFPConv2Frm: 1686 case ARMII::VFPConv3Frm: 1687 // Encode Dd / Sd. 1688 Binary |= encodeVFPRd(MI, 0); 1689 break; 1690 case ARMII::VFPConv4Frm: 1691 // Encode Dn / Sn. 1692 Binary |= encodeVFPRn(MI, 0); 1693 break; 1694 case ARMII::VFPConv5Frm: 1695 // Encode Dm / Sm. 1696 Binary |= encodeVFPRm(MI, 0); 1697 break; 1698 } 1699 1700 switch (Form) { 1701 default: break; 1702 case ARMII::VFPConv1Frm: 1703 // Encode Dm / Sm. 1704 Binary |= encodeVFPRm(MI, 1); 1705 break; 1706 case ARMII::VFPConv2Frm: 1707 case ARMII::VFPConv3Frm: 1708 // Encode Dn / Sn. 1709 Binary |= encodeVFPRn(MI, 1); 1710 break; 1711 case ARMII::VFPConv4Frm: 1712 case ARMII::VFPConv5Frm: 1713 // Encode Dd / Sd. 1714 Binary |= encodeVFPRd(MI, 1); 1715 break; 1716 } 1717 1718 if (Form == ARMII::VFPConv5Frm) 1719 // Encode Dn / Sn. 1720 Binary |= encodeVFPRn(MI, 2); 1721 else if (Form == ARMII::VFPConv3Frm) 1722 // Encode Dm / Sm. 1723 Binary |= encodeVFPRm(MI, 2); 1724 1725 emitWordLE(Binary); 1726} 1727 1728void ARMCodeEmitter::emitVFPLoadStoreInstruction(const MachineInstr &MI) { 1729 // Part of binary is determined by TableGn. 1730 unsigned Binary = getBinaryCodeForInstr(MI); 1731 1732 // Set the conditional execution predicate 1733 Binary |= II->getPredicate(&MI) << ARMII::CondShift; 1734 1735 if (MI.getOpcode() == ARM::VLDRS || MI.getOpcode() == ARM::VLDRD || 1736 MI.getOpcode() == ARM::VSTRS || MI.getOpcode() == ARM::VSTRD){ 1737 emitWordLE(Binary); 1738 return; 1739 } 1740 1741 unsigned OpIdx = 0; 1742 1743 // Encode Dd / Sd. 1744 Binary |= encodeVFPRd(MI, OpIdx++); 1745 1746 // Encode address base. 1747 const MachineOperand &Base = MI.getOperand(OpIdx++); 1748 Binary |= getMachineOpValue(MI, Base) << ARMII::RegRnShift; 1749 1750 // If there is a non-zero immediate offset, encode it. 1751 if (Base.isReg()) { 1752 const MachineOperand &Offset = MI.getOperand(OpIdx); 1753 if (unsigned ImmOffs = ARM_AM::getAM5Offset(Offset.getImm())) { 1754 if (ARM_AM::getAM5Op(Offset.getImm()) == ARM_AM::add) 1755 Binary |= 1 << ARMII::U_BitShift; 1756 Binary |= ImmOffs; 1757 emitWordLE(Binary); 1758 return; 1759 } 1760 } 1761 1762 // If immediate offset is omitted, default to +0. 1763 Binary |= 1 << ARMII::U_BitShift; 1764 1765 emitWordLE(Binary); 1766} 1767 1768void 1769ARMCodeEmitter::emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI) { 1770 const TargetInstrDesc &TID = MI.getDesc(); 1771 bool IsUpdating = (TID.TSFlags & ARMII::IndexModeMask) != 0; 1772 1773 // Part of binary is determined by TableGn. 1774 unsigned Binary = getBinaryCodeForInstr(MI); 1775 1776 // Set the conditional execution predicate 1777 Binary |= II->getPredicate(&MI) << ARMII::CondShift; 1778 1779 // Skip operand 0 of an instruction with base register update. 1780 unsigned OpIdx = 0; 1781 if (IsUpdating) 1782 ++OpIdx; 1783 1784 // Set base address operand 1785 Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; 1786 1787 // Set addressing mode by modifying bits U(23) and P(24) 1788 ARM_AM::AMSubMode Mode = ARM_AM::getLoadStoreMultipleSubMode(MI.getOpcode()); 1789 Binary |= getAddrModeUPBits(ARM_AM::getAM4SubMode(Mode)); 1790 1791 // Set bit W(21) 1792 if (IsUpdating) 1793 Binary |= 0x1 << ARMII::W_BitShift; 1794 1795 // First register is encoded in Dd. 1796 Binary |= encodeVFPRd(MI, OpIdx+2); 1797 1798 // Count the number of registers. 1799 unsigned NumRegs = 1; 1800 for (unsigned i = OpIdx+3, e = MI.getNumOperands(); i != e; ++i) { 1801 const MachineOperand &MO = MI.getOperand(i); 1802 if (!MO.isReg() || MO.isImplicit()) 1803 break; 1804 ++NumRegs; 1805 } 1806 // Bit 8 will be set if <list> is consecutive 64-bit registers (e.g., D0) 1807 // Otherwise, it will be 0, in the case of 32-bit registers. 1808 if(Binary & 0x100) 1809 Binary |= NumRegs * 2; 1810 else 1811 Binary |= NumRegs; 1812 1813 emitWordLE(Binary); 1814} 1815 1816void ARMCodeEmitter::emitMiscInstruction(const MachineInstr &MI) { 1817 unsigned Opcode = MI.getDesc().Opcode; 1818 // Part of binary is determined by TableGn. 1819 unsigned Binary = getBinaryCodeForInstr(MI); 1820 1821 // Set the conditional execution predicate 1822 Binary |= II->getPredicate(&MI) << ARMII::CondShift; 1823 1824 emitWordLE(Binary); 1825} 1826 1827static unsigned encodeNEONRd(const MachineInstr &MI, unsigned OpIdx) { 1828 unsigned RegD = MI.getOperand(OpIdx).getReg(); 1829 unsigned Binary = 0; 1830 RegD = getARMRegisterNumbering(RegD); 1831 Binary |= (RegD & 0xf) << ARMII::RegRdShift; 1832 Binary |= ((RegD >> 4) & 1) << ARMII::D_BitShift; 1833 return Binary; 1834} 1835 1836static unsigned encodeNEONRn(const MachineInstr &MI, unsigned OpIdx) { 1837 unsigned RegN = MI.getOperand(OpIdx).getReg(); 1838 unsigned Binary = 0; 1839 RegN = getARMRegisterNumbering(RegN); 1840 Binary |= (RegN & 0xf) << ARMII::RegRnShift; 1841 Binary |= ((RegN >> 4) & 1) << ARMII::N_BitShift; 1842 return Binary; 1843} 1844 1845static unsigned encodeNEONRm(const MachineInstr &MI, unsigned OpIdx) { 1846 unsigned RegM = MI.getOperand(OpIdx).getReg(); 1847 unsigned Binary = 0; 1848 RegM = getARMRegisterNumbering(RegM); 1849 Binary |= (RegM & 0xf); 1850 Binary |= ((RegM >> 4) & 1) << ARMII::M_BitShift; 1851 return Binary; 1852} 1853 1854/// convertNEONDataProcToThumb - Convert the ARM mode encoding for a NEON 1855/// data-processing instruction to the corresponding Thumb encoding. 1856static unsigned convertNEONDataProcToThumb(unsigned Binary) { 1857 assert((Binary & 0xfe000000) == 0xf2000000 && 1858 "not an ARM NEON data-processing instruction"); 1859 unsigned UBit = (Binary >> 24) & 1; 1860 return 0xef000000 | (UBit << 28) | (Binary & 0xffffff); 1861} 1862 1863void ARMCodeEmitter::emitNEONLaneInstruction(const MachineInstr &MI) { 1864 unsigned Binary = getBinaryCodeForInstr(MI); 1865 1866 unsigned RegTOpIdx, RegNOpIdx, LnOpIdx; 1867 const TargetInstrDesc &TID = MI.getDesc(); 1868 if ((TID.TSFlags & ARMII::FormMask) == ARMII::NGetLnFrm) { 1869 RegTOpIdx = 0; 1870 RegNOpIdx = 1; 1871 LnOpIdx = 2; 1872 } else { // ARMII::NSetLnFrm 1873 RegTOpIdx = 2; 1874 RegNOpIdx = 0; 1875 LnOpIdx = 3; 1876 } 1877 1878 // Set the conditional execution predicate 1879 Binary |= (IsThumb ? ARMCC::AL : II->getPredicate(&MI)) << ARMII::CondShift; 1880 1881 unsigned RegT = MI.getOperand(RegTOpIdx).getReg(); 1882 RegT = getARMRegisterNumbering(RegT); 1883 Binary |= (RegT << ARMII::RegRdShift); 1884 Binary |= encodeNEONRn(MI, RegNOpIdx); 1885 1886 unsigned LaneShift; 1887 if ((Binary & (1 << 22)) != 0) 1888 LaneShift = 0; // 8-bit elements 1889 else if ((Binary & (1 << 5)) != 0) 1890 LaneShift = 1; // 16-bit elements 1891 else 1892 LaneShift = 2; // 32-bit elements 1893 1894 unsigned Lane = MI.getOperand(LnOpIdx).getImm() << LaneShift; 1895 unsigned Opc1 = Lane >> 2; 1896 unsigned Opc2 = Lane & 3; 1897 assert((Opc1 & 3) == 0 && "out-of-range lane number operand"); 1898 Binary |= (Opc1 << 21); 1899 Binary |= (Opc2 << 5); 1900 1901 emitWordLE(Binary); 1902} 1903 1904void ARMCodeEmitter::emitNEONDupInstruction(const MachineInstr &MI) { 1905 unsigned Binary = getBinaryCodeForInstr(MI); 1906 1907 // Set the conditional execution predicate 1908 Binary |= (IsThumb ? ARMCC::AL : II->getPredicate(&MI)) << ARMII::CondShift; 1909 1910 unsigned RegT = MI.getOperand(1).getReg(); 1911 RegT = getARMRegisterNumbering(RegT); 1912 Binary |= (RegT << ARMII::RegRdShift); 1913 Binary |= encodeNEONRn(MI, 0); 1914 emitWordLE(Binary); 1915} 1916 1917void ARMCodeEmitter::emitNEON1RegModImmInstruction(const MachineInstr &MI) { 1918 unsigned Binary = getBinaryCodeForInstr(MI); 1919 // Destination register is encoded in Dd. 1920 Binary |= encodeNEONRd(MI, 0); 1921 // Immediate fields: Op, Cmode, I, Imm3, Imm4 1922 unsigned Imm = MI.getOperand(1).getImm(); 1923 unsigned Op = (Imm >> 12) & 1; 1924 unsigned Cmode = (Imm >> 8) & 0xf; 1925 unsigned I = (Imm >> 7) & 1; 1926 unsigned Imm3 = (Imm >> 4) & 0x7; 1927 unsigned Imm4 = Imm & 0xf; 1928 Binary |= (I << 24) | (Imm3 << 16) | (Cmode << 8) | (Op << 5) | Imm4; 1929 if (IsThumb) 1930 Binary = convertNEONDataProcToThumb(Binary); 1931 emitWordLE(Binary); 1932} 1933 1934void ARMCodeEmitter::emitNEON2RegInstruction(const MachineInstr &MI) { 1935 const TargetInstrDesc &TID = MI.getDesc(); 1936 unsigned Binary = getBinaryCodeForInstr(MI); 1937 // Destination register is encoded in Dd; source register in Dm. 1938 unsigned OpIdx = 0; 1939 Binary |= encodeNEONRd(MI, OpIdx++); 1940 if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) 1941 ++OpIdx; 1942 Binary |= encodeNEONRm(MI, OpIdx); 1943 if (IsThumb) 1944 Binary = convertNEONDataProcToThumb(Binary); 1945 // FIXME: This does not handle VDUPfdf or VDUPfqf. 1946 emitWordLE(Binary); 1947} 1948 1949void ARMCodeEmitter::emitNEON3RegInstruction(const MachineInstr &MI) { 1950 const TargetInstrDesc &TID = MI.getDesc(); 1951 unsigned Binary = getBinaryCodeForInstr(MI); 1952 // Destination register is encoded in Dd; source registers in Dn and Dm. 1953 unsigned OpIdx = 0; 1954 Binary |= encodeNEONRd(MI, OpIdx++); 1955 if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) 1956 ++OpIdx; 1957 Binary |= encodeNEONRn(MI, OpIdx++); 1958 if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) 1959 ++OpIdx; 1960 Binary |= encodeNEONRm(MI, OpIdx); 1961 if (IsThumb) 1962 Binary = convertNEONDataProcToThumb(Binary); 1963 // FIXME: This does not handle VMOVDneon or VMOVQ. 1964 emitWordLE(Binary); 1965} 1966 1967#include "ARMGenCodeEmitter.inc" 1968