// Copyright 2015, VIXL authors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//   * Neither the name of ARM Limited nor the names of its contributors may
//     be used to endorse or promote products derived from this software
//     without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#ifndef VIXL_AARCH32_OPERANDS_AARCH32_H_
#define VIXL_AARCH32_OPERANDS_AARCH32_H_

#include "aarch32/instructions-aarch32.h"

namespace vixl {
namespace aarch32 {

// Operand represents generic set of arguments to pass to an instruction.
//
//   Usage: <instr> <Rd> , <Operand>
//
//   where <instr> is the instruction to use (e.g., Mov(), Rsb(), etc.)
//         <Rd> is the destination register
//         <Operand> is the rest of the arguments to the instruction
//
//   <Operand> can be one of:
//
//   #<imm> - an unsigned 32-bit immediate value
//   <Rm>, <shift> <#amount> - immediate shifted register
//   <Rm>, <shift> <Rs> - register shifted register
//
class Operand {
 public:
  // { #<immediate> }
  // where <immediate> is uint32_t.
  // This is allowed to be an implicit constructor because Operand is
  // a wrapper class that doesn't normally perform any type conversion.
  Operand(uint32_t immediate)  // NOLINT(runtime/explicit)
      : imm_(immediate), rm_(NoReg), shift_(LSL), amount_(0), rs_(NoReg) {}
  Operand(int32_t immediate)  // NOLINT(runtime/explicit)
      : imm_(immediate), rm_(NoReg), shift_(LSL), amount_(0), rs_(NoReg) {}

  // rm
  // where rm is the base register
  // This is allowed to be an implicit constructor because Operand is
  // a wrapper class that doesn't normally perform any type conversion.
  Operand(Register rm)  // NOLINT(runtime/explicit)
      : imm_(0), rm_(rm), shift_(LSL), amount_(0), rs_(NoReg) {
    VIXL_ASSERT(rm_.IsValid());
  }

  // rm, <shift>
  // where rm is the base register, and
  //       <shift> is RRX
  Operand(Register rm, Shift shift)
      : imm_(0), rm_(rm), shift_(shift), amount_(0), rs_(NoReg) {
    VIXL_ASSERT(rm_.IsValid());
    VIXL_ASSERT(shift_.IsRRX());
  }

  // rm, <shift> #<amount>
  // where rm is the base register, and
  //       <shift> is one of {LSL, LSR, ASR, ROR}, and
  //       <amount> is uint6_t.
  Operand(Register rm, Shift shift, uint32_t amount)
      : imm_(0), rm_(rm), shift_(shift), amount_(amount), rs_(NoReg) {
    VIXL_ASSERT(rm_.IsValid());
    VIXL_ASSERT(!shift_.IsRRX());
#ifdef VIXL_DEBUG
    switch (shift_.GetType()) {
      case LSL:
        VIXL_ASSERT(amount_ <= 31);
        break;
      case ROR:
        VIXL_ASSERT(amount_ <= 31);
        break;
      case LSR:
      case ASR:
        VIXL_ASSERT(amount_ <= 32);
        break;
      case RRX:
      default:
        VIXL_UNREACHABLE();
        break;
    }
#endif
  }

  // rm, <shift> rs
  // where rm is the base register, and
  //       <shift> is one of {LSL, LSR, ASR, ROR}, and
  //       rs is the shifted register
  Operand(Register rm, Shift shift, Register rs)
      : imm_(0), rm_(rm), shift_(shift), amount_(0), rs_(rs) {
    VIXL_ASSERT(rm_.IsValid() && rs_.IsValid());
    VIXL_ASSERT(!shift_.IsRRX());
  }

  // Factory methods creating operands from any integral or pointer type. The
  // source must fit into 32 bits.
  template <typename T>
  static Operand From(T immediate) {
#if __cplusplus >= 201103L
    VIXL_STATIC_ASSERT_MESSAGE(std::is_integral<T>::value,
                               "An integral type is required to build an "
                               "immediate operand.");
#endif
    // Allow both a signed or unsigned 32 bit integer to be passed, but store it
    // as a uint32_t. The signedness information will be lost. We have to add a
    // static_cast to make sure the compiler does not complain about implicit 64
    // to 32 narrowing. It's perfectly acceptable for the user to pass a 64-bit
    // value, as long as it can be encoded in 32 bits.
    VIXL_ASSERT(IsInt32(immediate) || IsUint32(immediate));
    return Operand(static_cast<uint32_t>(immediate));
  }

