xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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