llvm/llvm/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h

//===-- ARMAddressingModes.h - ARM Addressing Modes -------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains the ARM addressing mode implementation stuff.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMADDRESSINGMODES_H
#define LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMADDRESSINGMODES_H

#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/bit.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>

namespace llvm {

/// ARM_AM - ARM Addressing Mode Stuff
namespace ARM_AM {
  enum ShiftOpc {};

  enum AddrOpc {};

  inline const char *getAddrOpcStr(AddrOpc Op) {}

  inline const StringRef getShiftOpcStr(ShiftOpc Op) {}

  inline unsigned getShiftOpcEncoding(ShiftOpc Op) {}

  enum AMSubMode {};

  inline const char *getAMSubModeStr(AMSubMode Mode) {}

  //===--------------------------------------------------------------------===//
  // Addressing Mode #1: shift_operand with registers
  //===--------------------------------------------------------------------===//
  //
  // This 'addressing mode' is used for arithmetic instructions.  It can
  // represent things like:
  //   reg
  //   reg [asr|lsl|lsr|ror|rrx] reg
  //   reg [asr|lsl|lsr|ror|rrx] imm
  //
  // This is stored three operands [rega, regb, opc].  The first is the base
  // reg, the second is the shift amount (or reg0 if not present or imm).  The
  // third operand encodes the shift opcode and the imm if a reg isn't present.
  //
  inline unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm) {}
  inline unsigned getSORegOffset(unsigned Op) {}
  inline ShiftOpc getSORegShOp(unsigned Op) {}

  /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return
  /// the 8-bit imm value.
  inline unsigned getSOImmValImm(unsigned Imm) {}
  /// getSOImmValRot - Given an encoded imm field for the reg/imm form, return
  /// the rotate amount.
  inline unsigned getSOImmValRot(unsigned Imm) {}

  /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand,
  /// computing the rotate amount to use.  If this immediate value cannot be
  /// handled with a single shifter-op, determine a good rotate amount that will
  /// take a maximal chunk of bits out of the immediate.
  inline unsigned getSOImmValRotate(unsigned Imm) {}

  /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit
  /// into an shifter_operand immediate operand, return the 12-bit encoding for
  /// it.  If not, return -1.
  inline int getSOImmVal(unsigned Arg) {}

  /// isSOImmTwoPartVal - Return true if the specified value can be obtained by
  /// or'ing together two SOImmVal's.
  inline bool isSOImmTwoPartVal(unsigned V) {}

  /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal,
  /// return the first chunk of it.
  inline unsigned getSOImmTwoPartFirst(unsigned V) {}

  /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal,
  /// return the second chunk of it.
  inline unsigned getSOImmTwoPartSecond(unsigned V) {}

  /// isSOImmTwoPartValNeg - Return true if the specified value can be obtained
  /// by two SOImmVal, that -V = First + Second.
  /// "R+V" can be optimized to (sub (sub R, First), Second).
  /// "R=V" can be optimized to (sub (mvn R, ~(-First)), Second).
  inline bool isSOImmTwoPartValNeg(unsigned V) {}

  /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed
  /// by a left shift. Returns the shift amount to use.
  inline unsigned getThumbImmValShift(unsigned Imm) {}

  /// isThumbImmShiftedVal - Return true if the specified value can be obtained
  /// by left shifting a 8-bit immediate.
  inline bool isThumbImmShiftedVal(unsigned V) {}

  /// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed
  /// by a left shift. Returns the shift amount to use.
  inline unsigned getThumbImm16ValShift(unsigned Imm) {}

  /// isThumbImm16ShiftedVal - Return true if the specified value can be
  /// obtained by left shifting a 16-bit immediate.
  inline bool isThumbImm16ShiftedVal(unsigned V) {}

  /// getThumbImmNonShiftedVal - If V is a value that satisfies
  /// isThumbImmShiftedVal, return the non-shiftd value.
  inline unsigned getThumbImmNonShiftedVal(unsigned V) {}