  template <typename T>
  static Operand From(T* address) {
    uintptr_t address_as_integral = reinterpret_cast<uintptr_t>(address);
    VIXL_ASSERT(IsUint32(address_as_integral));
    return Operand(static_cast<uint32_t>(address_as_integral));
  }

  bool IsImmediate() const { return !rm_.IsValid(); }

  bool IsPlainRegister() const {
    return rm_.IsValid() && !shift_.IsRRX() && !rs_.IsValid() && (amount_ == 0);
  }

  bool IsImmediateShiftedRegister() const {
    return rm_.IsValid() && !rs_.IsValid();
  }

  bool IsRegisterShiftedRegister() const {
    return rm_.IsValid() && rs_.IsValid();
  }

  uint32_t GetImmediate() const {
    VIXL_ASSERT(IsImmediate());
    return imm_;
  }

  int32_t GetSignedImmediate() const {
    VIXL_ASSERT(IsImmediate());
    int32_t result;
    memcpy(&result, &imm_, sizeof(result));
    return result;
  }

  Register GetBaseRegister() const {
    VIXL_ASSERT(IsImmediateShiftedRegister() || IsRegisterShiftedRegister());
    return rm_;
  }

  Shift GetShift() const {
    VIXL_ASSERT(IsImmediateShiftedRegister() || IsRegisterShiftedRegister());
    return shift_;
  }

  uint32_t GetShiftAmount() const {
    VIXL_ASSERT(IsImmediateShiftedRegister());
    return amount_;
  }

  Register GetShiftRegister() const {
    VIXL_ASSERT(IsRegisterShiftedRegister());
    return rs_;
  }

  uint32_t GetTypeEncodingValue() const {
    return shift_.IsRRX() ? kRRXEncodedValue : shift_.GetValue();
  }

 private:
// Forbid implicitly creating operands around types that cannot be encoded
// into a uint32_t without loss.
#if __cplusplus >= 201103L
  Operand(int64_t) = delete;   // NOLINT(runtime/explicit)
  Operand(uint64_t) = delete;  // NOLINT(runtime/explicit)
  Operand(float) = delete;     // NOLINT(runtime/explicit)
  Operand(double) = delete;    // NOLINT(runtime/explicit)
#else
  VIXL_NO_RETURN_IN_DEBUG_MODE Operand(int64_t) {  // NOLINT(runtime/explicit)
    VIXL_UNREACHABLE();
  }
  VIXL_NO_RETURN_IN_DEBUG_MODE Operand(uint64_t) {  // NOLINT(runtime/explicit)
    VIXL_UNREACHABLE();
  }
  VIXL_NO_RETURN_IN_DEBUG_MODE Operand(float) {  // NOLINT
    VIXL_UNREACHABLE();
  }
  VIXL_NO_RETURN_IN_DEBUG_MODE Operand(double) {  // NOLINT
    VIXL_UNREACHABLE();
  }
#endif

  uint32_t imm_;
  Register rm_;
  Shift shift_;
  uint32_t amount_;
  Register rs_;
};

std::ostream& operator<<(std::ostream& os, const Operand& operand);

class NeonImmediate {
  template <typename T>
  struct DataTypeIdentity {
    T data_type_;
  };

 public:
  // { #<immediate> }
  // where <immediate> is 32 bit number.
  // This is allowed to be an implicit constructor because NeonImmediate is
  // a wrapper class that doesn't normally perform any type conversion.
  NeonImmediate(uint32_t immediate)  // NOLINT(runtime/explicit)
      : imm_(immediate), immediate_type_(I32) {}
  NeonImmediate(int immediate)  // NOLINT(runtime/explicit)
      : imm_(immediate), immediate_type_(I32) {}

