10b57cec5SDimitry Andric //===-- ARM/ARMMCCodeEmitter.cpp - Convert ARM code to machine code -------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the ARMMCCodeEmitter class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "MCTargetDesc/ARMAddressingModes.h" 140b57cec5SDimitry Andric #include "MCTargetDesc/ARMBaseInfo.h" 150b57cec5SDimitry Andric #include "MCTargetDesc/ARMFixupKinds.h" 160b57cec5SDimitry Andric #include "MCTargetDesc/ARMMCExpr.h" 170b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h" 180b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 190b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 200b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 210b57cec5SDimitry Andric #include "llvm/MC/MCCodeEmitter.h" 220b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 230b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 240b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 260b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 270b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 280b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 290b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 300b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 310b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 32*5f757f3fSDimitry Andric #include "llvm/Support/EndianStream.h" 330b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 340b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 350b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 3606c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 370b57cec5SDimitry Andric #include <algorithm> 380b57cec5SDimitry Andric #include <cassert> 390b57cec5SDimitry Andric #include <cstdint> 400b57cec5SDimitry Andric #include <cstdlib> 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric using namespace llvm; 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric #define DEBUG_TYPE "mccodeemitter" 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric STATISTIC(MCNumEmitted, "Number of MC instructions emitted."); 470b57cec5SDimitry Andric STATISTIC(MCNumCPRelocations, "Number of constant pool relocations created."); 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric namespace { 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric class ARMMCCodeEmitter : public MCCodeEmitter { 520b57cec5SDimitry Andric const MCInstrInfo &MCII; 530b57cec5SDimitry Andric MCContext &CTX; 540b57cec5SDimitry Andric bool IsLittleEndian; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric public: 570b57cec5SDimitry Andric ARMMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx, bool IsLittle) 580b57cec5SDimitry Andric : MCII(mcii), CTX(ctx), IsLittleEndian(IsLittle) { 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric ARMMCCodeEmitter(const ARMMCCodeEmitter &) = delete; 610b57cec5SDimitry Andric ARMMCCodeEmitter &operator=(const ARMMCCodeEmitter &) = delete; 620b57cec5SDimitry Andric ~ARMMCCodeEmitter() override = default; 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric bool isThumb(const MCSubtargetInfo &STI) const { 6506c3fb27SDimitry Andric return STI.hasFeature(ARM::ModeThumb); 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric bool isThumb2(const MCSubtargetInfo &STI) const { 6906c3fb27SDimitry Andric return isThumb(STI) && STI.hasFeature(ARM::FeatureThumb2); 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric bool isTargetMachO(const MCSubtargetInfo &STI) const { 730b57cec5SDimitry Andric const Triple &TT = STI.getTargetTriple(); 740b57cec5SDimitry Andric return TT.isOSBinFormatMachO(); 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric unsigned getMachineSoImmOpValue(unsigned SoImm) const; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric // getBinaryCodeForInstr - TableGen'erated function for getting the 800b57cec5SDimitry Andric // binary encoding for an instruction. 810b57cec5SDimitry Andric uint64_t getBinaryCodeForInstr(const MCInst &MI, 820b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 830b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric /// getMachineOpValue - Return binary encoding of operand. If the machine 860b57cec5SDimitry Andric /// operand requires relocation, record the relocation and return zero. 870b57cec5SDimitry Andric unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, 880b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 890b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 900b57cec5SDimitry Andric 9106c3fb27SDimitry Andric /// getHiLoImmOpValue - Return the encoding for either the hi / low 16-bit, or 9206c3fb27SDimitry Andric /// high/middle-high/middle-low/low 8 bits of the specified operand. This is 9306c3fb27SDimitry Andric /// used for operands with :lower16:, :upper16: :lower0_7:, :lower8_15:, 9406c3fb27SDimitry Andric /// :higher0_7:, and :higher8_15: prefixes. 9506c3fb27SDimitry Andric uint32_t getHiLoImmOpValue(const MCInst &MI, unsigned OpIdx, 960b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 970b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric bool EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, 1000b57cec5SDimitry Andric unsigned &Reg, unsigned &Imm, 1010b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1020b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric /// getThumbBLTargetOpValue - Return encoding info for Thumb immediate 1050b57cec5SDimitry Andric /// BL branch target. 1060b57cec5SDimitry Andric uint32_t getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx, 1070b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1080b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric /// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate 1110b57cec5SDimitry Andric /// BLX branch target. 1120b57cec5SDimitry Andric uint32_t getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, 1130b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1140b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric /// getThumbBRTargetOpValue - Return encoding info for Thumb branch target. 1170b57cec5SDimitry Andric uint32_t getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx, 1180b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1190b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric /// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target. 1220b57cec5SDimitry Andric uint32_t getThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx, 1230b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1240b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric /// getThumbCBTargetOpValue - Return encoding info for Thumb branch target. 1270b57cec5SDimitry Andric uint32_t getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx, 1280b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1290b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric /// getBranchTargetOpValue - Return encoding info for 24-bit immediate 1320b57cec5SDimitry Andric /// branch target. 1330b57cec5SDimitry Andric uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 1340b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1350b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric /// getThumbBranchTargetOpValue - Return encoding info for 24-bit 1380b57cec5SDimitry Andric /// immediate Thumb2 direct branch target. 1390b57cec5SDimitry Andric uint32_t getThumbBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 1400b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1410b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric /// getARMBranchTargetOpValue - Return encoding info for 24-bit immediate 1440b57cec5SDimitry Andric /// branch target. 1450b57cec5SDimitry Andric uint32_t getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 1460b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1470b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1480b57cec5SDimitry Andric uint32_t getARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx, 1490b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1500b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1510b57cec5SDimitry Andric uint32_t getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, 1520b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1530b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric /// getAdrLabelOpValue - Return encoding info for 12-bit immediate 1560b57cec5SDimitry Andric /// ADR label target. 1570b57cec5SDimitry Andric uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 1580b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1590b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1600b57cec5SDimitry Andric uint32_t getThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 1610b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1620b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1630b57cec5SDimitry Andric uint32_t getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 1640b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1650b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric uint32_t getITMaskOpValue(const MCInst &MI, unsigned OpIdx, 1680b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1690b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric /// getMVEShiftImmOpValue - Return encoding info for the 'sz:imm5' 1720b57cec5SDimitry Andric /// operand. 1730b57cec5SDimitry Andric uint32_t getMVEShiftImmOpValue(const MCInst &MI, unsigned OpIdx, 1740b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1750b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' 1780b57cec5SDimitry Andric /// operand. 1790b57cec5SDimitry Andric uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, 1800b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1810b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric /// getThumbAddrModeRegRegOpValue - Return encoding for 'reg + reg' operand. 1840b57cec5SDimitry Andric uint32_t getThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx, 1850b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1860b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric /// getT2AddrModeImm8s4OpValue - Return encoding info for 'reg +/- imm8<<2' 1890b57cec5SDimitry Andric /// operand. 1900b57cec5SDimitry Andric uint32_t getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx, 1910b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1920b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric /// getT2AddrModeImm7s4OpValue - Return encoding info for 'reg +/- imm7<<2' 1950b57cec5SDimitry Andric /// operand. 1960b57cec5SDimitry Andric uint32_t getT2AddrModeImm7s4OpValue(const MCInst &MI, unsigned OpIdx, 1970b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1980b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric /// getT2AddrModeImm0_1020s4OpValue - Return encoding info for 'reg + imm8<<2' 2010b57cec5SDimitry Andric /// operand. 2020b57cec5SDimitry Andric uint32_t getT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx, 2030b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2040b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric /// getT2ScaledImmOpValue - Return encoding info for '+/- immX<<Y' 2070b57cec5SDimitry Andric /// operand. 2080b57cec5SDimitry Andric template<unsigned Bits, unsigned Shift> 2090b57cec5SDimitry Andric uint32_t getT2ScaledImmOpValue(const MCInst &MI, unsigned OpIdx, 2100b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2110b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric /// getMveAddrModeRQOpValue - Return encoding info for 'reg, vreg' 2140b57cec5SDimitry Andric /// operand. 2150b57cec5SDimitry Andric uint32_t getMveAddrModeRQOpValue(const MCInst &MI, unsigned OpIdx, 2160b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2170b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric /// getMveAddrModeQOpValue - Return encoding info for 'reg +/- imm7<<{shift}' 2200b57cec5SDimitry Andric /// operand. 2210b57cec5SDimitry Andric template<int shift> 2220b57cec5SDimitry Andric uint32_t getMveAddrModeQOpValue(const MCInst &MI, unsigned OpIdx, 2230b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2240b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric /// getLdStSORegOpValue - Return encoding info for 'reg +/- reg shop imm' 2270b57cec5SDimitry Andric /// operand as needed by load/store instructions. 2280b57cec5SDimitry Andric uint32_t getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx, 2290b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2300b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric /// getLdStmModeOpValue - Return encoding for load/store multiple mode. 2330b57cec5SDimitry Andric uint32_t getLdStmModeOpValue(const MCInst &MI, unsigned OpIdx, 2340b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2350b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 2360b57cec5SDimitry Andric ARM_AM::AMSubMode Mode = (ARM_AM::AMSubMode)MI.getOperand(OpIdx).getImm(); 2370b57cec5SDimitry Andric switch (Mode) { 2380b57cec5SDimitry Andric default: llvm_unreachable("Unknown addressing sub-mode!"); 2390b57cec5SDimitry Andric case ARM_AM::da: return 0; 2400b57cec5SDimitry Andric case ARM_AM::ia: return 1; 2410b57cec5SDimitry Andric case ARM_AM::db: return 2; 2420b57cec5SDimitry Andric case ARM_AM::ib: return 3; 2430b57cec5SDimitry Andric } 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric /// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value. 2470b57cec5SDimitry Andric /// 2480b57cec5SDimitry Andric unsigned getShiftOp(ARM_AM::ShiftOpc ShOpc) const { 2490b57cec5SDimitry Andric switch (ShOpc) { 2500b57cec5SDimitry Andric case ARM_AM::no_shift: 2510b57cec5SDimitry Andric case ARM_AM::lsl: return 0; 2520b57cec5SDimitry Andric case ARM_AM::lsr: return 1; 2530b57cec5SDimitry Andric case ARM_AM::asr: return 2; 2540b57cec5SDimitry Andric case ARM_AM::ror: 2550b57cec5SDimitry Andric case ARM_AM::rrx: return 3; 2560b57cec5SDimitry Andric default: 2570b57cec5SDimitry Andric llvm_unreachable("Invalid ShiftOpc!"); 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric /// getAddrMode2OffsetOpValue - Return encoding for am2offset operands. 2620b57cec5SDimitry Andric uint32_t getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx, 2630b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2640b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric /// getPostIdxRegOpValue - Return encoding for postidx_reg operands. 2670b57cec5SDimitry Andric uint32_t getPostIdxRegOpValue(const MCInst &MI, unsigned OpIdx, 2680b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2690b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric /// getAddrMode3OffsetOpValue - Return encoding for am3offset operands. 2720b57cec5SDimitry Andric uint32_t getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx, 2730b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2740b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric /// getAddrMode3OpValue - Return encoding for addrmode3 operands. 2770b57cec5SDimitry Andric uint32_t getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx, 2780b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2790b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric /// getAddrModeThumbSPOpValue - Return encoding info for 'reg +/- imm12' 2820b57cec5SDimitry Andric /// operand. 2830b57cec5SDimitry Andric uint32_t getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx, 2840b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2850b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric /// getAddrModeISOpValue - Encode the t_addrmode_is# operands. 2880b57cec5SDimitry Andric uint32_t getAddrModeISOpValue(const MCInst &MI, unsigned OpIdx, 2890b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2900b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric /// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands. 2930b57cec5SDimitry Andric uint32_t getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx, 2940b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 2950b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric /// getAddrMode5OpValue - Return encoding info for 'reg +/- (imm8 << 2)' operand. 2980b57cec5SDimitry Andric uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, 2990b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3000b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric /// getAddrMode5FP16OpValue - Return encoding info for 'reg +/- (imm8 << 1)' operand. 3030b57cec5SDimitry Andric uint32_t getAddrMode5FP16OpValue(const MCInst &MI, unsigned OpIdx, 3040b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3050b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric /// getCCOutOpValue - Return encoding of the 's' bit. 3080b57cec5SDimitry Andric unsigned getCCOutOpValue(const MCInst &MI, unsigned Op, 3090b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3100b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 3110b57cec5SDimitry Andric // The operand is either reg0 or CPSR. The 's' bit is encoded as '0' or 3120b57cec5SDimitry Andric // '1' respectively. 3130b57cec5SDimitry Andric return MI.getOperand(Op).getReg() == ARM::CPSR; 3140b57cec5SDimitry Andric } 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric unsigned getModImmOpValue(const MCInst &MI, unsigned Op, 3170b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3180b57cec5SDimitry Andric const MCSubtargetInfo &ST) const { 3190b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(Op); 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric // Support for fixups (MCFixup) 3220b57cec5SDimitry Andric if (MO.isExpr()) { 3230b57cec5SDimitry Andric const MCExpr *Expr = MO.getExpr(); 3240b57cec5SDimitry Andric // Fixups resolve to plain values that need to be encoded. 3250b57cec5SDimitry Andric MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_mod_imm); 3260b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); 3270b57cec5SDimitry Andric return 0; 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric // Immediate is already in its encoded format 3310b57cec5SDimitry Andric return MO.getImm(); 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric /// getT2SOImmOpValue - Return an encoded 12-bit shifted-immediate value. 3350b57cec5SDimitry Andric unsigned getT2SOImmOpValue(const MCInst &MI, unsigned Op, 3360b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3370b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 3380b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(Op); 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric // Support for fixups (MCFixup) 3410b57cec5SDimitry Andric if (MO.isExpr()) { 3420b57cec5SDimitry Andric const MCExpr *Expr = MO.getExpr(); 3430b57cec5SDimitry Andric // Fixups resolve to plain values that need to be encoded. 3440b57cec5SDimitry Andric MCFixupKind Kind = MCFixupKind(ARM::fixup_t2_so_imm); 3450b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); 3460b57cec5SDimitry Andric return 0; 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric unsigned SoImm = MO.getImm(); 3490b57cec5SDimitry Andric unsigned Encoded = ARM_AM::getT2SOImmVal(SoImm); 3500b57cec5SDimitry Andric assert(Encoded != ~0U && "Not a Thumb2 so_imm value?"); 3510b57cec5SDimitry Andric return Encoded; 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric unsigned getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum, 3550b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3560b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 3570b57cec5SDimitry Andric template<unsigned Bits, unsigned Shift> 3580b57cec5SDimitry Andric unsigned getT2AddrModeImmOpValue(const MCInst &MI, unsigned OpNum, 3590b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3600b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 3610b57cec5SDimitry Andric unsigned getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum, 3620b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3630b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric /// getSORegOpValue - Return an encoded so_reg shifted register value. 3660b57cec5SDimitry Andric unsigned getSORegRegOpValue(const MCInst &MI, unsigned Op, 3670b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3680b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 3690b57cec5SDimitry Andric unsigned getSORegImmOpValue(const MCInst &MI, unsigned Op, 3700b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3710b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 3720b57cec5SDimitry Andric unsigned getT2SORegOpValue(const MCInst &MI, unsigned Op, 3730b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3740b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric unsigned getNEONVcvtImm32OpValue(const MCInst &MI, unsigned Op, 3770b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3780b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 3790b57cec5SDimitry Andric return 64 - MI.getOperand(Op).getImm(); 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric unsigned getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op, 3830b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3840b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric unsigned getRegisterListOpValue(const MCInst &MI, unsigned Op, 3870b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3880b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 3890b57cec5SDimitry Andric unsigned getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op, 3900b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3910b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 3920b57cec5SDimitry Andric unsigned getAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op, 3930b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3940b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 3950b57cec5SDimitry Andric unsigned getAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op, 3960b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 3970b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 3980b57cec5SDimitry Andric unsigned getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op, 3990b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4000b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric unsigned getShiftRight8Imm(const MCInst &MI, unsigned Op, 4030b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4040b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4050b57cec5SDimitry Andric unsigned getShiftRight16Imm(const MCInst &MI, unsigned Op, 4060b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4070b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4080b57cec5SDimitry Andric unsigned getShiftRight32Imm(const MCInst &MI, unsigned Op, 4090b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4100b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4110b57cec5SDimitry Andric unsigned getShiftRight64Imm(const MCInst &MI, unsigned Op, 4120b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4130b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric unsigned getThumbSRImmOpValue(const MCInst &MI, unsigned Op, 4160b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4170b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric unsigned NEONThumb2DataIPostEncoder(const MCInst &MI, 4200b57cec5SDimitry Andric unsigned EncodedValue, 4210b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4220b57cec5SDimitry Andric unsigned NEONThumb2LoadStorePostEncoder(const MCInst &MI, 4230b57cec5SDimitry Andric unsigned EncodedValue, 4240b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4250b57cec5SDimitry Andric unsigned NEONThumb2DupPostEncoder(const MCInst &MI, 4260b57cec5SDimitry Andric unsigned EncodedValue, 4270b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4280b57cec5SDimitry Andric unsigned NEONThumb2V8PostEncoder(const MCInst &MI, 4290b57cec5SDimitry Andric unsigned EncodedValue, 4300b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric unsigned VFPThumb2PostEncoder(const MCInst &MI, 4330b57cec5SDimitry Andric unsigned EncodedValue, 4340b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric uint32_t getPowerTwoOpValue(const MCInst &MI, unsigned OpIdx, 4370b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4380b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4390b57cec5SDimitry Andric 440*5f757f3fSDimitry Andric void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB, 4410b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4420b57cec5SDimitry Andric const MCSubtargetInfo &STI) const override; 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric template <bool isNeg, ARM::Fixups fixup> 4450b57cec5SDimitry Andric uint32_t getBFTargetOpValue(const MCInst &MI, unsigned OpIdx, 4460b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4470b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric uint32_t getBFAfterTargetOpValue(const MCInst &MI, unsigned OpIdx, 4500b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4510b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric uint32_t getVPTMaskOpValue(const MCInst &MI, unsigned OpIdx, 4540b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4550b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4560b57cec5SDimitry Andric uint32_t getRestrictedCondCodeOpValue(const MCInst &MI, unsigned OpIdx, 4570b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4580b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4590b57cec5SDimitry Andric template <unsigned size> 4600b57cec5SDimitry Andric uint32_t getMVEPairVectorIndexOpValue(const MCInst &MI, unsigned OpIdx, 4610b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4620b57cec5SDimitry Andric const MCSubtargetInfo &STI) const; 4630b57cec5SDimitry Andric }; 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric } // end anonymous namespace 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric /// NEONThumb2DataIPostEncoder - Post-process encoded NEON data-processing 4680b57cec5SDimitry Andric /// instructions, and rewrite them to their Thumb2 form if we are currently in 4690b57cec5SDimitry Andric /// Thumb2 mode. 4700b57cec5SDimitry Andric unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI, 4710b57cec5SDimitry Andric unsigned EncodedValue, 4720b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 4730b57cec5SDimitry Andric if (isThumb2(STI)) { 4740b57cec5SDimitry Andric // NEON Thumb2 data-processsing encodings are very simple: bit 24 is moved 4750b57cec5SDimitry Andric // to bit 12 of the high half-word (i.e. bit 28), and bits 27-24 are 4760b57cec5SDimitry Andric // set to 1111. 4770b57cec5SDimitry Andric unsigned Bit24 = EncodedValue & 0x01000000; 4780b57cec5SDimitry Andric unsigned Bit28 = Bit24 << 4; 4790b57cec5SDimitry Andric EncodedValue &= 0xEFFFFFFF; 4800b57cec5SDimitry Andric EncodedValue |= Bit28; 4810b57cec5SDimitry Andric EncodedValue |= 0x0F000000; 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric return EncodedValue; 4850b57cec5SDimitry Andric } 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric /// NEONThumb2LoadStorePostEncoder - Post-process encoded NEON load/store 4880b57cec5SDimitry Andric /// instructions, and rewrite them to their Thumb2 form if we are currently in 4890b57cec5SDimitry Andric /// Thumb2 mode. 4900b57cec5SDimitry Andric unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI, 4910b57cec5SDimitry Andric unsigned EncodedValue, 4920b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 4930b57cec5SDimitry Andric if (isThumb2(STI)) { 4940b57cec5SDimitry Andric EncodedValue &= 0xF0FFFFFF; 4950b57cec5SDimitry Andric EncodedValue |= 0x09000000; 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric return EncodedValue; 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric 5010b57cec5SDimitry Andric /// NEONThumb2DupPostEncoder - Post-process encoded NEON vdup 5020b57cec5SDimitry Andric /// instructions, and rewrite them to their Thumb2 form if we are currently in 5030b57cec5SDimitry Andric /// Thumb2 mode. 5040b57cec5SDimitry Andric unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI, 5050b57cec5SDimitry Andric unsigned EncodedValue, 5060b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 5070b57cec5SDimitry Andric if (isThumb2(STI)) { 5080b57cec5SDimitry Andric EncodedValue &= 0x00FFFFFF; 5090b57cec5SDimitry Andric EncodedValue |= 0xEE000000; 5100b57cec5SDimitry Andric } 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric return EncodedValue; 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric /// Post-process encoded NEON v8 instructions, and rewrite them to Thumb2 form 5160b57cec5SDimitry Andric /// if we are in Thumb2. 5170b57cec5SDimitry Andric unsigned ARMMCCodeEmitter::NEONThumb2V8PostEncoder(const MCInst &MI, 5180b57cec5SDimitry Andric unsigned EncodedValue, 5190b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 5200b57cec5SDimitry Andric if (isThumb2(STI)) { 5210b57cec5SDimitry Andric EncodedValue |= 0xC000000; // Set bits 27-26 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric return EncodedValue; 5250b57cec5SDimitry Andric } 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric /// VFPThumb2PostEncoder - Post-process encoded VFP instructions and rewrite 5280b57cec5SDimitry Andric /// them to their Thumb2 form if we are currently in Thumb2 mode. 5290b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 5300b57cec5SDimitry Andric VFPThumb2PostEncoder(const MCInst &MI, unsigned EncodedValue, 5310b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 5320b57cec5SDimitry Andric if (isThumb2(STI)) { 5330b57cec5SDimitry Andric EncodedValue &= 0x0FFFFFFF; 5340b57cec5SDimitry Andric EncodedValue |= 0xE0000000; 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric return EncodedValue; 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric /// getMachineOpValue - Return binary encoding of operand. If the machine 5400b57cec5SDimitry Andric /// operand requires relocation, record the relocation and return zero. 5410b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 5420b57cec5SDimitry Andric getMachineOpValue(const MCInst &MI, const MCOperand &MO, 5430b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 5440b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 5450b57cec5SDimitry Andric if (MO.isReg()) { 5460b57cec5SDimitry Andric unsigned Reg = MO.getReg(); 5470b57cec5SDimitry Andric unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg); 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric // In NEON, Q registers are encoded as 2x their register number, 5500b57cec5SDimitry Andric // because they're using the same indices as the D registers they 5510b57cec5SDimitry Andric // overlap. In MVE, there are no 64-bit vector instructions, so 5520b57cec5SDimitry Andric // the encodings all refer to Q-registers by their literal 5530b57cec5SDimitry Andric // register number. 5540b57cec5SDimitry Andric 55506c3fb27SDimitry Andric if (STI.hasFeature(ARM::HasMVEIntegerOps)) 5560b57cec5SDimitry Andric return RegNo; 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric switch (Reg) { 5590b57cec5SDimitry Andric default: 5600b57cec5SDimitry Andric return RegNo; 5610b57cec5SDimitry Andric case ARM::Q0: case ARM::Q1: case ARM::Q2: case ARM::Q3: 5620b57cec5SDimitry Andric case ARM::Q4: case ARM::Q5: case ARM::Q6: case ARM::Q7: 5630b57cec5SDimitry Andric case ARM::Q8: case ARM::Q9: case ARM::Q10: case ARM::Q11: 5640b57cec5SDimitry Andric case ARM::Q12: case ARM::Q13: case ARM::Q14: case ARM::Q15: 5650b57cec5SDimitry Andric return 2 * RegNo; 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric } else if (MO.isImm()) { 5680b57cec5SDimitry Andric return static_cast<unsigned>(MO.getImm()); 569fe6060f1SDimitry Andric } else if (MO.isDFPImm()) { 570fe6060f1SDimitry Andric return static_cast<unsigned>(APFloat(bit_cast<double>(MO.getDFPImm())) 571fe6060f1SDimitry Andric .bitcastToAPInt() 572fe6060f1SDimitry Andric .getHiBits(32) 573fe6060f1SDimitry Andric .getLimitedValue()); 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric llvm_unreachable("Unable to encode MCOperand!"); 5770b57cec5SDimitry Andric } 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric /// getAddrModeImmOpValue - Return encoding info for 'reg +/- imm' operand. 5800b57cec5SDimitry Andric bool ARMMCCodeEmitter:: 5810b57cec5SDimitry Andric EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg, 5820b57cec5SDimitry Andric unsigned &Imm, SmallVectorImpl<MCFixup> &Fixups, 5830b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 5840b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 5850b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 5860b57cec5SDimitry Andric 5870b57cec5SDimitry Andric Reg = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 5880b57cec5SDimitry Andric 5890b57cec5SDimitry Andric int32_t SImm = MO1.getImm(); 5900b57cec5SDimitry Andric bool isAdd = true; 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric // Special value for #-0 5930b57cec5SDimitry Andric if (SImm == INT32_MIN) { 5940b57cec5SDimitry Andric SImm = 0; 5950b57cec5SDimitry Andric isAdd = false; 5960b57cec5SDimitry Andric } 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 5990b57cec5SDimitry Andric if (SImm < 0) { 6000b57cec5SDimitry Andric SImm = -SImm; 6010b57cec5SDimitry Andric isAdd = false; 6020b57cec5SDimitry Andric } 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric Imm = SImm; 6050b57cec5SDimitry Andric return isAdd; 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric /// getBranchTargetOpValue - Helper function to get the branch target operand, 6090b57cec5SDimitry Andric /// which is either an immediate or requires a fixup. 6100b57cec5SDimitry Andric static uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 6110b57cec5SDimitry Andric unsigned FixupKind, 6120b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 6130b57cec5SDimitry Andric const MCSubtargetInfo &STI) { 6140b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric // If the destination is an immediate, we have nothing to do. 6170b57cec5SDimitry Andric if (MO.isImm()) return MO.getImm(); 6180b57cec5SDimitry Andric assert(MO.isExpr() && "Unexpected branch target type!"); 6190b57cec5SDimitry Andric const MCExpr *Expr = MO.getExpr(); 6200b57cec5SDimitry Andric MCFixupKind Kind = MCFixupKind(FixupKind); 6210b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); 6220b57cec5SDimitry Andric 6230b57cec5SDimitry Andric // All of the information is in the fixup. 6240b57cec5SDimitry Andric return 0; 6250b57cec5SDimitry Andric } 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric // Thumb BL and BLX use a strange offset encoding where bits 22 and 21 are 6280b57cec5SDimitry Andric // determined by negating them and XOR'ing them with bit 23. 6290b57cec5SDimitry Andric static int32_t encodeThumbBLOffset(int32_t offset) { 6300b57cec5SDimitry Andric offset >>= 1; 6310b57cec5SDimitry Andric uint32_t S = (offset & 0x800000) >> 23; 6320b57cec5SDimitry Andric uint32_t J1 = (offset & 0x400000) >> 22; 6330b57cec5SDimitry Andric uint32_t J2 = (offset & 0x200000) >> 21; 6340b57cec5SDimitry Andric J1 = (~J1 & 0x1); 6350b57cec5SDimitry Andric J2 = (~J2 & 0x1); 6360b57cec5SDimitry Andric J1 ^= S; 6370b57cec5SDimitry Andric J2 ^= S; 6380b57cec5SDimitry Andric 6390b57cec5SDimitry Andric offset &= ~0x600000; 6400b57cec5SDimitry Andric offset |= J1 << 22; 6410b57cec5SDimitry Andric offset |= J2 << 21; 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric return offset; 6440b57cec5SDimitry Andric } 6450b57cec5SDimitry Andric 6460b57cec5SDimitry Andric /// getThumbBLTargetOpValue - Return encoding info for immediate branch target. 6470b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 6480b57cec5SDimitry Andric getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx, 6490b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 6500b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 6510b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 6520b57cec5SDimitry Andric if (MO.isExpr()) 6530b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bl, 6540b57cec5SDimitry Andric Fixups, STI); 6550b57cec5SDimitry Andric return encodeThumbBLOffset(MO.getImm()); 6560b57cec5SDimitry Andric } 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric /// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate 6590b57cec5SDimitry Andric /// BLX branch target. 6600b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 6610b57cec5SDimitry Andric getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, 6620b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 6630b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 6640b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 6650b57cec5SDimitry Andric if (MO.isExpr()) 6660b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_blx, 6670b57cec5SDimitry Andric Fixups, STI); 6680b57cec5SDimitry Andric return encodeThumbBLOffset(MO.getImm()); 6690b57cec5SDimitry Andric } 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric /// getThumbBRTargetOpValue - Return encoding info for Thumb branch target. 6720b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 6730b57cec5SDimitry Andric getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx, 6740b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 6750b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 6760b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 6770b57cec5SDimitry Andric if (MO.isExpr()) 6780b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_br, 6790b57cec5SDimitry Andric Fixups, STI); 6800b57cec5SDimitry Andric return (MO.getImm() >> 1); 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric /// getThumbBCCTargetOpValue - Return encoding info for Thumb branch target. 6840b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 6850b57cec5SDimitry Andric getThumbBCCTargetOpValue(const MCInst &MI, unsigned OpIdx, 6860b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 6870b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 6880b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 6890b57cec5SDimitry Andric if (MO.isExpr()) 6900b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bcc, 6910b57cec5SDimitry Andric Fixups, STI); 6920b57cec5SDimitry Andric return (MO.getImm() >> 1); 6930b57cec5SDimitry Andric } 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric /// getThumbCBTargetOpValue - Return encoding info for Thumb branch target. 6960b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 6970b57cec5SDimitry Andric getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx, 6980b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 6990b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 7000b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 7010b57cec5SDimitry Andric if (MO.isExpr()) 7020b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cb, Fixups, STI); 7030b57cec5SDimitry Andric return (MO.getImm() >> 1); 7040b57cec5SDimitry Andric } 7050b57cec5SDimitry Andric 7060b57cec5SDimitry Andric /// Return true if this branch has a non-always predication 7070b57cec5SDimitry Andric static bool HasConditionalBranch(const MCInst &MI) { 7080b57cec5SDimitry Andric int NumOp = MI.getNumOperands(); 7090b57cec5SDimitry Andric if (NumOp >= 2) { 7100b57cec5SDimitry Andric for (int i = 0; i < NumOp-1; ++i) { 7110b57cec5SDimitry Andric const MCOperand &MCOp1 = MI.getOperand(i); 7120b57cec5SDimitry Andric const MCOperand &MCOp2 = MI.getOperand(i + 1); 7130b57cec5SDimitry Andric if (MCOp1.isImm() && MCOp2.isReg() && 7140b57cec5SDimitry Andric (MCOp2.getReg() == 0 || MCOp2.getReg() == ARM::CPSR)) { 7150b57cec5SDimitry Andric if (ARMCC::CondCodes(MCOp1.getImm()) != ARMCC::AL) 7160b57cec5SDimitry Andric return true; 7170b57cec5SDimitry Andric } 7180b57cec5SDimitry Andric } 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric return false; 7210b57cec5SDimitry Andric } 7220b57cec5SDimitry Andric 7230b57cec5SDimitry Andric /// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch 7240b57cec5SDimitry Andric /// target. 7250b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 7260b57cec5SDimitry Andric getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 7270b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 7280b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 7290b57cec5SDimitry Andric // FIXME: This really, really shouldn't use TargetMachine. We don't want 7300b57cec5SDimitry Andric // coupling between MC and TM anywhere we can help it. 7310b57cec5SDimitry Andric if (isThumb2(STI)) 7320b57cec5SDimitry Andric return 7330b57cec5SDimitry Andric ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups, STI); 7340b57cec5SDimitry Andric return getARMBranchTargetOpValue(MI, OpIdx, Fixups, STI); 7350b57cec5SDimitry Andric } 7360b57cec5SDimitry Andric 7370b57cec5SDimitry Andric /// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch 7380b57cec5SDimitry Andric /// target. 7390b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 7400b57cec5SDimitry Andric getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, 7410b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 7420b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 7430b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 7440b57cec5SDimitry Andric if (MO.isExpr()) { 7450b57cec5SDimitry Andric if (HasConditionalBranch(MI)) 7460b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, 7470b57cec5SDimitry Andric ARM::fixup_arm_condbranch, Fixups, STI); 7480b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, 7490b57cec5SDimitry Andric ARM::fixup_arm_uncondbranch, Fixups, STI); 7500b57cec5SDimitry Andric } 7510b57cec5SDimitry Andric 7520b57cec5SDimitry Andric return MO.getImm() >> 2; 7530b57cec5SDimitry Andric } 7540b57cec5SDimitry Andric 7550b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 7560b57cec5SDimitry Andric getARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx, 7570b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 7580b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 7590b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 7600b57cec5SDimitry Andric if (MO.isExpr()) { 7610b57cec5SDimitry Andric if (HasConditionalBranch(MI)) 7620b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, 7630b57cec5SDimitry Andric ARM::fixup_arm_condbl, Fixups, STI); 7640b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_uncondbl, Fixups, STI); 7650b57cec5SDimitry Andric } 7660b57cec5SDimitry Andric 7670b57cec5SDimitry Andric return MO.getImm() >> 2; 7680b57cec5SDimitry Andric } 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 7710b57cec5SDimitry Andric getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, 7720b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 7730b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 7740b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 7750b57cec5SDimitry Andric if (MO.isExpr()) 7760b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_blx, Fixups, STI); 7770b57cec5SDimitry Andric 7780b57cec5SDimitry Andric return MO.getImm() >> 1; 7790b57cec5SDimitry Andric } 7800b57cec5SDimitry Andric 7810b57cec5SDimitry Andric /// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit 7820b57cec5SDimitry Andric /// immediate branch target. 7830b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter::getThumbBranchTargetOpValue( 7840b57cec5SDimitry Andric const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 7850b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 7860b57cec5SDimitry Andric unsigned Val = 0; 7870b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 7880b57cec5SDimitry Andric 7890b57cec5SDimitry Andric if(MO.isExpr()) 7900b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_uncondbranch, Fixups, STI); 7910b57cec5SDimitry Andric else 7920b57cec5SDimitry Andric Val = MO.getImm() >> 1; 7930b57cec5SDimitry Andric 7940b57cec5SDimitry Andric bool I = (Val & 0x800000); 7950b57cec5SDimitry Andric bool J1 = (Val & 0x400000); 7960b57cec5SDimitry Andric bool J2 = (Val & 0x200000); 7970b57cec5SDimitry Andric if (I ^ J1) 7980b57cec5SDimitry Andric Val &= ~0x400000; 7990b57cec5SDimitry Andric else 8000b57cec5SDimitry Andric Val |= 0x400000; 8010b57cec5SDimitry Andric 8020b57cec5SDimitry Andric if (I ^ J2) 8030b57cec5SDimitry Andric Val &= ~0x200000; 8040b57cec5SDimitry Andric else 8050b57cec5SDimitry Andric Val |= 0x200000; 8060b57cec5SDimitry Andric 8070b57cec5SDimitry Andric return Val; 8080b57cec5SDimitry Andric } 8090b57cec5SDimitry Andric 8100b57cec5SDimitry Andric /// getAdrLabelOpValue - Return encoding info for 12-bit shifted-immediate 8110b57cec5SDimitry Andric /// ADR label target. 8120b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 8130b57cec5SDimitry Andric getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 8140b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 8150b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 8160b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 8170b57cec5SDimitry Andric if (MO.isExpr()) 8180b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_adr_pcrel_12, 8190b57cec5SDimitry Andric Fixups, STI); 8200b57cec5SDimitry Andric int64_t offset = MO.getImm(); 8210b57cec5SDimitry Andric uint32_t Val = 0x2000; 8220b57cec5SDimitry Andric 8230b57cec5SDimitry Andric int SoImmVal; 8240b57cec5SDimitry Andric if (offset == INT32_MIN) { 8250b57cec5SDimitry Andric Val = 0x1000; 8260b57cec5SDimitry Andric SoImmVal = 0; 8270b57cec5SDimitry Andric } else if (offset < 0) { 8280b57cec5SDimitry Andric Val = 0x1000; 8290b57cec5SDimitry Andric offset *= -1; 8300b57cec5SDimitry Andric SoImmVal = ARM_AM::getSOImmVal(offset); 8310b57cec5SDimitry Andric if(SoImmVal == -1) { 8320b57cec5SDimitry Andric Val = 0x2000; 8330b57cec5SDimitry Andric offset *= -1; 8340b57cec5SDimitry Andric SoImmVal = ARM_AM::getSOImmVal(offset); 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric } else { 8370b57cec5SDimitry Andric SoImmVal = ARM_AM::getSOImmVal(offset); 8380b57cec5SDimitry Andric if(SoImmVal == -1) { 8390b57cec5SDimitry Andric Val = 0x1000; 8400b57cec5SDimitry Andric offset *= -1; 8410b57cec5SDimitry Andric SoImmVal = ARM_AM::getSOImmVal(offset); 8420b57cec5SDimitry Andric } 8430b57cec5SDimitry Andric } 8440b57cec5SDimitry Andric 8450b57cec5SDimitry Andric assert(SoImmVal != -1 && "Not a valid so_imm value!"); 8460b57cec5SDimitry Andric 8470b57cec5SDimitry Andric Val |= SoImmVal; 8480b57cec5SDimitry Andric return Val; 8490b57cec5SDimitry Andric } 8500b57cec5SDimitry Andric 8510b57cec5SDimitry Andric /// getT2AdrLabelOpValue - Return encoding info for 12-bit immediate ADR label 8520b57cec5SDimitry Andric /// target. 8530b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 8540b57cec5SDimitry Andric getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 8550b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 8560b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 8570b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 8580b57cec5SDimitry Andric if (MO.isExpr()) 8590b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_adr_pcrel_12, 8600b57cec5SDimitry Andric Fixups, STI); 8610b57cec5SDimitry Andric int32_t Val = MO.getImm(); 8620b57cec5SDimitry Andric if (Val == INT32_MIN) 8630b57cec5SDimitry Andric Val = 0x1000; 8640b57cec5SDimitry Andric else if (Val < 0) { 8650b57cec5SDimitry Andric Val *= -1; 8660b57cec5SDimitry Andric Val |= 0x1000; 8670b57cec5SDimitry Andric } 8680b57cec5SDimitry Andric return Val; 8690b57cec5SDimitry Andric } 8700b57cec5SDimitry Andric 8710b57cec5SDimitry Andric /// getITMaskOpValue - Return the architectural encoding of an IT 8720b57cec5SDimitry Andric /// predication mask, given the MCOperand format. 8730b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 8740b57cec5SDimitry Andric getITMaskOpValue(const MCInst &MI, unsigned OpIdx, 8750b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 8760b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 8770b57cec5SDimitry Andric const MCOperand MaskMO = MI.getOperand(OpIdx); 8780b57cec5SDimitry Andric assert(MaskMO.isImm() && "Unexpected operand type!"); 8790b57cec5SDimitry Andric 8800b57cec5SDimitry Andric unsigned Mask = MaskMO.getImm(); 8810b57cec5SDimitry Andric 8820b57cec5SDimitry Andric // IT masks are encoded as a sequence of replacement low-order bits 8830b57cec5SDimitry Andric // for the condition code. So if the low bit of the starting 8840b57cec5SDimitry Andric // condition code is 1, then we have to flip all the bits above the 8850b57cec5SDimitry Andric // terminating bit (which is the lowest 1 bit). 8860b57cec5SDimitry Andric assert(OpIdx > 0 && "IT mask appears first!"); 8870b57cec5SDimitry Andric const MCOperand CondMO = MI.getOperand(OpIdx-1); 8880b57cec5SDimitry Andric assert(CondMO.isImm() && "Unexpected operand type!"); 8890b57cec5SDimitry Andric if (CondMO.getImm() & 1) { 8900b57cec5SDimitry Andric unsigned LowBit = Mask & -Mask; 8910b57cec5SDimitry Andric unsigned BitsAboveLowBit = 0xF & (-LowBit << 1); 8920b57cec5SDimitry Andric Mask ^= BitsAboveLowBit; 8930b57cec5SDimitry Andric } 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric return Mask; 8960b57cec5SDimitry Andric } 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric /// getThumbAdrLabelOpValue - Return encoding info for 8-bit immediate ADR label 8990b57cec5SDimitry Andric /// target. 9000b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 9010b57cec5SDimitry Andric getThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, 9020b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 9030b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 9040b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 9050b57cec5SDimitry Andric if (MO.isExpr()) 9060b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_thumb_adr_pcrel_10, 9070b57cec5SDimitry Andric Fixups, STI); 9080b57cec5SDimitry Andric return MO.getImm(); 9090b57cec5SDimitry Andric } 9100b57cec5SDimitry Andric 9110b57cec5SDimitry Andric /// getThumbAddrModeRegRegOpValue - Return encoding info for 'reg + reg' 9120b57cec5SDimitry Andric /// operand. 9130b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 9140b57cec5SDimitry Andric getThumbAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx, 9150b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &, 9160b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 9170b57cec5SDimitry Andric // [Rn, Rm] 9180b57cec5SDimitry Andric // {5-3} = Rm 9190b57cec5SDimitry Andric // {2-0} = Rn 9200b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpIdx); 9210b57cec5SDimitry Andric const MCOperand &MO2 = MI.getOperand(OpIdx + 1); 9220b57cec5SDimitry Andric unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(MO1.getReg()); 9230b57cec5SDimitry Andric unsigned Rm = CTX.getRegisterInfo()->getEncodingValue(MO2.getReg()); 9240b57cec5SDimitry Andric return (Rm << 3) | Rn; 9250b57cec5SDimitry Andric } 9260b57cec5SDimitry Andric 9270b57cec5SDimitry Andric /// getMVEShiftImmOpValue - Return encoding info for the 'sz:imm5' 9280b57cec5SDimitry Andric /// operand. 9290b57cec5SDimitry Andric uint32_t 9300b57cec5SDimitry Andric ARMMCCodeEmitter::getMVEShiftImmOpValue(const MCInst &MI, unsigned OpIdx, 9310b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 9320b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 9330b57cec5SDimitry Andric // {4-0} = szimm5 9340b57cec5SDimitry Andric // The value we are trying to encode is an immediate between either the 9350b57cec5SDimitry Andric // range of [1-7] or [1-15] depending on whether we are dealing with the 9360b57cec5SDimitry Andric // u8/s8 or the u16/s16 variants respectively. 9370b57cec5SDimitry Andric // This value is encoded as follows, if ShiftImm is the value within those 9380b57cec5SDimitry Andric // ranges then the encoding szimm5 = ShiftImm + size, where size is either 8 9390b57cec5SDimitry Andric // or 16. 9400b57cec5SDimitry Andric 9410b57cec5SDimitry Andric unsigned Size, ShiftImm; 9420b57cec5SDimitry Andric switch(MI.getOpcode()) { 9430b57cec5SDimitry Andric case ARM::MVE_VSHLL_imms16bh: 9440b57cec5SDimitry Andric case ARM::MVE_VSHLL_imms16th: 9450b57cec5SDimitry Andric case ARM::MVE_VSHLL_immu16bh: 9460b57cec5SDimitry Andric case ARM::MVE_VSHLL_immu16th: 9470b57cec5SDimitry Andric Size = 16; 9480b57cec5SDimitry Andric break; 9490b57cec5SDimitry Andric case ARM::MVE_VSHLL_imms8bh: 9500b57cec5SDimitry Andric case ARM::MVE_VSHLL_imms8th: 9510b57cec5SDimitry Andric case ARM::MVE_VSHLL_immu8bh: 9520b57cec5SDimitry Andric case ARM::MVE_VSHLL_immu8th: 9530b57cec5SDimitry Andric Size = 8; 9540b57cec5SDimitry Andric break; 9550b57cec5SDimitry Andric default: 9560b57cec5SDimitry Andric llvm_unreachable("Use of operand not supported by this instruction"); 9570b57cec5SDimitry Andric } 9580b57cec5SDimitry Andric ShiftImm = MI.getOperand(OpIdx).getImm(); 9590b57cec5SDimitry Andric return Size + ShiftImm; 9600b57cec5SDimitry Andric } 9610b57cec5SDimitry Andric 9620b57cec5SDimitry Andric /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' operand. 9630b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 9640b57cec5SDimitry Andric getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, 9650b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 9660b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 9670b57cec5SDimitry Andric // {17-13} = reg 9680b57cec5SDimitry Andric // {12} = (U)nsigned (add == '1', sub == '0') 9690b57cec5SDimitry Andric // {11-0} = imm12 970fe6060f1SDimitry Andric unsigned Reg = 0, Imm12 = 0; 9710b57cec5SDimitry Andric bool isAdd = true; 9720b57cec5SDimitry Andric // If The first operand isn't a register, we have a label reference. 9730b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 974fe6060f1SDimitry Andric if (MO.isReg()) { 975fe6060f1SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 976fe6060f1SDimitry Andric if (MO1.isImm()) { 977fe6060f1SDimitry Andric isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm12, Fixups, STI); 978fe6060f1SDimitry Andric } else if (MO1.isExpr()) { 979fe6060f1SDimitry Andric assert(!isThumb(STI) && !isThumb2(STI) && 980fe6060f1SDimitry Andric "Thumb mode requires different encoding"); 981fe6060f1SDimitry Andric Reg = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 9820b57cec5SDimitry Andric isAdd = false; // 'U' bit is set as part of the fixup. 983fe6060f1SDimitry Andric MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_ldst_abs_12); 984fe6060f1SDimitry Andric Fixups.push_back(MCFixup::create(0, MO1.getExpr(), Kind, MI.getLoc())); 985fe6060f1SDimitry Andric } 986fe6060f1SDimitry Andric } else if (MO.isExpr()) { 987fe6060f1SDimitry Andric Reg = CTX.getRegisterInfo()->getEncodingValue(ARM::PC); // Rn is PC. 988fe6060f1SDimitry Andric isAdd = false; // 'U' bit is set as part of the fixup. 9890b57cec5SDimitry Andric MCFixupKind Kind; 9900b57cec5SDimitry Andric if (isThumb2(STI)) 9910b57cec5SDimitry Andric Kind = MCFixupKind(ARM::fixup_t2_ldst_pcrel_12); 9920b57cec5SDimitry Andric else 9930b57cec5SDimitry Andric Kind = MCFixupKind(ARM::fixup_arm_ldst_pcrel_12); 994fe6060f1SDimitry Andric Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric ++MCNumCPRelocations; 9970b57cec5SDimitry Andric } else { 9980b57cec5SDimitry Andric Reg = ARM::PC; 9990b57cec5SDimitry Andric int32_t Offset = MO.getImm(); 10000b57cec5SDimitry Andric if (Offset == INT32_MIN) { 10010b57cec5SDimitry Andric Offset = 0; 10020b57cec5SDimitry Andric isAdd = false; 10030b57cec5SDimitry Andric } else if (Offset < 0) { 10040b57cec5SDimitry Andric Offset *= -1; 10050b57cec5SDimitry Andric isAdd = false; 10060b57cec5SDimitry Andric } 10070b57cec5SDimitry Andric Imm12 = Offset; 10080b57cec5SDimitry Andric } 10090b57cec5SDimitry Andric uint32_t Binary = Imm12 & 0xfff; 10100b57cec5SDimitry Andric // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 10110b57cec5SDimitry Andric if (isAdd) 10120b57cec5SDimitry Andric Binary |= (1 << 12); 10130b57cec5SDimitry Andric Binary |= (Reg << 13); 10140b57cec5SDimitry Andric return Binary; 10150b57cec5SDimitry Andric } 10160b57cec5SDimitry Andric 10170b57cec5SDimitry Andric template<unsigned Bits, unsigned Shift> 10180b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 10190b57cec5SDimitry Andric getT2ScaledImmOpValue(const MCInst &MI, unsigned OpIdx, 10200b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 10210b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 10220b57cec5SDimitry Andric // FIXME: The immediate operand should have already been encoded like this 10230b57cec5SDimitry Andric // before ever getting here. The encoder method should just need to combine 10240b57cec5SDimitry Andric // the MI operands for the register and the offset into a single 10250b57cec5SDimitry Andric // representation for the complex operand in the .td file. This isn't just 10260b57cec5SDimitry Andric // style, unfortunately. As-is, we can't represent the distinct encoding 10270b57cec5SDimitry Andric // for #-0. 10280b57cec5SDimitry Andric 10290b57cec5SDimitry Andric // {Bits} = (U)nsigned (add == '1', sub == '0') 10300b57cec5SDimitry Andric // {(Bits-1)-0} = immediate 10310b57cec5SDimitry Andric int32_t Imm = MI.getOperand(OpIdx).getImm(); 10320b57cec5SDimitry Andric bool isAdd = Imm >= 0; 10330b57cec5SDimitry Andric 10340b57cec5SDimitry Andric // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 10350b57cec5SDimitry Andric if (Imm < 0) 10360b57cec5SDimitry Andric Imm = -(uint32_t)Imm; 10370b57cec5SDimitry Andric 10380b57cec5SDimitry Andric Imm >>= Shift; 10390b57cec5SDimitry Andric 10400b57cec5SDimitry Andric uint32_t Binary = Imm & ((1U << Bits) - 1); 10410b57cec5SDimitry Andric // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 10420b57cec5SDimitry Andric if (isAdd) 10430b57cec5SDimitry Andric Binary |= (1U << Bits); 10440b57cec5SDimitry Andric return Binary; 10450b57cec5SDimitry Andric } 10460b57cec5SDimitry Andric 10470b57cec5SDimitry Andric /// getMveAddrModeRQOpValue - Return encoding info for 'reg, vreg' 10480b57cec5SDimitry Andric /// operand. 10490b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 10500b57cec5SDimitry Andric getMveAddrModeRQOpValue(const MCInst &MI, unsigned OpIdx, 10510b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 10520b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 10530b57cec5SDimitry Andric // {6-3} Rn 10540b57cec5SDimitry Andric // {2-0} Qm 10550b57cec5SDimitry Andric const MCOperand &M0 = MI.getOperand(OpIdx); 10560b57cec5SDimitry Andric const MCOperand &M1 = MI.getOperand(OpIdx + 1); 10570b57cec5SDimitry Andric 10580b57cec5SDimitry Andric unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(M0.getReg()); 10590b57cec5SDimitry Andric unsigned Qm = CTX.getRegisterInfo()->getEncodingValue(M1.getReg()); 10600b57cec5SDimitry Andric 10610b57cec5SDimitry Andric assert(Qm < 8 && "Qm is supposed to be encodable in 3 bits"); 10620b57cec5SDimitry Andric 10630b57cec5SDimitry Andric return (Rn << 3) | Qm; 10640b57cec5SDimitry Andric } 10650b57cec5SDimitry Andric 10660b57cec5SDimitry Andric /// getMveAddrModeRQOpValue - Return encoding info for 'reg, vreg' 10670b57cec5SDimitry Andric /// operand. 10680b57cec5SDimitry Andric template<int shift> 10690b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 10700b57cec5SDimitry Andric getMveAddrModeQOpValue(const MCInst &MI, unsigned OpIdx, 10710b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 10720b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 10730b57cec5SDimitry Andric // {10-8} Qm 10740b57cec5SDimitry Andric // {7-0} Imm 10750b57cec5SDimitry Andric const MCOperand &M0 = MI.getOperand(OpIdx); 10760b57cec5SDimitry Andric const MCOperand &M1 = MI.getOperand(OpIdx + 1); 10770b57cec5SDimitry Andric 10780b57cec5SDimitry Andric unsigned Qm = CTX.getRegisterInfo()->getEncodingValue(M0.getReg()); 10790b57cec5SDimitry Andric int32_t Imm = M1.getImm(); 10800b57cec5SDimitry Andric 10810b57cec5SDimitry Andric bool isAdd = Imm >= 0; 10820b57cec5SDimitry Andric 10830b57cec5SDimitry Andric Imm >>= shift; 10840b57cec5SDimitry Andric 10850b57cec5SDimitry Andric if (!isAdd) 10860b57cec5SDimitry Andric Imm = -(uint32_t)Imm; 10870b57cec5SDimitry Andric 10880b57cec5SDimitry Andric Imm &= 0x7f; 10890b57cec5SDimitry Andric 10900b57cec5SDimitry Andric if (isAdd) 10910b57cec5SDimitry Andric Imm |= 0x80; 10920b57cec5SDimitry Andric 10930b57cec5SDimitry Andric assert(Qm < 8 && "Qm is supposed to be encodable in 3 bits"); 10940b57cec5SDimitry Andric 10950b57cec5SDimitry Andric return (Qm << 8) | Imm; 10960b57cec5SDimitry Andric } 10970b57cec5SDimitry Andric 10980b57cec5SDimitry Andric /// getT2AddrModeImm8s4OpValue - Return encoding info for 10990b57cec5SDimitry Andric /// 'reg +/- imm8<<2' operand. 11000b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 11010b57cec5SDimitry Andric getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx, 11020b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 11030b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 11040b57cec5SDimitry Andric // {12-9} = reg 11050b57cec5SDimitry Andric // {8} = (U)nsigned (add == '1', sub == '0') 11060b57cec5SDimitry Andric // {7-0} = imm8 11070b57cec5SDimitry Andric unsigned Reg, Imm8; 11080b57cec5SDimitry Andric bool isAdd = true; 11090b57cec5SDimitry Andric // If The first operand isn't a register, we have a label reference. 11100b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 11110b57cec5SDimitry Andric if (!MO.isReg()) { 11120b57cec5SDimitry Andric Reg = CTX.getRegisterInfo()->getEncodingValue(ARM::PC); // Rn is PC. 11130b57cec5SDimitry Andric Imm8 = 0; 11140b57cec5SDimitry Andric isAdd = false ; // 'U' bit is set as part of the fixup. 11150b57cec5SDimitry Andric 11160b57cec5SDimitry Andric assert(MO.isExpr() && "Unexpected machine operand type!"); 11170b57cec5SDimitry Andric const MCExpr *Expr = MO.getExpr(); 11180b57cec5SDimitry Andric MCFixupKind Kind = MCFixupKind(ARM::fixup_t2_pcrel_10); 11190b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); 11200b57cec5SDimitry Andric 11210b57cec5SDimitry Andric ++MCNumCPRelocations; 11220b57cec5SDimitry Andric } else 11230b57cec5SDimitry Andric isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups, STI); 11240b57cec5SDimitry Andric 11250b57cec5SDimitry Andric // FIXME: The immediate operand should have already been encoded like this 11260b57cec5SDimitry Andric // before ever getting here. The encoder method should just need to combine 11270b57cec5SDimitry Andric // the MI operands for the register and the offset into a single 11280b57cec5SDimitry Andric // representation for the complex operand in the .td file. This isn't just 11290b57cec5SDimitry Andric // style, unfortunately. As-is, we can't represent the distinct encoding 11300b57cec5SDimitry Andric // for #-0. 1131349cc55cSDimitry Andric assert(((Imm8 & 0x3) == 0) && "Not a valid immediate!"); 11320b57cec5SDimitry Andric uint32_t Binary = (Imm8 >> 2) & 0xff; 11330b57cec5SDimitry Andric // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 11340b57cec5SDimitry Andric if (isAdd) 11350b57cec5SDimitry Andric Binary |= (1 << 8); 11360b57cec5SDimitry Andric Binary |= (Reg << 9); 11370b57cec5SDimitry Andric return Binary; 11380b57cec5SDimitry Andric } 11390b57cec5SDimitry Andric 11400b57cec5SDimitry Andric /// getT2AddrModeImm7s4OpValue - Return encoding info for 11410b57cec5SDimitry Andric /// 'reg +/- imm7<<2' operand. 11420b57cec5SDimitry Andric uint32_t 11430b57cec5SDimitry Andric ARMMCCodeEmitter::getT2AddrModeImm7s4OpValue(const MCInst &MI, unsigned OpIdx, 11440b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 11450b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 11460b57cec5SDimitry Andric // {11-8} = reg 11470b57cec5SDimitry Andric // {7} = (A)dd (add == '1', sub == '0') 11480b57cec5SDimitry Andric // {6-0} = imm7 11490b57cec5SDimitry Andric unsigned Reg, Imm7; 11500b57cec5SDimitry Andric // If The first operand isn't a register, we have a label reference. 11510b57cec5SDimitry Andric bool isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm7, Fixups, STI); 11520b57cec5SDimitry Andric 11530b57cec5SDimitry Andric // FIXME: The immediate operand should have already been encoded like this 11540b57cec5SDimitry Andric // before ever getting here. The encoder method should just need to combine 11550b57cec5SDimitry Andric // the MI operands for the register and the offset into a single 11560b57cec5SDimitry Andric // representation for the complex operand in the .td file. This isn't just 11570b57cec5SDimitry Andric // style, unfortunately. As-is, we can't represent the distinct encoding 11580b57cec5SDimitry Andric // for #-0. 11590b57cec5SDimitry Andric uint32_t Binary = (Imm7 >> 2) & 0xff; 11600b57cec5SDimitry Andric // Immediate is always encoded as positive. The 'A' bit controls add vs sub. 11610b57cec5SDimitry Andric if (isAdd) 11620b57cec5SDimitry Andric Binary |= (1 << 7); 11630b57cec5SDimitry Andric Binary |= (Reg << 8); 11640b57cec5SDimitry Andric return Binary; 11650b57cec5SDimitry Andric } 11660b57cec5SDimitry Andric 11670b57cec5SDimitry Andric /// getT2AddrModeImm0_1020s4OpValue - Return encoding info for 11680b57cec5SDimitry Andric /// 'reg + imm8<<2' operand. 11690b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 11700b57cec5SDimitry Andric getT2AddrModeImm0_1020s4OpValue(const MCInst &MI, unsigned OpIdx, 11710b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 11720b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 11730b57cec5SDimitry Andric // {11-8} = reg 11740b57cec5SDimitry Andric // {7-0} = imm8 11750b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 11760b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 11770b57cec5SDimitry Andric unsigned Reg = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 11780b57cec5SDimitry Andric unsigned Imm8 = MO1.getImm(); 11790b57cec5SDimitry Andric return (Reg << 8) | Imm8; 11800b57cec5SDimitry Andric } 11810b57cec5SDimitry Andric 118206c3fb27SDimitry Andric uint32_t ARMMCCodeEmitter::getHiLoImmOpValue(const MCInst &MI, unsigned OpIdx, 11830b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 11840b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 11850b57cec5SDimitry Andric // {20-16} = imm{15-12} 11860b57cec5SDimitry Andric // {11-0} = imm{11-0} 11870b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 11880b57cec5SDimitry Andric if (MO.isImm()) 118906c3fb27SDimitry Andric // Hi / lo bits already extracted during earlier passes. 11900b57cec5SDimitry Andric return static_cast<unsigned>(MO.getImm()); 11910b57cec5SDimitry Andric 119206c3fb27SDimitry Andric // Handle :upper16:, :lower16:, :upper8_15:, :upper0_7:, :lower8_15: 119306c3fb27SDimitry Andric // :lower0_7: assembly prefixes. 11940b57cec5SDimitry Andric const MCExpr *E = MO.getExpr(); 11950b57cec5SDimitry Andric MCFixupKind Kind; 11960b57cec5SDimitry Andric if (E->getKind() == MCExpr::Target) { 11970b57cec5SDimitry Andric const ARMMCExpr *ARM16Expr = cast<ARMMCExpr>(E); 11980b57cec5SDimitry Andric E = ARM16Expr->getSubExpr(); 11990b57cec5SDimitry Andric 12000b57cec5SDimitry Andric if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(E)) { 12010b57cec5SDimitry Andric const int64_t Value = MCE->getValue(); 12020b57cec5SDimitry Andric if (Value > UINT32_MAX) 12030b57cec5SDimitry Andric report_fatal_error("constant value truncated (limited to 32-bit)"); 12040b57cec5SDimitry Andric 12050b57cec5SDimitry Andric switch (ARM16Expr->getKind()) { 12060b57cec5SDimitry Andric case ARMMCExpr::VK_ARM_HI16: 12070b57cec5SDimitry Andric return (int32_t(Value) & 0xffff0000) >> 16; 12080b57cec5SDimitry Andric case ARMMCExpr::VK_ARM_LO16: 12090b57cec5SDimitry Andric return (int32_t(Value) & 0x0000ffff); 121006c3fb27SDimitry Andric 121106c3fb27SDimitry Andric case ARMMCExpr::VK_ARM_HI_8_15: 121206c3fb27SDimitry Andric return (int32_t(Value) & 0xff000000) >> 24; 121306c3fb27SDimitry Andric case ARMMCExpr::VK_ARM_HI_0_7: 121406c3fb27SDimitry Andric return (int32_t(Value) & 0x00ff0000) >> 16; 121506c3fb27SDimitry Andric case ARMMCExpr::VK_ARM_LO_8_15: 121606c3fb27SDimitry Andric return (int32_t(Value) & 0x0000ff00) >> 8; 121706c3fb27SDimitry Andric case ARMMCExpr::VK_ARM_LO_0_7: 121806c3fb27SDimitry Andric return (int32_t(Value) & 0x000000ff); 121906c3fb27SDimitry Andric 12200b57cec5SDimitry Andric default: llvm_unreachable("Unsupported ARMFixup"); 12210b57cec5SDimitry Andric } 12220b57cec5SDimitry Andric } 12230b57cec5SDimitry Andric 12240b57cec5SDimitry Andric switch (ARM16Expr->getKind()) { 12250b57cec5SDimitry Andric default: llvm_unreachable("Unsupported ARMFixup"); 12260b57cec5SDimitry Andric case ARMMCExpr::VK_ARM_HI16: 12270b57cec5SDimitry Andric Kind = MCFixupKind(isThumb(STI) ? ARM::fixup_t2_movt_hi16 12280b57cec5SDimitry Andric : ARM::fixup_arm_movt_hi16); 12290b57cec5SDimitry Andric break; 12300b57cec5SDimitry Andric case ARMMCExpr::VK_ARM_LO16: 12310b57cec5SDimitry Andric Kind = MCFixupKind(isThumb(STI) ? ARM::fixup_t2_movw_lo16 12320b57cec5SDimitry Andric : ARM::fixup_arm_movw_lo16); 12330b57cec5SDimitry Andric break; 123406c3fb27SDimitry Andric case ARMMCExpr::VK_ARM_HI_8_15: 123506c3fb27SDimitry Andric if (!isThumb(STI)) 123606c3fb27SDimitry Andric llvm_unreachable(":upper_8_15: not supported in Arm state"); 123706c3fb27SDimitry Andric Kind = MCFixupKind(ARM::fixup_arm_thumb_upper_8_15); 123806c3fb27SDimitry Andric break; 123906c3fb27SDimitry Andric case ARMMCExpr::VK_ARM_HI_0_7: 124006c3fb27SDimitry Andric if (!isThumb(STI)) 124106c3fb27SDimitry Andric llvm_unreachable(":upper_0_7: not supported in Arm state"); 124206c3fb27SDimitry Andric Kind = MCFixupKind(ARM::fixup_arm_thumb_upper_0_7); 124306c3fb27SDimitry Andric break; 124406c3fb27SDimitry Andric case ARMMCExpr::VK_ARM_LO_8_15: 124506c3fb27SDimitry Andric if (!isThumb(STI)) 124606c3fb27SDimitry Andric llvm_unreachable(":lower_8_15: not supported in Arm state"); 124706c3fb27SDimitry Andric Kind = MCFixupKind(ARM::fixup_arm_thumb_lower_8_15); 124806c3fb27SDimitry Andric break; 124906c3fb27SDimitry Andric case ARMMCExpr::VK_ARM_LO_0_7: 125006c3fb27SDimitry Andric if (!isThumb(STI)) 125106c3fb27SDimitry Andric llvm_unreachable(":lower_0_7: not supported in Arm state"); 125206c3fb27SDimitry Andric Kind = MCFixupKind(ARM::fixup_arm_thumb_lower_0_7); 125306c3fb27SDimitry Andric break; 12540b57cec5SDimitry Andric } 12550b57cec5SDimitry Andric 12560b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, E, Kind, MI.getLoc())); 12570b57cec5SDimitry Andric return 0; 12580b57cec5SDimitry Andric } 125906c3fb27SDimitry Andric // If the expression doesn't have :upper16:, :lower16: on it, it's just a 126006c3fb27SDimitry Andric // plain immediate expression, previously those evaluated to the lower 16 bits 126106c3fb27SDimitry Andric // of the expression regardless of whether we have a movt or a movw, but that 126206c3fb27SDimitry Andric // led to misleadingly results. This is disallowed in the AsmParser in 126306c3fb27SDimitry Andric // validateInstruction() so this should never happen. The same holds for 126406c3fb27SDimitry Andric // thumb1 :upper8_15:, :upper0_7:, lower8_15: or :lower0_7: with movs or adds. 126506c3fb27SDimitry Andric llvm_unreachable("expression without :upper16:, :lower16:, :upper8_15:," 126606c3fb27SDimitry Andric ":upper0_7:, lower8_15: or :lower0_7:"); 12670b57cec5SDimitry Andric } 12680b57cec5SDimitry Andric 12690b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 12700b57cec5SDimitry Andric getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx, 12710b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 12720b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 12730b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 12740b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpIdx+1); 12750b57cec5SDimitry Andric const MCOperand &MO2 = MI.getOperand(OpIdx+2); 12760b57cec5SDimitry Andric unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 12770b57cec5SDimitry Andric unsigned Rm = CTX.getRegisterInfo()->getEncodingValue(MO1.getReg()); 12780b57cec5SDimitry Andric unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()); 12790b57cec5SDimitry Andric bool isAdd = ARM_AM::getAM2Op(MO2.getImm()) == ARM_AM::add; 12800b57cec5SDimitry Andric ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(MO2.getImm()); 12810b57cec5SDimitry Andric unsigned SBits = getShiftOp(ShOp); 12820b57cec5SDimitry Andric 12830b57cec5SDimitry Andric // While "lsr #32" and "asr #32" exist, they are encoded with a 0 in the shift 12840b57cec5SDimitry Andric // amount. However, it would be an easy mistake to make so check here. 12850b57cec5SDimitry Andric assert((ShImm & ~0x1f) == 0 && "Out of range shift amount"); 12860b57cec5SDimitry Andric 12870b57cec5SDimitry Andric // {16-13} = Rn 12880b57cec5SDimitry Andric // {12} = isAdd 12890b57cec5SDimitry Andric // {11-0} = shifter 12900b57cec5SDimitry Andric // {3-0} = Rm 12910b57cec5SDimitry Andric // {4} = 0 12920b57cec5SDimitry Andric // {6-5} = type 12930b57cec5SDimitry Andric // {11-7} = imm 12940b57cec5SDimitry Andric uint32_t Binary = Rm; 12950b57cec5SDimitry Andric Binary |= Rn << 13; 12960b57cec5SDimitry Andric Binary |= SBits << 5; 12970b57cec5SDimitry Andric Binary |= ShImm << 7; 12980b57cec5SDimitry Andric if (isAdd) 12990b57cec5SDimitry Andric Binary |= 1 << 12; 13000b57cec5SDimitry Andric return Binary; 13010b57cec5SDimitry Andric } 13020b57cec5SDimitry Andric 13030b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 13040b57cec5SDimitry Andric getAddrMode2OffsetOpValue(const MCInst &MI, unsigned OpIdx, 13050b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 13060b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 13070b57cec5SDimitry Andric // {13} 1 == imm12, 0 == Rm 13080b57cec5SDimitry Andric // {12} isAdd 13090b57cec5SDimitry Andric // {11-0} imm12/Rm 13100b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 13110b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpIdx+1); 13120b57cec5SDimitry Andric unsigned Imm = MO1.getImm(); 13130b57cec5SDimitry Andric bool isAdd = ARM_AM::getAM2Op(Imm) == ARM_AM::add; 13140b57cec5SDimitry Andric bool isReg = MO.getReg() != 0; 13150b57cec5SDimitry Andric uint32_t Binary = ARM_AM::getAM2Offset(Imm); 13160b57cec5SDimitry Andric // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm12 13170b57cec5SDimitry Andric if (isReg) { 13180b57cec5SDimitry Andric ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(Imm); 13190b57cec5SDimitry Andric Binary <<= 7; // Shift amount is bits [11:7] 13200b57cec5SDimitry Andric Binary |= getShiftOp(ShOp) << 5; // Shift type is bits [6:5] 13210b57cec5SDimitry Andric Binary |= CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); // Rm is bits [3:0] 13220b57cec5SDimitry Andric } 13230b57cec5SDimitry Andric return Binary | (isAdd << 12) | (isReg << 13); 13240b57cec5SDimitry Andric } 13250b57cec5SDimitry Andric 13260b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 13270b57cec5SDimitry Andric getPostIdxRegOpValue(const MCInst &MI, unsigned OpIdx, 13280b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 13290b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 13300b57cec5SDimitry Andric // {4} isAdd 13310b57cec5SDimitry Andric // {3-0} Rm 13320b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 13330b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpIdx+1); 13340b57cec5SDimitry Andric bool isAdd = MO1.getImm() != 0; 13350b57cec5SDimitry Andric return CTX.getRegisterInfo()->getEncodingValue(MO.getReg()) | (isAdd << 4); 13360b57cec5SDimitry Andric } 13370b57cec5SDimitry Andric 13380b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 13390b57cec5SDimitry Andric getAddrMode3OffsetOpValue(const MCInst &MI, unsigned OpIdx, 13400b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 13410b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 13420b57cec5SDimitry Andric // {9} 1 == imm8, 0 == Rm 13430b57cec5SDimitry Andric // {8} isAdd 13440b57cec5SDimitry Andric // {7-4} imm7_4/zero 13450b57cec5SDimitry Andric // {3-0} imm3_0/Rm 13460b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 13470b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpIdx+1); 13480b57cec5SDimitry Andric unsigned Imm = MO1.getImm(); 13490b57cec5SDimitry Andric bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add; 13500b57cec5SDimitry Andric bool isImm = MO.getReg() == 0; 13510b57cec5SDimitry Andric uint32_t Imm8 = ARM_AM::getAM3Offset(Imm); 13520b57cec5SDimitry Andric // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8 13530b57cec5SDimitry Andric if (!isImm) 13540b57cec5SDimitry Andric Imm8 = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 13550b57cec5SDimitry Andric return Imm8 | (isAdd << 8) | (isImm << 9); 13560b57cec5SDimitry Andric } 13570b57cec5SDimitry Andric 13580b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 13590b57cec5SDimitry Andric getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx, 13600b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 13610b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 13620b57cec5SDimitry Andric // {13} 1 == imm8, 0 == Rm 13630b57cec5SDimitry Andric // {12-9} Rn 13640b57cec5SDimitry Andric // {8} isAdd 13650b57cec5SDimitry Andric // {7-4} imm7_4/zero 13660b57cec5SDimitry Andric // {3-0} imm3_0/Rm 13670b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 13680b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpIdx+1); 13690b57cec5SDimitry Andric const MCOperand &MO2 = MI.getOperand(OpIdx+2); 13700b57cec5SDimitry Andric 13710b57cec5SDimitry Andric // If The first operand isn't a register, we have a label reference. 13720b57cec5SDimitry Andric if (!MO.isReg()) { 13730b57cec5SDimitry Andric unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(ARM::PC); // Rn is PC. 13740b57cec5SDimitry Andric 13750b57cec5SDimitry Andric assert(MO.isExpr() && "Unexpected machine operand type!"); 13760b57cec5SDimitry Andric const MCExpr *Expr = MO.getExpr(); 13770b57cec5SDimitry Andric MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_10_unscaled); 13780b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); 13790b57cec5SDimitry Andric 13800b57cec5SDimitry Andric ++MCNumCPRelocations; 13810b57cec5SDimitry Andric return (Rn << 9) | (1 << 13); 13820b57cec5SDimitry Andric } 13830b57cec5SDimitry Andric unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 13840b57cec5SDimitry Andric unsigned Imm = MO2.getImm(); 13850b57cec5SDimitry Andric bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add; 13860b57cec5SDimitry Andric bool isImm = MO1.getReg() == 0; 13870b57cec5SDimitry Andric uint32_t Imm8 = ARM_AM::getAM3Offset(Imm); 13880b57cec5SDimitry Andric // if reg +/- reg, Rm will be non-zero. Otherwise, we have reg +/- imm8 13890b57cec5SDimitry Andric if (!isImm) 13900b57cec5SDimitry Andric Imm8 = CTX.getRegisterInfo()->getEncodingValue(MO1.getReg()); 13910b57cec5SDimitry Andric return (Rn << 9) | Imm8 | (isAdd << 8) | (isImm << 13); 13920b57cec5SDimitry Andric } 13930b57cec5SDimitry Andric 13940b57cec5SDimitry Andric /// getAddrModeThumbSPOpValue - Encode the t_addrmode_sp operands. 13950b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 13960b57cec5SDimitry Andric getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx, 13970b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 13980b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 13990b57cec5SDimitry Andric // [SP, #imm] 14000b57cec5SDimitry Andric // {7-0} = imm8 14010b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 14020b57cec5SDimitry Andric assert(MI.getOperand(OpIdx).getReg() == ARM::SP && 14030b57cec5SDimitry Andric "Unexpected base register!"); 14040b57cec5SDimitry Andric 14050b57cec5SDimitry Andric // The immediate is already shifted for the implicit zeroes, so no change 14060b57cec5SDimitry Andric // here. 14070b57cec5SDimitry Andric return MO1.getImm() & 0xff; 14080b57cec5SDimitry Andric } 14090b57cec5SDimitry Andric 14100b57cec5SDimitry Andric /// getAddrModeISOpValue - Encode the t_addrmode_is# operands. 14110b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 14120b57cec5SDimitry Andric getAddrModeISOpValue(const MCInst &MI, unsigned OpIdx, 14130b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 14140b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 14150b57cec5SDimitry Andric // [Rn, #imm] 14160b57cec5SDimitry Andric // {7-3} = imm5 14170b57cec5SDimitry Andric // {2-0} = Rn 14180b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 14190b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 14200b57cec5SDimitry Andric unsigned Rn = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 14210b57cec5SDimitry Andric unsigned Imm5 = MO1.getImm(); 14220b57cec5SDimitry Andric return ((Imm5 & 0x1f) << 3) | Rn; 14230b57cec5SDimitry Andric } 14240b57cec5SDimitry Andric 14250b57cec5SDimitry Andric /// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands. 14260b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 14270b57cec5SDimitry Andric getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx, 14280b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 14290b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 14300b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 14310b57cec5SDimitry Andric if (MO.isExpr()) 14320b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cp, Fixups, STI); 14330b57cec5SDimitry Andric return (MO.getImm() >> 2); 14340b57cec5SDimitry Andric } 14350b57cec5SDimitry Andric 14360b57cec5SDimitry Andric /// getAddrMode5OpValue - Return encoding info for 'reg +/- (imm8 << 2)' operand. 14370b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 14380b57cec5SDimitry Andric getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, 14390b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 14400b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 14410b57cec5SDimitry Andric // {12-9} = reg 14420b57cec5SDimitry Andric // {8} = (U)nsigned (add == '1', sub == '0') 14430b57cec5SDimitry Andric // {7-0} = imm8 14440b57cec5SDimitry Andric unsigned Reg, Imm8; 14450b57cec5SDimitry Andric bool isAdd; 14460b57cec5SDimitry Andric // If The first operand isn't a register, we have a label reference. 14470b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 14480b57cec5SDimitry Andric if (!MO.isReg()) { 14490b57cec5SDimitry Andric Reg = CTX.getRegisterInfo()->getEncodingValue(ARM::PC); // Rn is PC. 14500b57cec5SDimitry Andric Imm8 = 0; 14510b57cec5SDimitry Andric isAdd = false; // 'U' bit is handled as part of the fixup. 14520b57cec5SDimitry Andric 14530b57cec5SDimitry Andric assert(MO.isExpr() && "Unexpected machine operand type!"); 14540b57cec5SDimitry Andric const MCExpr *Expr = MO.getExpr(); 14550b57cec5SDimitry Andric MCFixupKind Kind; 14560b57cec5SDimitry Andric if (isThumb2(STI)) 14570b57cec5SDimitry Andric Kind = MCFixupKind(ARM::fixup_t2_pcrel_10); 14580b57cec5SDimitry Andric else 14590b57cec5SDimitry Andric Kind = MCFixupKind(ARM::fixup_arm_pcrel_10); 14600b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); 14610b57cec5SDimitry Andric 14620b57cec5SDimitry Andric ++MCNumCPRelocations; 14630b57cec5SDimitry Andric } else { 14640b57cec5SDimitry Andric EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups, STI); 14650b57cec5SDimitry Andric isAdd = ARM_AM::getAM5Op(Imm8) == ARM_AM::add; 14660b57cec5SDimitry Andric } 14670b57cec5SDimitry Andric 14680b57cec5SDimitry Andric uint32_t Binary = ARM_AM::getAM5Offset(Imm8); 14690b57cec5SDimitry Andric // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 14700b57cec5SDimitry Andric if (isAdd) 14710b57cec5SDimitry Andric Binary |= (1 << 8); 14720b57cec5SDimitry Andric Binary |= (Reg << 9); 14730b57cec5SDimitry Andric return Binary; 14740b57cec5SDimitry Andric } 14750b57cec5SDimitry Andric 14760b57cec5SDimitry Andric /// getAddrMode5FP16OpValue - Return encoding info for 'reg +/- (imm8 << 1)' operand. 14770b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 14780b57cec5SDimitry Andric getAddrMode5FP16OpValue(const MCInst &MI, unsigned OpIdx, 14790b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 14800b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 14810b57cec5SDimitry Andric // {12-9} = reg 14820b57cec5SDimitry Andric // {8} = (U)nsigned (add == '1', sub == '0') 14830b57cec5SDimitry Andric // {7-0} = imm8 14840b57cec5SDimitry Andric unsigned Reg, Imm8; 14850b57cec5SDimitry Andric bool isAdd; 14860b57cec5SDimitry Andric // If The first operand isn't a register, we have a label reference. 14870b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 14880b57cec5SDimitry Andric if (!MO.isReg()) { 14890b57cec5SDimitry Andric Reg = CTX.getRegisterInfo()->getEncodingValue(ARM::PC); // Rn is PC. 14900b57cec5SDimitry Andric Imm8 = 0; 14910b57cec5SDimitry Andric isAdd = false; // 'U' bit is handled as part of the fixup. 14920b57cec5SDimitry Andric 14930b57cec5SDimitry Andric assert(MO.isExpr() && "Unexpected machine operand type!"); 14940b57cec5SDimitry Andric const MCExpr *Expr = MO.getExpr(); 14950b57cec5SDimitry Andric MCFixupKind Kind; 14960b57cec5SDimitry Andric if (isThumb2(STI)) 14970b57cec5SDimitry Andric Kind = MCFixupKind(ARM::fixup_t2_pcrel_9); 14980b57cec5SDimitry Andric else 14990b57cec5SDimitry Andric Kind = MCFixupKind(ARM::fixup_arm_pcrel_9); 15000b57cec5SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc())); 15010b57cec5SDimitry Andric 15020b57cec5SDimitry Andric ++MCNumCPRelocations; 15030b57cec5SDimitry Andric } else { 15040b57cec5SDimitry Andric EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups, STI); 15050b57cec5SDimitry Andric isAdd = ARM_AM::getAM5Op(Imm8) == ARM_AM::add; 15060b57cec5SDimitry Andric } 15070b57cec5SDimitry Andric 15080b57cec5SDimitry Andric uint32_t Binary = ARM_AM::getAM5Offset(Imm8); 15090b57cec5SDimitry Andric // Immediate is always encoded as positive. The 'U' bit controls add vs sub. 15100b57cec5SDimitry Andric if (isAdd) 15110b57cec5SDimitry Andric Binary |= (1 << 8); 15120b57cec5SDimitry Andric Binary |= (Reg << 9); 15130b57cec5SDimitry Andric return Binary; 15140b57cec5SDimitry Andric } 15150b57cec5SDimitry Andric 15160b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 15170b57cec5SDimitry Andric getSORegRegOpValue(const MCInst &MI, unsigned OpIdx, 15180b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 15190b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 15200b57cec5SDimitry Andric // Sub-operands are [reg, reg, imm]. The first register is Rm, the reg to be 15210b57cec5SDimitry Andric // shifted. The second is Rs, the amount to shift by, and the third specifies 15220b57cec5SDimitry Andric // the type of the shift. 15230b57cec5SDimitry Andric // 15240b57cec5SDimitry Andric // {3-0} = Rm. 15250b57cec5SDimitry Andric // {4} = 1 15260b57cec5SDimitry Andric // {6-5} = type 15270b57cec5SDimitry Andric // {11-8} = Rs 15280b57cec5SDimitry Andric // {7} = 0 15290b57cec5SDimitry Andric 15300b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 15310b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 15320b57cec5SDimitry Andric const MCOperand &MO2 = MI.getOperand(OpIdx + 2); 15330b57cec5SDimitry Andric ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm()); 15340b57cec5SDimitry Andric 15350b57cec5SDimitry Andric // Encode Rm. 15360b57cec5SDimitry Andric unsigned Binary = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 15370b57cec5SDimitry Andric 15380b57cec5SDimitry Andric // Encode the shift opcode. 15390b57cec5SDimitry Andric unsigned SBits = 0; 15400b57cec5SDimitry Andric unsigned Rs = MO1.getReg(); 15410b57cec5SDimitry Andric if (Rs) { 15420b57cec5SDimitry Andric // Set shift operand (bit[7:4]). 15430b57cec5SDimitry Andric // LSL - 0001 15440b57cec5SDimitry Andric // LSR - 0011 15450b57cec5SDimitry Andric // ASR - 0101 15460b57cec5SDimitry Andric // ROR - 0111 15470b57cec5SDimitry Andric switch (SOpc) { 15480b57cec5SDimitry Andric default: llvm_unreachable("Unknown shift opc!"); 15490b57cec5SDimitry Andric case ARM_AM::lsl: SBits = 0x1; break; 15500b57cec5SDimitry Andric case ARM_AM::lsr: SBits = 0x3; break; 15510b57cec5SDimitry Andric case ARM_AM::asr: SBits = 0x5; break; 15520b57cec5SDimitry Andric case ARM_AM::ror: SBits = 0x7; break; 15530b57cec5SDimitry Andric } 15540b57cec5SDimitry Andric } 15550b57cec5SDimitry Andric 15560b57cec5SDimitry Andric Binary |= SBits << 4; 15570b57cec5SDimitry Andric 15580b57cec5SDimitry Andric // Encode the shift operation Rs. 15590b57cec5SDimitry Andric // Encode Rs bit[11:8]. 15600b57cec5SDimitry Andric assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0); 15610b57cec5SDimitry Andric return Binary | (CTX.getRegisterInfo()->getEncodingValue(Rs) << ARMII::RegRsShift); 15620b57cec5SDimitry Andric } 15630b57cec5SDimitry Andric 15640b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 15650b57cec5SDimitry Andric getSORegImmOpValue(const MCInst &MI, unsigned OpIdx, 15660b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 15670b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 15680b57cec5SDimitry Andric // Sub-operands are [reg, imm]. The first register is Rm, the reg to be 15690b57cec5SDimitry Andric // shifted. The second is the amount to shift by. 15700b57cec5SDimitry Andric // 15710b57cec5SDimitry Andric // {3-0} = Rm. 15720b57cec5SDimitry Andric // {4} = 0 15730b57cec5SDimitry Andric // {6-5} = type 15740b57cec5SDimitry Andric // {11-7} = imm 15750b57cec5SDimitry Andric 15760b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 15770b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 15780b57cec5SDimitry Andric ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO1.getImm()); 15790b57cec5SDimitry Andric 15800b57cec5SDimitry Andric // Encode Rm. 15810b57cec5SDimitry Andric unsigned Binary = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 15820b57cec5SDimitry Andric 15830b57cec5SDimitry Andric // Encode the shift opcode. 15840b57cec5SDimitry Andric unsigned SBits = 0; 15850b57cec5SDimitry Andric 15860b57cec5SDimitry Andric // Set shift operand (bit[6:4]). 15870b57cec5SDimitry Andric // LSL - 000 15880b57cec5SDimitry Andric // LSR - 010 15890b57cec5SDimitry Andric // ASR - 100 15900b57cec5SDimitry Andric // ROR - 110 15910b57cec5SDimitry Andric // RRX - 110 and bit[11:8] clear. 15920b57cec5SDimitry Andric switch (SOpc) { 15930b57cec5SDimitry Andric default: llvm_unreachable("Unknown shift opc!"); 15940b57cec5SDimitry Andric case ARM_AM::lsl: SBits = 0x0; break; 15950b57cec5SDimitry Andric case ARM_AM::lsr: SBits = 0x2; break; 15960b57cec5SDimitry Andric case ARM_AM::asr: SBits = 0x4; break; 15970b57cec5SDimitry Andric case ARM_AM::ror: SBits = 0x6; break; 15980b57cec5SDimitry Andric case ARM_AM::rrx: 15990b57cec5SDimitry Andric Binary |= 0x60; 16000b57cec5SDimitry Andric return Binary; 16010b57cec5SDimitry Andric } 16020b57cec5SDimitry Andric 16030b57cec5SDimitry Andric // Encode shift_imm bit[11:7]. 16040b57cec5SDimitry Andric Binary |= SBits << 4; 16050b57cec5SDimitry Andric unsigned Offset = ARM_AM::getSORegOffset(MO1.getImm()); 16060b57cec5SDimitry Andric assert(Offset < 32 && "Offset must be in range 0-31!"); 16070b57cec5SDimitry Andric return Binary | (Offset << 7); 16080b57cec5SDimitry Andric } 16090b57cec5SDimitry Andric 16100b57cec5SDimitry Andric 16110b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 16120b57cec5SDimitry Andric getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum, 16130b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 16140b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 16150b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpNum); 16160b57cec5SDimitry Andric const MCOperand &MO2 = MI.getOperand(OpNum+1); 16170b57cec5SDimitry Andric const MCOperand &MO3 = MI.getOperand(OpNum+2); 16180b57cec5SDimitry Andric 16190b57cec5SDimitry Andric // Encoded as [Rn, Rm, imm]. 16200b57cec5SDimitry Andric // FIXME: Needs fixup support. 16210b57cec5SDimitry Andric unsigned Value = CTX.getRegisterInfo()->getEncodingValue(MO1.getReg()); 16220b57cec5SDimitry Andric Value <<= 4; 16230b57cec5SDimitry Andric Value |= CTX.getRegisterInfo()->getEncodingValue(MO2.getReg()); 16240b57cec5SDimitry Andric Value <<= 2; 16250b57cec5SDimitry Andric Value |= MO3.getImm(); 16260b57cec5SDimitry Andric 16270b57cec5SDimitry Andric return Value; 16280b57cec5SDimitry Andric } 16290b57cec5SDimitry Andric 16300b57cec5SDimitry Andric template<unsigned Bits, unsigned Shift> 16310b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 16320b57cec5SDimitry Andric getT2AddrModeImmOpValue(const MCInst &MI, unsigned OpNum, 16330b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 16340b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 16350b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpNum); 16360b57cec5SDimitry Andric const MCOperand &MO2 = MI.getOperand(OpNum+1); 16370b57cec5SDimitry Andric 16380b57cec5SDimitry Andric // FIXME: Needs fixup support. 16390b57cec5SDimitry Andric unsigned Value = CTX.getRegisterInfo()->getEncodingValue(MO1.getReg()); 16400b57cec5SDimitry Andric 16410b57cec5SDimitry Andric // If the immediate is B bits long, we need B+1 bits in order 16420b57cec5SDimitry Andric // to represent the (inverse of the) sign bit. 16430b57cec5SDimitry Andric Value <<= (Bits + 1); 16440b57cec5SDimitry Andric int32_t tmp = (int32_t)MO2.getImm(); 16450b57cec5SDimitry Andric if (tmp == INT32_MIN) { // represents subtracting zero rather than adding it 16460b57cec5SDimitry Andric tmp = 0; 16470b57cec5SDimitry Andric } else if (tmp < 0) { 16480b57cec5SDimitry Andric tmp = abs(tmp); 16490b57cec5SDimitry Andric } else { 16500b57cec5SDimitry Andric Value |= (1U << Bits); // Set the ADD bit 16510b57cec5SDimitry Andric } 16520b57cec5SDimitry Andric Value |= (tmp >> Shift) & ((1U << Bits) - 1); 16530b57cec5SDimitry Andric return Value; 16540b57cec5SDimitry Andric } 16550b57cec5SDimitry Andric 16560b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 16570b57cec5SDimitry Andric getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum, 16580b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 16590b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 16600b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpNum); 16610b57cec5SDimitry Andric 16620b57cec5SDimitry Andric // FIXME: Needs fixup support. 16630b57cec5SDimitry Andric unsigned Value = 0; 16648a4dda33SDimitry Andric auto tmp = static_cast<uint32_t>(MO1.getImm()); 16658a4dda33SDimitry Andric if (static_cast<int32_t>(tmp) < 0) 16668a4dda33SDimitry Andric tmp = -tmp; 16670b57cec5SDimitry Andric else 16680b57cec5SDimitry Andric Value |= 256; // Set the ADD bit 16690b57cec5SDimitry Andric Value |= tmp & 255; 16700b57cec5SDimitry Andric return Value; 16710b57cec5SDimitry Andric } 16720b57cec5SDimitry Andric 16730b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 16740b57cec5SDimitry Andric getT2SORegOpValue(const MCInst &MI, unsigned OpIdx, 16750b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 16760b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 16770b57cec5SDimitry Andric // Sub-operands are [reg, imm]. The first register is Rm, the reg to be 16780b57cec5SDimitry Andric // shifted. The second is the amount to shift by. 16790b57cec5SDimitry Andric // 16800b57cec5SDimitry Andric // {3-0} = Rm. 16810b57cec5SDimitry Andric // {4} = 0 16820b57cec5SDimitry Andric // {6-5} = type 16830b57cec5SDimitry Andric // {11-7} = imm 16840b57cec5SDimitry Andric 16850b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 16860b57cec5SDimitry Andric const MCOperand &MO1 = MI.getOperand(OpIdx + 1); 16870b57cec5SDimitry Andric ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO1.getImm()); 16880b57cec5SDimitry Andric 16890b57cec5SDimitry Andric // Encode Rm. 16900b57cec5SDimitry Andric unsigned Binary = CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 16910b57cec5SDimitry Andric 16920b57cec5SDimitry Andric // Encode the shift opcode. 16930b57cec5SDimitry Andric unsigned SBits = 0; 16940b57cec5SDimitry Andric // Set shift operand (bit[6:4]). 16950b57cec5SDimitry Andric // LSL - 000 16960b57cec5SDimitry Andric // LSR - 010 16970b57cec5SDimitry Andric // ASR - 100 16980b57cec5SDimitry Andric // ROR - 110 16990b57cec5SDimitry Andric switch (SOpc) { 17000b57cec5SDimitry Andric default: llvm_unreachable("Unknown shift opc!"); 17010b57cec5SDimitry Andric case ARM_AM::lsl: SBits = 0x0; break; 17020b57cec5SDimitry Andric case ARM_AM::lsr: SBits = 0x2; break; 17030b57cec5SDimitry Andric case ARM_AM::asr: SBits = 0x4; break; 1704bdd1243dSDimitry Andric case ARM_AM::rrx: [[fallthrough]]; 17050b57cec5SDimitry Andric case ARM_AM::ror: SBits = 0x6; break; 17060b57cec5SDimitry Andric } 17070b57cec5SDimitry Andric 17080b57cec5SDimitry Andric Binary |= SBits << 4; 17090b57cec5SDimitry Andric if (SOpc == ARM_AM::rrx) 17100b57cec5SDimitry Andric return Binary; 17110b57cec5SDimitry Andric 17120b57cec5SDimitry Andric // Encode shift_imm bit[11:7]. 17130b57cec5SDimitry Andric return Binary | ARM_AM::getSORegOffset(MO1.getImm()) << 7; 17140b57cec5SDimitry Andric } 17150b57cec5SDimitry Andric 17160b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 17170b57cec5SDimitry Andric getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op, 17180b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 17190b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 17200b57cec5SDimitry Andric // 10 bits. lower 5 bits are the lsb of the mask, high five bits are the 17210b57cec5SDimitry Andric // msb of the mask. 17220b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(Op); 17230b57cec5SDimitry Andric uint32_t v = ~MO.getImm(); 172406c3fb27SDimitry Andric uint32_t lsb = llvm::countr_zero(v); 172506c3fb27SDimitry Andric uint32_t msb = llvm::Log2_32(v); 17260b57cec5SDimitry Andric assert(v != 0 && lsb < 32 && msb < 32 && "Illegal bitfield mask!"); 17270b57cec5SDimitry Andric return lsb | (msb << 5); 17280b57cec5SDimitry Andric } 17290b57cec5SDimitry Andric 17300b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 17310b57cec5SDimitry Andric getRegisterListOpValue(const MCInst &MI, unsigned Op, 17320b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 17330b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 17340b57cec5SDimitry Andric // VLDM/VSTM/VSCCLRM: 17350b57cec5SDimitry Andric // {12-8} = Vd 17360b57cec5SDimitry Andric // {7-0} = Number of registers 17370b57cec5SDimitry Andric // 17380b57cec5SDimitry Andric // LDM/STM: 17390b57cec5SDimitry Andric // {15-0} = Bitfield of GPRs. 17400b57cec5SDimitry Andric unsigned Reg = MI.getOperand(Op).getReg(); 17410b57cec5SDimitry Andric bool SPRRegs = ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg); 17420b57cec5SDimitry Andric bool DPRRegs = ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg); 17430b57cec5SDimitry Andric 17440b57cec5SDimitry Andric unsigned Binary = 0; 17450b57cec5SDimitry Andric 17460b57cec5SDimitry Andric if (SPRRegs || DPRRegs) { 17470b57cec5SDimitry Andric // VLDM/VSTM/VSCCLRM 17480b57cec5SDimitry Andric unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg); 17490b57cec5SDimitry Andric unsigned NumRegs = (MI.getNumOperands() - Op) & 0xff; 17500b57cec5SDimitry Andric Binary |= (RegNo & 0x1f) << 8; 17510b57cec5SDimitry Andric 17520b57cec5SDimitry Andric // Ignore VPR 17530b57cec5SDimitry Andric if (MI.getOpcode() == ARM::VSCCLRMD || MI.getOpcode() == ARM::VSCCLRMS) 17540b57cec5SDimitry Andric --NumRegs; 17550b57cec5SDimitry Andric if (SPRRegs) 17560b57cec5SDimitry Andric Binary |= NumRegs; 17570b57cec5SDimitry Andric else 17580b57cec5SDimitry Andric Binary |= NumRegs * 2; 17590b57cec5SDimitry Andric } else { 17600b57cec5SDimitry Andric const MCRegisterInfo &MRI = *CTX.getRegisterInfo(); 1761fe6060f1SDimitry Andric assert(is_sorted(drop_begin(MI, Op), 17620b57cec5SDimitry Andric [&](const MCOperand &LHS, const MCOperand &RHS) { 17630b57cec5SDimitry Andric return MRI.getEncodingValue(LHS.getReg()) < 17640b57cec5SDimitry Andric MRI.getEncodingValue(RHS.getReg()); 17650b57cec5SDimitry Andric })); 17660b57cec5SDimitry Andric for (unsigned I = Op, E = MI.getNumOperands(); I < E; ++I) { 17678bcb0991SDimitry Andric unsigned RegNo = MRI.getEncodingValue(MI.getOperand(I).getReg()); 17680b57cec5SDimitry Andric Binary |= 1 << RegNo; 17690b57cec5SDimitry Andric } 17700b57cec5SDimitry Andric } 17710b57cec5SDimitry Andric 17720b57cec5SDimitry Andric return Binary; 17730b57cec5SDimitry Andric } 17740b57cec5SDimitry Andric 17750b57cec5SDimitry Andric /// getAddrMode6AddressOpValue - Encode an addrmode6 register number along 17760b57cec5SDimitry Andric /// with the alignment operand. 17770b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 17780b57cec5SDimitry Andric getAddrMode6AddressOpValue(const MCInst &MI, unsigned Op, 17790b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 17800b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 17810b57cec5SDimitry Andric const MCOperand &Reg = MI.getOperand(Op); 17820b57cec5SDimitry Andric const MCOperand &Imm = MI.getOperand(Op + 1); 17830b57cec5SDimitry Andric 17840b57cec5SDimitry Andric unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg.getReg()); 17850b57cec5SDimitry Andric unsigned Align = 0; 17860b57cec5SDimitry Andric 17870b57cec5SDimitry Andric switch (Imm.getImm()) { 17880b57cec5SDimitry Andric default: break; 17890b57cec5SDimitry Andric case 2: 17900b57cec5SDimitry Andric case 4: 17910b57cec5SDimitry Andric case 8: Align = 0x01; break; 17920b57cec5SDimitry Andric case 16: Align = 0x02; break; 17930b57cec5SDimitry Andric case 32: Align = 0x03; break; 17940b57cec5SDimitry Andric } 17950b57cec5SDimitry Andric 17960b57cec5SDimitry Andric return RegNo | (Align << 4); 17970b57cec5SDimitry Andric } 17980b57cec5SDimitry Andric 17990b57cec5SDimitry Andric /// getAddrMode6OneLane32AddressOpValue - Encode an addrmode6 register number 18000b57cec5SDimitry Andric /// along with the alignment operand for use in VST1 and VLD1 with size 32. 18010b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 18020b57cec5SDimitry Andric getAddrMode6OneLane32AddressOpValue(const MCInst &MI, unsigned Op, 18030b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 18040b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 18050b57cec5SDimitry Andric const MCOperand &Reg = MI.getOperand(Op); 18060b57cec5SDimitry Andric const MCOperand &Imm = MI.getOperand(Op + 1); 18070b57cec5SDimitry Andric 18080b57cec5SDimitry Andric unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg.getReg()); 18090b57cec5SDimitry Andric unsigned Align = 0; 18100b57cec5SDimitry Andric 18110b57cec5SDimitry Andric switch (Imm.getImm()) { 18120b57cec5SDimitry Andric default: break; 18130b57cec5SDimitry Andric case 8: 18140b57cec5SDimitry Andric case 16: 18150b57cec5SDimitry Andric case 32: // Default '0' value for invalid alignments of 8, 16, 32 bytes. 18160b57cec5SDimitry Andric case 2: Align = 0x00; break; 18170b57cec5SDimitry Andric case 4: Align = 0x03; break; 18180b57cec5SDimitry Andric } 18190b57cec5SDimitry Andric 18200b57cec5SDimitry Andric return RegNo | (Align << 4); 18210b57cec5SDimitry Andric } 18220b57cec5SDimitry Andric 18230b57cec5SDimitry Andric 18240b57cec5SDimitry Andric /// getAddrMode6DupAddressOpValue - Encode an addrmode6 register number and 18250b57cec5SDimitry Andric /// alignment operand for use in VLD-dup instructions. This is the same as 18260b57cec5SDimitry Andric /// getAddrMode6AddressOpValue except for the alignment encoding, which is 18270b57cec5SDimitry Andric /// different for VLD4-dup. 18280b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 18290b57cec5SDimitry Andric getAddrMode6DupAddressOpValue(const MCInst &MI, unsigned Op, 18300b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 18310b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 18320b57cec5SDimitry Andric const MCOperand &Reg = MI.getOperand(Op); 18330b57cec5SDimitry Andric const MCOperand &Imm = MI.getOperand(Op + 1); 18340b57cec5SDimitry Andric 18350b57cec5SDimitry Andric unsigned RegNo = CTX.getRegisterInfo()->getEncodingValue(Reg.getReg()); 18360b57cec5SDimitry Andric unsigned Align = 0; 18370b57cec5SDimitry Andric 18380b57cec5SDimitry Andric switch (Imm.getImm()) { 18390b57cec5SDimitry Andric default: break; 18400b57cec5SDimitry Andric case 2: 18410b57cec5SDimitry Andric case 4: 18420b57cec5SDimitry Andric case 8: Align = 0x01; break; 18430b57cec5SDimitry Andric case 16: Align = 0x03; break; 18440b57cec5SDimitry Andric } 18450b57cec5SDimitry Andric 18460b57cec5SDimitry Andric return RegNo | (Align << 4); 18470b57cec5SDimitry Andric } 18480b57cec5SDimitry Andric 18490b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 18500b57cec5SDimitry Andric getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op, 18510b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 18520b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 18530b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(Op); 18540b57cec5SDimitry Andric if (MO.getReg() == 0) return 0x0D; 18550b57cec5SDimitry Andric return CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); 18560b57cec5SDimitry Andric } 18570b57cec5SDimitry Andric 18580b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 18590b57cec5SDimitry Andric getShiftRight8Imm(const MCInst &MI, unsigned Op, 18600b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 18610b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 18620b57cec5SDimitry Andric return 8 - MI.getOperand(Op).getImm(); 18630b57cec5SDimitry Andric } 18640b57cec5SDimitry Andric 18650b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 18660b57cec5SDimitry Andric getShiftRight16Imm(const MCInst &MI, unsigned Op, 18670b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 18680b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 18690b57cec5SDimitry Andric return 16 - MI.getOperand(Op).getImm(); 18700b57cec5SDimitry Andric } 18710b57cec5SDimitry Andric 18720b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 18730b57cec5SDimitry Andric getShiftRight32Imm(const MCInst &MI, unsigned Op, 18740b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 18750b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 18760b57cec5SDimitry Andric return 32 - MI.getOperand(Op).getImm(); 18770b57cec5SDimitry Andric } 18780b57cec5SDimitry Andric 18790b57cec5SDimitry Andric unsigned ARMMCCodeEmitter:: 18800b57cec5SDimitry Andric getShiftRight64Imm(const MCInst &MI, unsigned Op, 18810b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 18820b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 18830b57cec5SDimitry Andric return 64 - MI.getOperand(Op).getImm(); 18840b57cec5SDimitry Andric } 18850b57cec5SDimitry Andric 1886*5f757f3fSDimitry Andric void ARMMCCodeEmitter::encodeInstruction(const MCInst &MI, 1887*5f757f3fSDimitry Andric SmallVectorImpl<char> &CB, 18880b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 18890b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 18900b57cec5SDimitry Andric // Pseudo instructions don't get encoded. 18910b57cec5SDimitry Andric const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 18920b57cec5SDimitry Andric uint64_t TSFlags = Desc.TSFlags; 18930b57cec5SDimitry Andric if ((TSFlags & ARMII::FormMask) == ARMII::Pseudo) 18940b57cec5SDimitry Andric return; 18950b57cec5SDimitry Andric 18960b57cec5SDimitry Andric int Size; 18970b57cec5SDimitry Andric if (Desc.getSize() == 2 || Desc.getSize() == 4) 18980b57cec5SDimitry Andric Size = Desc.getSize(); 18990b57cec5SDimitry Andric else 19000b57cec5SDimitry Andric llvm_unreachable("Unexpected instruction size!"); 19010b57cec5SDimitry Andric 1902*5f757f3fSDimitry Andric auto Endian = 1903*5f757f3fSDimitry Andric IsLittleEndian ? llvm::endianness::little : llvm::endianness::big; 19040b57cec5SDimitry Andric uint32_t Binary = getBinaryCodeForInstr(MI, Fixups, STI); 1905*5f757f3fSDimitry Andric if (Size == 2) { 1906*5f757f3fSDimitry Andric support::endian::write<uint16_t>(CB, Binary, Endian); 1907*5f757f3fSDimitry Andric } else if (isThumb(STI)) { 19080b57cec5SDimitry Andric // Thumb 32-bit wide instructions need to emit the high order halfword 19090b57cec5SDimitry Andric // first. 1910*5f757f3fSDimitry Andric support::endian::write<uint16_t>(CB, Binary >> 16, Endian); 1911*5f757f3fSDimitry Andric support::endian::write<uint16_t>(CB, Binary & 0xffff, Endian); 1912*5f757f3fSDimitry Andric } else { 1913*5f757f3fSDimitry Andric support::endian::write<uint32_t>(CB, Binary, Endian); 1914*5f757f3fSDimitry Andric } 19150b57cec5SDimitry Andric ++MCNumEmitted; // Keep track of the # of mi's emitted. 19160b57cec5SDimitry Andric } 19170b57cec5SDimitry Andric 19180b57cec5SDimitry Andric template <bool isNeg, ARM::Fixups fixup> 19190b57cec5SDimitry Andric uint32_t 19200b57cec5SDimitry Andric ARMMCCodeEmitter::getBFTargetOpValue(const MCInst &MI, unsigned OpIdx, 19210b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 19220b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 19230b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 19240b57cec5SDimitry Andric if (MO.isExpr()) 19250b57cec5SDimitry Andric return ::getBranchTargetOpValue(MI, OpIdx, fixup, Fixups, STI); 19260b57cec5SDimitry Andric return isNeg ? -(MO.getImm() >> 1) : (MO.getImm() >> 1); 19270b57cec5SDimitry Andric } 19280b57cec5SDimitry Andric 19290b57cec5SDimitry Andric uint32_t 19300b57cec5SDimitry Andric ARMMCCodeEmitter::getBFAfterTargetOpValue(const MCInst &MI, unsigned OpIdx, 19310b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 19320b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 19330b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 19340b57cec5SDimitry Andric const MCOperand BranchMO = MI.getOperand(0); 19350b57cec5SDimitry Andric 19360b57cec5SDimitry Andric if (MO.isExpr()) { 19370b57cec5SDimitry Andric assert(BranchMO.isExpr()); 19380b57cec5SDimitry Andric const MCExpr *DiffExpr = MCBinaryExpr::createSub( 19390b57cec5SDimitry Andric MO.getExpr(), BranchMO.getExpr(), CTX); 19400b57cec5SDimitry Andric MCFixupKind Kind = MCFixupKind(ARM::fixup_bfcsel_else_target); 19410b57cec5SDimitry Andric Fixups.push_back(llvm::MCFixup::create(0, DiffExpr, Kind, MI.getLoc())); 19420b57cec5SDimitry Andric return 0; 19430b57cec5SDimitry Andric } 19440b57cec5SDimitry Andric 19450b57cec5SDimitry Andric assert(MO.isImm() && BranchMO.isImm()); 19460b57cec5SDimitry Andric int Diff = MO.getImm() - BranchMO.getImm(); 19470b57cec5SDimitry Andric assert(Diff == 4 || Diff == 2); 19480b57cec5SDimitry Andric 19490b57cec5SDimitry Andric return Diff == 4; 19500b57cec5SDimitry Andric } 19510b57cec5SDimitry Andric 19520b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter::getVPTMaskOpValue(const MCInst &MI, unsigned OpIdx, 19530b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 19540b57cec5SDimitry Andric const MCSubtargetInfo &STI)const { 19550b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 19560b57cec5SDimitry Andric assert(MO.isImm() && "Unexpected operand type!"); 19570b57cec5SDimitry Andric 19580b57cec5SDimitry Andric int Value = MO.getImm(); 19590b57cec5SDimitry Andric int Imm = 0; 19600b57cec5SDimitry Andric 19610b57cec5SDimitry Andric // VPT Masks are actually encoded as a series of invert/don't invert bits, 19620b57cec5SDimitry Andric // rather than true/false bits. 19630b57cec5SDimitry Andric unsigned PrevBit = 0; 19640b57cec5SDimitry Andric for (int i = 3; i >= 0; --i) { 19650b57cec5SDimitry Andric unsigned Bit = (Value >> i) & 1; 19660b57cec5SDimitry Andric 19670b57cec5SDimitry Andric // Check if we are at the end of the mask. 19680b57cec5SDimitry Andric if ((Value & ~(~0U << i)) == 0) { 19690b57cec5SDimitry Andric Imm |= (1 << i); 19700b57cec5SDimitry Andric break; 19710b57cec5SDimitry Andric } 19720b57cec5SDimitry Andric 19730b57cec5SDimitry Andric // Convert the bit in the mask based on the previous bit. 19740b57cec5SDimitry Andric if (Bit != PrevBit) 19750b57cec5SDimitry Andric Imm |= (1 << i); 19760b57cec5SDimitry Andric 19770b57cec5SDimitry Andric PrevBit = Bit; 19780b57cec5SDimitry Andric } 19790b57cec5SDimitry Andric 19800b57cec5SDimitry Andric return Imm; 19810b57cec5SDimitry Andric } 19820b57cec5SDimitry Andric 19830b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter::getRestrictedCondCodeOpValue( 19840b57cec5SDimitry Andric const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups, 19850b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 19860b57cec5SDimitry Andric 19870b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 19880b57cec5SDimitry Andric assert(MO.isImm() && "Unexpected operand type!"); 19890b57cec5SDimitry Andric 19900b57cec5SDimitry Andric switch (MO.getImm()) { 19910b57cec5SDimitry Andric default: 19920b57cec5SDimitry Andric assert(0 && "Unexpected Condition!"); 19930b57cec5SDimitry Andric return 0; 19940b57cec5SDimitry Andric case ARMCC::HS: 19950b57cec5SDimitry Andric case ARMCC::EQ: 19960b57cec5SDimitry Andric return 0; 19970b57cec5SDimitry Andric case ARMCC::HI: 19980b57cec5SDimitry Andric case ARMCC::NE: 19990b57cec5SDimitry Andric return 1; 20000b57cec5SDimitry Andric case ARMCC::GE: 20010b57cec5SDimitry Andric return 4; 20020b57cec5SDimitry Andric case ARMCC::LT: 20030b57cec5SDimitry Andric return 5; 20040b57cec5SDimitry Andric case ARMCC::GT: 20050b57cec5SDimitry Andric return 6; 20060b57cec5SDimitry Andric case ARMCC::LE: 20070b57cec5SDimitry Andric return 7; 20080b57cec5SDimitry Andric } 20090b57cec5SDimitry Andric } 20100b57cec5SDimitry Andric 20110b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 20120b57cec5SDimitry Andric getPowerTwoOpValue(const MCInst &MI, unsigned OpIdx, 20130b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 20140b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 20150b57cec5SDimitry Andric const MCOperand &MO = MI.getOperand(OpIdx); 20160b57cec5SDimitry Andric assert(MO.isImm() && "Unexpected operand type!"); 201706c3fb27SDimitry Andric return llvm::countr_zero((uint64_t)MO.getImm()); 20180b57cec5SDimitry Andric } 20190b57cec5SDimitry Andric 20200b57cec5SDimitry Andric template <unsigned start> 20210b57cec5SDimitry Andric uint32_t ARMMCCodeEmitter:: 20220b57cec5SDimitry Andric getMVEPairVectorIndexOpValue(const MCInst &MI, unsigned OpIdx, 20230b57cec5SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 20240b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 20250b57cec5SDimitry Andric const MCOperand MO = MI.getOperand(OpIdx); 20260b57cec5SDimitry Andric assert(MO.isImm() && "Unexpected operand type!"); 20270b57cec5SDimitry Andric 20280b57cec5SDimitry Andric int Value = MO.getImm(); 20290b57cec5SDimitry Andric return Value - start; 20300b57cec5SDimitry Andric } 20310b57cec5SDimitry Andric 20320b57cec5SDimitry Andric #include "ARMGenMCCodeEmitter.inc" 20330b57cec5SDimitry Andric 20340b57cec5SDimitry Andric MCCodeEmitter *llvm::createARMLEMCCodeEmitter(const MCInstrInfo &MCII, 20350b57cec5SDimitry Andric MCContext &Ctx) { 20360b57cec5SDimitry Andric return new ARMMCCodeEmitter(MCII, Ctx, true); 20370b57cec5SDimitry Andric } 20380b57cec5SDimitry Andric 20390b57cec5SDimitry Andric MCCodeEmitter *llvm::createARMBEMCCodeEmitter(const MCInstrInfo &MCII, 20400b57cec5SDimitry Andric MCContext &Ctx) { 20410b57cec5SDimitry Andric return new ARMMCCodeEmitter(MCII, Ctx, false); 20420b57cec5SDimitry Andric } 2043