  /// getT2SOImmValSplat - Return the 12-bit encoded representation
  /// if the specified value can be obtained by splatting the low 8 bits
  /// into every other byte or every byte of a 32-bit value. i.e.,
  ///     00000000 00000000 00000000 abcdefgh    control = 0
  ///     00000000 abcdefgh 00000000 abcdefgh    control = 1
  ///     abcdefgh 00000000 abcdefgh 00000000    control = 2
  ///     abcdefgh abcdefgh abcdefgh abcdefgh    control = 3
  /// Return -1 if none of the above apply.
  /// See ARM Reference Manual A6.3.2.
  inline int getT2SOImmValSplatVal(unsigned V) {}

  /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the
  /// specified value is a rotated 8-bit value. Return -1 if no rotation
  /// encoding is possible.
  /// See ARM Reference Manual A6.3.2.
  inline int getT2SOImmValRotateVal(unsigned V) {}

  /// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit
  /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit
  /// encoding for it.  If not, return -1.
  /// See ARM Reference Manual A6.3.2.
  inline int getT2SOImmVal(unsigned Arg) {}

  inline unsigned getT2SOImmValRotate(unsigned V) {}

  inline bool isT2SOImmTwoPartVal(unsigned Imm) {}

  inline unsigned getT2SOImmTwoPartFirst(unsigned Imm) {}

  inline unsigned getT2SOImmTwoPartSecond(unsigned Imm) {}