  // { #<immediate> }
  // where <immediate> is a 64 bit number
  // This is allowed to be an implicit constructor because NeonImmediate is
  // a wrapper class that doesn't normally perform any type conversion.
  NeonImmediate(int64_t immediate)  // NOLINT(runtime/explicit)
      : imm_(immediate), immediate_type_(I64) {}
  NeonImmediate(uint64_t immediate)  // NOLINT(runtime/explicit)
      : imm_(immediate), immediate_type_(I64) {}

  // { #<immediate> }
  // where <immediate> is a non zero floating point number which can be encoded
  // as an 8 bit floating point (checked by the constructor).
  // This is allowed to be an implicit constructor because NeonImmediate is
  // a wrapper class that doesn't normally perform any type conversion.
  NeonImmediate(float immediate)  // NOLINT(runtime/explicit)
      : imm_(immediate), immediate_type_(F32) {}
  NeonImmediate(double immediate)  // NOLINT(runtime/explicit)
      : imm_(immediate), immediate_type_(F64) {}

  NeonImmediate(const NeonImmediate& src)
      : imm_(src.imm_), immediate_type_(src.immediate_type_) {}

  template <typename T>
  T GetImmediate() const {
    return GetImmediate(DataTypeIdentity<T>());
  }

  template <typename T>
  T GetImmediate(const DataTypeIdentity<T>&) const {
    VIXL_ASSERT(sizeof(T) <= sizeof(uint32_t));
    VIXL_ASSERT(CanConvert<T>());
    if (immediate_type_.Is(I64))
      return static_cast<T>(imm_.u64_ & static_cast<T>(-1));
    if (immediate_type_.Is(F64) || immediate_type_.Is(F32)) return 0;
    return static_cast<T>(imm_.u32_ & static_cast<T>(-1));
  }

  uint64_t GetImmediate(const DataTypeIdentity<uint64_t>&) const {
    VIXL_ASSERT(CanConvert<uint64_t>());
    if (immediate_type_.Is(I32)) return imm_.u32_;
    if (immediate_type_.Is(F64) || immediate_type_.Is(F32)) return 0;
    return imm_.u64_;
  }
  float GetImmediate(const DataTypeIdentity<float>&) const {
    VIXL_ASSERT(CanConvert<float>());
    if (immediate_type_.Is(F64)) return static_cast<float>(imm_.d_);
    return imm_.f_;
  }
  double GetImmediate(const DataTypeIdentity<double>&) const {
    VIXL_ASSERT(CanConvert<double>());
    if (immediate_type_.Is(F32)) return static_cast<double>(imm_.f_);
    return imm_.d_;
  }

  bool IsInteger32() const { return immediate_type_.Is(I32); }
  bool IsInteger64() const { return immediate_type_.Is(I64); }
  bool IsInteger() const { return IsInteger32() || IsInteger64(); }
  bool IsFloat() const { return immediate_type_.Is(F32); }
  bool IsDouble() const { return immediate_type_.Is(F64); }
  bool IsFloatZero() const {
    if (immediate_type_.Is(F32)) return imm_.f_ == 0.0f;
    if (immediate_type_.Is(F64)) return imm_.d_ == 0.0;
    return false;
  }

  template <typename T>
  bool CanConvert() const {
    return CanConvert(DataTypeIdentity<T>());
  }

  template <typename T>
  bool CanConvert(const DataTypeIdentity<T>&) const {
    VIXL_ASSERT(sizeof(T) < sizeof(uint32_t));
    return (immediate_type_.Is(I32) && ((imm_.u32_ >> (8 * sizeof(T))) == 0)) ||
           (immediate_type_.Is(I64) && ((imm_.u64_ >> (8 * sizeof(T))) == 0)) ||
           (immediate_type_.Is(F32) && (imm_.f_ == 0.0f)) ||
           (immediate_type_.Is(F64) && (imm_.d_ == 0.0));
  }
  bool CanConvert(const DataTypeIdentity<uint32_t>&) const {
    return immediate_type_.Is(I32) ||
           (immediate_type_.Is(I64) && ((imm_.u64_ >> 32) == 0)) ||
           (immediate_type_.Is(F32) && (imm_.f_ == 0.0f)) ||
           (immediate_type_.Is(F64) && (imm_.d_ == 0.0));
  }
  bool CanConvert(const DataTypeIdentity<uint64_t>&) const {
    return IsInteger() || CanConvert<uint32_t>();
  }
  bool CanConvert(const DataTypeIdentity<float>&) const {
    return IsFloat() || IsDouble();
  }
  bool CanConvert(const DataTypeIdentity<double>&) const {
    return IsFloat() || IsDouble();
  }
  friend std::ostream& operator<<(std::ostream& os,
                                  const NeonImmediate& operand);

 private:
  union NeonImmediateType {
    uint64_t u64_;
    double d_;
    uint32_t u32_;
    float f_;
    NeonImmediateType(uint64_t u) : u64_(u) {}
    NeonImmediateType(int64_t u) : u64_(u) {}
    NeonImmediateType(uint32_t u) : u32_(u) {}
    NeonImmediateType(int32_t u) : u32_(u) {}
    NeonImmediateType(double d) : d_(d) {}
    NeonImmediateType(float f) : f_(f) {}
    NeonImmediateType(const NeonImmediateType& ref) : u64_(ref.u64_) {}
  } imm_;

  DataType immediate_type_;
};

std::ostream& operator<<(std::ostream& os, const NeonImmediate& operand);

class NeonOperand {
 public:
  NeonOperand(int32_t immediate)  // NOLINT(runtime/explicit)
      : imm_(immediate), rm_(NoDReg) {}
  NeonOperand(uint32_t immediate)  // NOLINT(runtime/explicit)
      : imm_(immediate), rm_(NoDReg) {}
  NeonOperand(int64_t immediate)  // NOLINT(runtime/explicit)
      : imm_(immediate), rm_(NoDReg) {}
  NeonOperand(uint64_t immediate)  // NOLINT(runtime/explicit)
      : imm_(immediate), rm_(NoDReg) {}
  NeonOperand(float immediate)  // NOLINT(runtime/explicit)
      : imm_(immediate), rm_(NoDReg) {}
  NeonOperand(double immediate)  // NOLINT(runtime/explicit)
      : imm_(immediate), rm_(NoDReg) {}
  NeonOperand(const NeonImmediate& imm)  // NOLINT(runtime/explicit)
      : imm_(imm), rm_(NoDReg) {}
  NeonOperand(const VRegister& rm)  // NOLINT(runtime/explicit)
      : imm_(0), rm_(rm) {
    VIXL_ASSERT(rm_.IsValid());
  }

  bool IsImmediate() const { return !rm_.IsValid(); }
  bool IsRegister() const { return rm_.IsValid(); }
  bool IsFloatZero() const {
    VIXL_ASSERT(IsImmediate());
    return imm_.IsFloatZero();
  }

  const NeonImmediate& GetNeonImmediate() const { return imm_; }

  VRegister GetRegister() const {
    VIXL_ASSERT(IsRegister());
    return rm_;
  }

 protected:
  NeonImmediate imm_;
  VRegister rm_;
};

std::ostream& operator<<(std::ostream& os, const NeonOperand& operand);

// SOperand represents either an immediate or a SRegister.
class SOperand : public NeonOperand {
 public:
  // #<immediate>
  // where <immediate> is 32bit int
  // This is allowed to be an implicit constructor because SOperand is
  // a wrapper class that doesn't normally perform any type conversion.
  SOperand(int32_t immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}
  SOperand(uint32_t immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}
  // #<immediate>
  // where <immediate> is 32bit float
  SOperand(float immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}
  // where <immediate> is 64bit float
  SOperand(double immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}

  SOperand(const NeonImmediate& imm)  // NOLINT(runtime/explicit)
      : NeonOperand(imm) {}

  // rm
  // This is allowed to be an implicit constructor because SOperand is
  // a wrapper class that doesn't normally perform any type conversion.
  SOperand(SRegister rm)  // NOLINT(runtime/explicit)
      : NeonOperand(rm) {}
  SRegister GetRegister() const {
    VIXL_ASSERT(IsRegister() && (rm_.GetType() == CPURegister::kSRegister));
    return SRegister(rm_.GetCode());
  }
};

// DOperand represents either an immediate or a DRegister.
std::ostream& operator<<(std::ostream& os, const SOperand& operand);

class DOperand : public NeonOperand {
 public:
  // #<immediate>
  // where <immediate> is uint32_t.
  // This is allowed to be an implicit constructor because DOperand is
  // a wrapper class that doesn't normally perform any type conversion.
  DOperand(int32_t immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}
  DOperand(uint32_t immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}
  DOperand(int64_t immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}
  DOperand(uint64_t immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}