  //===--------------------------------------------------------------------===//
  // Addressing Mode #2
  //===--------------------------------------------------------------------===//
  //
  // This is used for most simple load/store instructions.
  //
  // addrmode2 := reg +/- reg shop imm
  // addrmode2 := reg +/- imm12
  //
  // The first operand is always a Reg.  The second operand is a reg if in
  // reg/reg form, otherwise it's reg#0.  The third field encodes the operation
  // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The
  // fourth operand 16-17 encodes the index mode.
  //
  // If this addressing mode is a frame index (before prolog/epilog insertion
  // and code rewriting), this operand will have the form:  FI#, reg0, <offs>
  // with no shift amount for the frame offset.
  //
  inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO,
                            unsigned IdxMode = 0) {}
  inline unsigned getAM2Offset(unsigned AM2Opc) {}
  inline AddrOpc getAM2Op(unsigned AM2Opc) {}
  inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) {}
  inline unsigned getAM2IdxMode(unsigned AM2Opc) {}

  //===--------------------------------------------------------------------===//
  // Addressing Mode #3
  //===--------------------------------------------------------------------===//
  //
  // This is used for sign-extending loads, and load/store-pair instructions.
  //
  // addrmode3 := reg +/- reg
  // addrmode3 := reg +/- imm8
  //
  // The first operand is always a Reg.  The second operand is a reg if in
  // reg/reg form, otherwise it's reg#0.  The third field encodes the operation
  // in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the
  // index mode.

  /// getAM3Opc - This function encodes the addrmode3 opc field.
  inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset,
                            unsigned IdxMode = 0) {}
  inline unsigned char getAM3Offset(unsigned AM3Opc) {}
  inline AddrOpc getAM3Op(unsigned AM3Opc) {}
  inline unsigned getAM3IdxMode(unsigned AM3Opc) {}

  //===--------------------------------------------------------------------===//
  // Addressing Mode #4
  //===--------------------------------------------------------------------===//
  //
  // This is used for load / store multiple instructions.
  //
  // addrmode4 := reg, <mode>
  //
  // The four modes are:
  //    IA - Increment after
  //    IB - Increment before
  //    DA - Decrement after
  //    DB - Decrement before
  // For VFP instructions, only the IA and DB modes are valid.

  inline AMSubMode getAM4SubMode(unsigned Mode) {}

  inline unsigned getAM4ModeImm(AMSubMode SubMode) {}

  //===--------------------------------------------------------------------===//
  // Addressing Mode #5
  //===--------------------------------------------------------------------===//
  //
  // This is used for coprocessor instructions, such as FP load/stores.
  //
  // addrmode5 := reg +/- imm8*4
  //
  // The first operand is always a Reg.  The second operand encodes the
  // operation (add or subtract) in bit 8 and the immediate in bits 0-7.

  /// getAM5Opc - This function encodes the addrmode5 opc field.
  inline unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset) {}
  inline unsigned char getAM5Offset(unsigned AM5Opc) {}
  inline AddrOpc getAM5Op(unsigned AM5Opc) {}

  //===--------------------------------------------------------------------===//
  // Addressing Mode #5 FP16
  //===--------------------------------------------------------------------===//
  //
  // This is used for coprocessor instructions, such as 16-bit FP load/stores.
  //
  // addrmode5fp16 := reg +/- imm8*2
  //
  // The first operand is always a Reg.  The second operand encodes the
  // operation (add or subtract) in bit 8 and the immediate in bits 0-7.

  /// getAM5FP16Opc - This function encodes the addrmode5fp16 opc field.
  inline unsigned getAM5FP16Opc(AddrOpc Opc, unsigned char Offset) {}
  inline unsigned char getAM5FP16Offset(unsigned AM5Opc) {}
  inline AddrOpc getAM5FP16Op(unsigned AM5Opc) {}

  //===--------------------------------------------------------------------===//
  // Addressing Mode #6
  //===--------------------------------------------------------------------===//
  //
  // This is used for NEON load / store instructions.
  //
  // addrmode6 := reg with optional alignment
  //
  // This is stored in two operands [regaddr, align].  The first is the
  // address register.  The second operand is the value of the alignment
  // specifier in bytes or zero if no explicit alignment.
  // Valid alignments depend on the specific instruction.

  //===--------------------------------------------------------------------===//
  // NEON/MVE Modified Immediates
  //===--------------------------------------------------------------------===//
  //
  // Several NEON and MVE instructions (e.g., VMOV) take a "modified immediate"
  // vector operand, where a small immediate encoded in the instruction
  // specifies a full NEON vector value.  These modified immediates are
  // represented here as encoded integers.  The low 8 bits hold the immediate
  // value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold
  // the "Cmode" field of the instruction.  The interfaces below treat the
  // Op and Cmode values as a single 5-bit value.

  inline unsigned createVMOVModImm(unsigned OpCmode, unsigned Val) {}
  inline unsigned getVMOVModImmOpCmode(unsigned ModImm) {}
  inline unsigned getVMOVModImmVal(unsigned ModImm) {}

  /// decodeVMOVModImm - Decode a NEON/MVE modified immediate value into the
  /// element value and the element size in bits.  (If the element size is
  /// smaller than the vector, it is splatted into all the elements.)
  inline uint64_t decodeVMOVModImm(unsigned ModImm, unsigned &EltBits) {}

  // Generic validation for single-byte immediate (0X00, 00X0, etc).
  inline bool isNEONBytesplat(unsigned Value, unsigned Size) {}

  /// Checks if Value is a correct immediate for instructions like VBIC/VORR.
  inline bool isNEONi16splat(unsigned Value) {}

  // Encode NEON 16 bits Splat immediate for instructions like VBIC/VORR
  inline unsigned encodeNEONi16splat(unsigned Value) {}

  /// Checks if Value is a correct immediate for instructions like VBIC/VORR.
  inline bool isNEONi32splat(unsigned Value) {}

  /// Encode NEON 32 bits Splat immediate for instructions like VBIC/VORR.
  inline unsigned encodeNEONi32splat(unsigned Value) {}

  //===--------------------------------------------------------------------===//
  // Floating-point Immediates
  //
  inline float getFPImmFloat(unsigned Imm) {}

  /// getFP16Imm - Return an 8-bit floating-point version of the 16-bit
  /// floating-point value. If the value cannot be represented as an 8-bit
  /// floating-point value, then return -1.
  inline int getFP16Imm(const APInt &Imm) {}

  inline int getFP16Imm(const APFloat &FPImm) {}

  /// If this is a FP16Imm encoded as a fp32 value, return the 8-bit encoding
  /// for it. Otherwise return -1 like getFP16Imm.
  inline int getFP32FP16Imm(const APInt &Imm) {}

  inline int getFP32FP16Imm(const APFloat &FPImm) {}

  /// getFP32Imm - Return an 8-bit floating-point version of the 32-bit
  /// floating-point value. If the value cannot be represented as an 8-bit
  /// floating-point value, then return -1.
  inline int getFP32Imm(const APInt &Imm) {}

  inline int getFP32Imm(const APFloat &FPImm) {}

  /// getFP64Imm - Return an 8-bit floating-point version of the 64-bit
  /// floating-point value. If the value cannot be represented as an 8-bit
  /// floating-point value, then return -1.
  inline int getFP64Imm(const APInt &Imm) {}

  inline int getFP64Imm(const APFloat &FPImm) {}

} // end namespace ARM_AM
} // end namespace llvm

#endif