  // #<immediate>
  // where <immediate> is a non zero floating point number which can be encoded
  // as an 8 bit floating point (checked by the constructor).
  // This is allowed to be an implicit constructor because DOperand is
  // a wrapper class that doesn't normally perform any type conversion.
  DOperand(float immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}
  DOperand(double immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}

  DOperand(const NeonImmediate& imm)  // NOLINT(runtime/explicit)
      : NeonOperand(imm) {}
  // rm
  // This is allowed to be an implicit constructor because DOperand is
  // a wrapper class that doesn't normally perform any type conversion.
  DOperand(DRegister rm)  // NOLINT(runtime/explicit)
      : NeonOperand(rm) {}

  DRegister GetRegister() const {
    VIXL_ASSERT(IsRegister() && (rm_.GetType() == CPURegister::kDRegister));
    return DRegister(rm_.GetCode());
  }
};

std::ostream& operator<<(std::ostream& os, const DOperand& operand);

// QOperand represents either an immediate or a QRegister.
class QOperand : public NeonOperand {
 public:
  // #<immediate>
  // where <immediate> is uint32_t.
  // This is allowed to be an implicit constructor because QOperand is
  // a wrapper class that doesn't normally perform any type conversion.
  QOperand(int32_t immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}
  QOperand(uint32_t immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}
  QOperand(int64_t immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}
  QOperand(uint64_t immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}
  QOperand(float immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}
  QOperand(double immediate)  // NOLINT(runtime/explicit)
      : NeonOperand(immediate) {}

  QOperand(const NeonImmediate& imm)  // NOLINT(runtime/explicit)
      : NeonOperand(imm) {}

  // rm
  // This is allowed to be an implicit constructor because QOperand is
  // a wrapper class that doesn't normally perform any type conversion.
  QOperand(QRegister rm)  // NOLINT(runtime/explicit)
      : NeonOperand(rm) {
    VIXL_ASSERT(rm_.IsValid());
  }

  QRegister GetRegister() const {
    VIXL_ASSERT(IsRegister() && (rm_.GetType() == CPURegister::kQRegister));
    return QRegister(rm_.GetCode());
  }
};

std::ostream& operator<<(std::ostream& os, const QOperand& operand);

class ImmediateVFP : public EncodingValue {
  template <typename T>
  struct FloatType {
    typedef T base_type;
  };

 public:
  explicit ImmediateVFP(const NeonImmediate& neon_imm) {
    if (neon_imm.IsFloat()) {
      const float imm = neon_imm.GetImmediate<float>();
      if (VFP::IsImmFP32(imm)) {
        SetEncodingValue(VFP::FP32ToImm8(imm));
      }
    } else if (neon_imm.IsDouble()) {
      const double imm = neon_imm.GetImmediate<double>();
      if (VFP::IsImmFP64(imm)) {
        SetEncodingValue(VFP::FP64ToImm8(imm));
      }
    }
  }

  template <typename T>
  static T Decode(uint32_t v) {
    return Decode(v, FloatType<T>());
  }

  static float Decode(uint32_t imm8, const FloatType<float>&) {
    return VFP::Imm8ToFP32(imm8);
  }

  static double Decode(uint32_t imm8, const FloatType<double>&) {
    return VFP::Imm8ToFP64(imm8);
  }
};


class ImmediateVbic : public EncodingValueAndImmediate {
 public:
  ImmediateVbic(DataType dt, const NeonImmediate& neon_imm);
  static DataType DecodeDt(uint32_t cmode);
  static NeonImmediate DecodeImmediate(uint32_t cmode, uint32_t immediate);
};

class ImmediateVand : public ImmediateVbic {
 public:
  ImmediateVand(DataType dt, const NeonImmediate neon_imm)
      : ImmediateVbic(dt, neon_imm) {
    if (IsValid()) {
      SetEncodedImmediate(~GetEncodedImmediate() & 0xff);
    }
  }
};

class ImmediateVmov : public EncodingValueAndImmediate {
 public:
  ImmediateVmov(DataType dt, const NeonImmediate& neon_imm);
  static DataType DecodeDt(uint32_t cmode);
  static NeonImmediate DecodeImmediate(uint32_t cmode, uint32_t immediate);
};

class ImmediateVmvn : public EncodingValueAndImmediate {
 public:
  ImmediateVmvn(DataType dt, const NeonImmediate& neon_imm);
  static DataType DecodeDt(uint32_t cmode);
  static NeonImmediate DecodeImmediate(uint32_t cmode, uint32_t immediate);
};

class ImmediateVorr : public EncodingValueAndImmediate {
 public:
  ImmediateVorr(DataType dt, const NeonImmediate& neon_imm);
  static DataType DecodeDt(uint32_t cmode);
  static NeonImmediate DecodeImmediate(uint32_t cmode, uint32_t immediate);
};

class ImmediateVorn : public ImmediateVorr {
 public:
  ImmediateVorn(DataType dt, const NeonImmediate& neon_imm)
      : ImmediateVorr(dt, neon_imm) {
    if (IsValid()) {
      SetEncodedImmediate(~GetEncodedImmediate() & 0xff);
    }
  }
};

// MemOperand represents the addressing mode of a load or store instruction.
//
//   Usage: <instr> <Rt> , <MemOperand>
//
//   where <instr> is the instruction to use (e.g., Ldr(), Str(), etc.),
//         <Rt> is general purpose register to be transferred,
//         <MemOperand> is the rest of the arguments to the instruction
//
//   <MemOperand> can be in one of 3 addressing modes:
//
//   [ <Rn>, <offset> ]   ==  offset addressing
//   [ <Rn>, <offset> ]!  ==  pre-indexed addressing
//   [ <Rn> ], <offset>   ==  post-indexed addressing
//
//   where <offset> can be one of:
//     - an immediate constant, such as <imm8>, <imm12>
//     - an index register <Rm>
//     - a shifted index register <Rm>, <shift> #<amount>
//
//   The index register may have an associated {+/-} sign,
//   which if omitted, defaults to + .
//
//   We have two constructors for the offset:
//
//   One with a signed value offset parameter. The value of sign_ is
//   "sign_of(constructor's offset parameter) and the value of offset_ is
//   "constructor's offset parameter".
//
//   The other with a sign and a positive value offset parameters. The value of
//   sign_ is "constructor's sign parameter" and the value of offset_ is
//   "constructor's sign parameter * constructor's offset parameter".
//
//   The value of offset_ reflects the effective offset. For an offset_ of 0,
//   sign_ can be positive or negative. Otherwise, sign_ always agrees with
//   the sign of offset_.
class MemOperand {
 public:
  // rn
  // where rn is the general purpose base register only
  explicit MemOperand(Register rn, AddrMode addrmode = Offset)
      : rn_(rn),
        offset_(0),
        sign_(plus),
        rm_(NoReg),
        shift_(LSL),
        shift_amount_(0),
        addrmode_(addrmode | kMemOperandRegisterOnly) {
    VIXL_ASSERT(rn_.IsValid());
  }

  // rn, #<imm>
  // where rn is the general purpose base register,
  //       <imm> is a 32-bit offset to add to rn
  //
  // Note: if rn is PC, then this form is equivalent to a "label"
  // Note: the second constructor allow minus zero (-0).
  MemOperand(Register rn, int32_t offset, AddrMode addrmode = Offset)
      : rn_(rn),
        offset_(offset),
        sign_((offset < 0) ? minus : plus),
        rm_(NoReg),
        shift_(LSL),
        shift_amount_(0),
        addrmode_(addrmode) {
    VIXL_ASSERT(rn_.IsValid());
  }
  MemOperand(Register rn, Sign sign, int32_t offset, AddrMode addrmode = Offset)
      : rn_(rn),
        offset_(sign.IsPlus() ? offset : -offset),
        sign_(sign),
        rm_(NoReg),
        shift_(LSL),
        shift_amount_(0),
        addrmode_(addrmode) {
    VIXL_ASSERT(rn_.IsValid());
    // With this constructor, the sign must only be specified by "sign".
    VIXL_ASSERT(offset >= 0);
  }

  // rn, {+/-}rm
  // where rn is the general purpose base register,
  //       {+/-} is the sign of the index register,
  //       rm is the general purpose index register,
  MemOperand(Register rn, Sign sign, Register rm, AddrMode addrmode = Offset)
      : rn_(rn),
        offset_(0),
        sign_(sign),
        rm_(rm),
        shift_(LSL),
        shift_amount_(0),
        addrmode_(addrmode) {
    VIXL_ASSERT(rn_.IsValid() && rm_.IsValid());
  }

  // rn, rm
  // where rn is the general purpose base register,
  //       rm is the general purpose index register,
  MemOperand(Register rn, Register rm, AddrMode addrmode = Offset)
      : rn_(rn),
        offset_(0),
        sign_(plus),
        rm_(rm),
        shift_(LSL),
        shift_amount_(0),
        addrmode_(addrmode) {
    VIXL_ASSERT(rn_.IsValid() && rm_.IsValid());
  }

  // rn, {+/-}rm, <shift>
  // where rn is the general purpose base register,
  //       {+/-} is the sign of the index register,
  //       rm is the general purpose index register,
  //       <shift> is RRX, applied to value from rm
  MemOperand(Register rn,
             Sign sign,
             Register rm,
             Shift shift,
             AddrMode addrmode = Offset)
      : rn_(rn),
        offset_(0),
        sign_(sign),
        rm_(rm),
        shift_(shift),
        shift_amount_(0),
        addrmode_(addrmode) {
    VIXL_ASSERT(rn_.IsValid() && rm_.IsValid());
    VIXL_ASSERT(shift_.IsRRX());
  }

  // rn, rm, <shift>
  // where rn is the general purpose base register,
  //       rm is the general purpose index register,
  //       <shift> is RRX, applied to value from rm
  MemOperand(Register rn, Register rm, Shift shift, AddrMode addrmode = Offset)
      : rn_(rn),
        offset_(0),
        sign_(plus),
        rm_(rm),
        shift_(shift),
        shift_amount_(0),
        addrmode_(addrmode) {
    VIXL_ASSERT(rn_.IsValid() && rm_.IsValid());
    VIXL_ASSERT(shift_.IsRRX());
  }

  // rn, {+/-}rm, <shift> #<amount>
  // where rn is the general purpose base register,
  //       {+/-} is the sign of the index register,
  //       rm is the general purpose index register,
  //       <shift> is one of {LSL, LSR, ASR, ROR}, applied to value from rm
  //       <shift_amount> is optional size to apply to value from rm
  MemOperand(Register rn,
             Sign sign,
             Register rm,
             Shift shift,
             uint32_t shift_amount,
             AddrMode addrmode = Offset)
      : rn_(rn),
        offset_(0),
        sign_(sign),
        rm_(rm),
        shift_(shift),
        shift_amount_(shift_amount),
        addrmode_(addrmode) {
    VIXL_ASSERT(rn_.IsValid() && rm_.IsValid());
    CheckShift();
  }

  // rn, rm, <shift> #<amount>
  // where rn is the general purpose base register,
  //       rm is the general purpose index register,
  //       <shift> is one of {LSL, LSR, ASR, ROR}, applied to value from rm
  //       <shift_amount> is optional size to apply to value from rm
  MemOperand(Register rn,
             Register rm,
             Shift shift,
             uint32_t shift_amount,
             AddrMode addrmode = Offset)
      : rn_(rn),
        offset_(0),
        sign_(plus),
        rm_(rm),
        shift_(shift),
        shift_amount_(shift_amount),
        addrmode_(addrmode) {
    VIXL_ASSERT(rn_.IsValid() && rm_.IsValid());
    CheckShift();
  }

  Register GetBaseRegister() const { return rn_; }
  int32_t GetOffsetImmediate() const { return offset_; }
  bool IsOffsetImmediateWithinRange(int min,
                                    int max,
                                    int multiple_of = 1) const {
    return (offset_ >= min) && (offset_ <= max) &&
           ((offset_ % multiple_of) == 0);
  }
  Sign GetSign() const { return sign_; }
  Register GetOffsetRegister() const { return rm_; }
  Shift GetShift() const { return shift_; }
  unsigned GetShiftAmount() const { return shift_amount_; }
  AddrMode GetAddrMode() const {
    return static_cast<AddrMode>(addrmode_ & kMemOperandAddrModeMask);
  }
  bool IsRegisterOnly() const {
    return (addrmode_ & kMemOperandRegisterOnly) != 0;
  }

  bool IsImmediate() const { return !rm_.IsValid(); }
  bool IsImmediateZero() const { return !rm_.IsValid() && (offset_ == 0); }
  bool IsPlainRegister() const {
    return rm_.IsValid() && shift_.IsLSL() && (shift_amount_ == 0);
  }
  bool IsShiftedRegister() const { return rm_.IsValid(); }
  bool IsImmediateOffset() const {
    return (GetAddrMode() == Offset) && !rm_.IsValid();
  }
  bool IsImmediateZeroOffset() const {
    return (GetAddrMode() == Offset) && !rm_.IsValid() && (offset_ == 0);
  }
  bool IsRegisterOffset() const {
    return (GetAddrMode() == Offset) && rm_.IsValid() && shift_.IsLSL() &&
           (shift_amount_ == 0);
  }
  bool IsShiftedRegisterOffset() const {
    return (GetAddrMode() == Offset) && rm_.IsValid();
  }
  uint32_t GetTypeEncodingValue() const {
    return shift_.IsRRX() ? kRRXEncodedValue : shift_.GetValue();
  }
  bool IsOffset() const { return GetAddrMode() == Offset; }
  bool IsPreIndex() const { return GetAddrMode() == PreIndex; }
  bool IsPostIndex() const { return GetAddrMode() == PostIndex; }
  bool IsShiftValid() const { return shift_.IsValidAmount(shift_amount_); }

 private:
  static const int kMemOperandRegisterOnly = 0x1000;
  static const int kMemOperandAddrModeMask = 0xfff;
  void CheckShift() {
#ifdef VIXL_DEBUG
    // Disallow any zero shift other than RRX #0 and LSL #0 .
    if ((shift_amount_ == 0) && shift_.IsRRX()) return;
    if ((shift_amount_ == 0) && !shift_.IsLSL()) {
      VIXL_ABORT_WITH_MSG(
          "A shift by 0 is only accepted in "
          "the case of lsl and will be treated as "
          "no shift.\n");
    }
    switch (shift_.GetType()) {
      case LSL:
        VIXL_ASSERT(shift_amount_ <= 31);
        break;
      case ROR:
        VIXL_ASSERT(shift_amount_ <= 31);
        break;
      case LSR:
      case ASR:
        VIXL_ASSERT(shift_amount_ <= 32);
        break;
      case RRX:
      default:
        VIXL_UNREACHABLE();
        break;
    }
#endif
  }
  Register rn_;
  int32_t offset_;
  Sign sign_;
  Register rm_;
  Shift shift_;
  uint32_t shift_amount_;
  uint32_t addrmode_;
};

std::ostream& operator<<(std::ostream& os, const MemOperand& operand);

class AlignedMemOperand : public MemOperand {
 public:
  AlignedMemOperand(Register rn, Alignment align, AddrMode addrmode = Offset)
      : MemOperand(rn, addrmode), align_(align) {
    VIXL_ASSERT(addrmode != PreIndex);
  }

  AlignedMemOperand(Register rn,
                    Alignment align,
                    Register rm,
                    AddrMode addrmode)
      : MemOperand(rn, rm, addrmode), align_(align) {
    VIXL_ASSERT(addrmode != PreIndex);
  }

  Alignment GetAlignment() const { return align_; }

 private:
  Alignment align_;
};

std::ostream& operator<<(std::ostream& os, const AlignedMemOperand& operand);

}  // namespace aarch32
}  // namespace vixl

#endif  // VIXL_AARCH32_OPERANDS_AARCH32_H_
