1b78f13911bfe6eda303e91ef215c87a165aae8aeAlexandre Rames// Copyright 2015, VIXL authors
288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// All rights reserved.
388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// Redistribution and use in source and binary forms, with or without
588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// modification, are permitted provided that the following conditions are met:
688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   * Redistributions of source code must retain the above copyright notice,
888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     this list of conditions and the following disclaimer.
988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   * Redistributions in binary form must reproduce the above copyright
1088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     notice, this list of conditions and the following disclaimer in the
1188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     documentation and/or other materials provided with the distribution.
1288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   * Neither the name of ARM Limited nor the names of its contributors may
1388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     be used to endorse or promote products derived from this software
1488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     without specific prior written permission.
1588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
1688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
1788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// POSSIBILITY OF SUCH DAMAGE.
2788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
28989663e3cb7be8ac458d71f8e8d99afd29b13a39Pierre Langlois#ifndef VIXL_AARCH32_OPERANDS_AARCH32_H_
29989663e3cb7be8ac458d71f8e8d99afd29b13a39Pierre Langlois#define VIXL_AARCH32_OPERANDS_AARCH32_H_
3088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
31d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#include "aarch32/instructions-aarch32.h"
3288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
3388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisnamespace vixl {
3488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisnamespace aarch32 {
3588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
3688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// Operand represents generic set of arguments to pass to an instruction.
3788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
3888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   Usage: <instr> <Rd> , <Operand>
3988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
4088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   where <instr> is the instruction to use (e.g., Mov(), Rsb(), etc.)
4188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//         <Rd> is the destination register
4288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//         <Operand> is the rest of the arguments to the instruction
4388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
4488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   <Operand> can be one of:
4588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
4688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   #<imm> - an unsigned 32-bit immediate value
4788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   <Rm>, <shift> <#amount> - immediate shifted register
4888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   <Rm>, <shift> <Rs> - register shifted register
4988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
5088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Operand {
5188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
5288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // { #<immediate> }
5388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where <immediate> is uint32_t.
5488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // This is allowed to be an implicit constructor because Operand is
5588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // a wrapper class that doesn't normally perform any type conversion.
5660241a544be0ebf48347789bf0ec268414364627Vincent Belliard  Operand(uint32_t immediate)  // NOLINT(runtime/explicit)
5788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(immediate),
5888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(NoReg),
5988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_(LSL),
6088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        amount_(0),
6188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rs_(NoReg) {}
6260241a544be0ebf48347789bf0ec268414364627Vincent Belliard  Operand(int32_t immediate)  // NOLINT(runtime/explicit)
63f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois      : imm_(immediate),
64f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois        rm_(NoReg),
65f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois        shift_(LSL),
66f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois        amount_(0),
67f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois        rs_(NoReg) {}
6888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
6988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // rm
7088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where rm is the base register
7188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // This is allowed to be an implicit constructor because Operand is
7288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // a wrapper class that doesn't normally perform any type conversion.
7360241a544be0ebf48347789bf0ec268414364627Vincent Belliard  Operand(Register rm)  // NOLINT(runtime/explicit)
7488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(0),
7588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(rm),
7688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_(LSL),
7788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        amount_(0),
7888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rs_(NoReg) {
7988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rm_.IsValid());
8088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
8188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
8288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // rm, <shift>
8388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where rm is the base register, and
8488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       <shift> is RRX
8588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Operand(Register rm, Shift shift)
8688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(0), rm_(rm), shift_(shift), amount_(0), rs_(NoReg) {
8788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rm_.IsValid());
8888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(shift_.IsRRX());
8988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
9088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
9188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // rm, <shift> #<amount>
9288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where rm is the base register, and
9388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       <shift> is one of {LSL, LSR, ASR, ROR}, and
9488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       <amount> is uint6_t.
9588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Operand(Register rm, Shift shift, uint32_t amount)
9688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(0), rm_(rm), shift_(shift), amount_(amount), rs_(NoReg) {
9788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rm_.IsValid());
9888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(!shift_.IsRRX());
9988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#ifdef VIXL_DEBUG
10088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    switch (shift_.GetType()) {
10188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case LSL:
10288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(amount_ <= 31);
10388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
10488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case ROR:
10588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(amount_ <= 31);
10688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
10788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case LSR:
10888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case ASR:
10988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(amount_ <= 32);
11088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
11188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case RRX:
11288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      default:
11388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_UNREACHABLE();
11488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
11588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
11688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#endif
11788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
11888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
11988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // rm, <shift> rs
12088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where rm is the base register, and
12188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       <shift> is one of {LSL, LSR, ASR, ROR}, and
12288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       rs is the shifted register
12388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Operand(Register rm, Shift shift, Register rs)
12488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(0), rm_(rm), shift_(shift), amount_(0), rs_(rs) {
12588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rm_.IsValid() && rs_.IsValid());
12688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(!shift_.IsRRX());
12788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
12888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
129f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois  // Factory methods creating operands from any integral or pointer type. The
130f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois  // source must fit into 32 bits.
131f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois  template <typename T>
132f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois  static Operand From(T immediate) {
133f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois#if __cplusplus >= 201103L
134f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois    VIXL_STATIC_ASSERT_MESSAGE(std::is_integral<T>::value,
135f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois                               "An integral type is required to build an "
136f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois                               "immediate operand.");
137f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois#endif
138efe0c1f222c9b2da15755b221ee0fa232939ce80Pierre Langlois    // Allow both a signed or unsigned 32 bit integer to be passed, but store it
139efe0c1f222c9b2da15755b221ee0fa232939ce80Pierre Langlois    // as a uint32_t. The signedness information will be lost. We have to add a
140efe0c1f222c9b2da15755b221ee0fa232939ce80Pierre Langlois    // static_cast to make sure the compiler does not complain about implicit 64
141efe0c1f222c9b2da15755b221ee0fa232939ce80Pierre Langlois    // to 32 narrowing. It's perfectly acceptable for the user to pass a 64-bit
142efe0c1f222c9b2da15755b221ee0fa232939ce80Pierre Langlois    // value, as long as it can be encoded in 32 bits.
143efe0c1f222c9b2da15755b221ee0fa232939ce80Pierre Langlois    VIXL_ASSERT(IsInt32(immediate) || IsUint32(immediate));
144f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois    return Operand(static_cast<uint32_t>(immediate));
145f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois  }
146f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois
147f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois  template <typename T>
148f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois  static Operand From(T* address) {
149f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois    uintptr_t address_as_integral = reinterpret_cast<uintptr_t>(address);
150f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois    VIXL_ASSERT(IsUint32(address_as_integral));
151f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois    return Operand(static_cast<uint32_t>(address_as_integral));
152f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois  }
153f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois
15488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsImmediate() const { return !rm_.IsValid(); }
15588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
15688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsPlainRegister() const {
15788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return rm_.IsValid() && !shift_.IsRRX() && !rs_.IsValid() && (amount_ == 0);
15888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
15988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
16088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsImmediateShiftedRegister() const {
16188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return rm_.IsValid() && !rs_.IsValid();
16288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
16388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
16488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsRegisterShiftedRegister() const {
16588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return rm_.IsValid() && rs_.IsValid();
16688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
16788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
16888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetImmediate() const {
16988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsImmediate());
17088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return imm_;
17188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
17288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
1732ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell  int32_t GetSignedImmediate() const {
1742ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell    VIXL_ASSERT(IsImmediate());
1752ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell    int32_t result;
1762ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell    memcpy(&result, &imm_, sizeof(result));
1772ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell    return result;
1782ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell  }
1792ec1f7562e90ebd295989c1323d59161a23dadfcMartyn Capewell
18088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register GetBaseRegister() const {
18188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsImmediateShiftedRegister() || IsRegisterShiftedRegister());
18288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return rm_;
18388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
18488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
18588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Shift GetShift() const {
18688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsImmediateShiftedRegister() || IsRegisterShiftedRegister());
18788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return shift_;
18888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
18988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
19088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetShiftAmount() const {
19188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsImmediateShiftedRegister());
19288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return amount_;
19388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
19488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
19588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register GetShiftRegister() const {
19688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsRegisterShiftedRegister());
19788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return rs_;
19888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
19988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
20088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetTypeEncodingValue() const {
20188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return shift_.IsRRX() ? kRRXEncodedValue : shift_.GetValue();
20288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
20388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
20488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
205f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois// Forbid implicitely creating operands around types that cannot be encoded
206f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois// into a uint32_t without loss.
207f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois#if __cplusplus >= 201103L
20860241a544be0ebf48347789bf0ec268414364627Vincent Belliard  Operand(int64_t) = delete;   // NOLINT(runtime/explicit)
20960241a544be0ebf48347789bf0ec268414364627Vincent Belliard  Operand(uint64_t) = delete;  // NOLINT(runtime/explicit)
21060241a544be0ebf48347789bf0ec268414364627Vincent Belliard  Operand(float) = delete;     // NOLINT(runtime/explicit)
21160241a544be0ebf48347789bf0ec268414364627Vincent Belliard  Operand(double) = delete;    // NOLINT(runtime/explicit)
212f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois#else
21334ecc5b8b9af49df5727cfc357db1fddc674cb44Jacob Bramley  VIXL_NO_RETURN_IN_DEBUG_MODE Operand(int64_t) {  // NOLINT(runtime/explicit)
214f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois    VIXL_UNREACHABLE();
215f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois  }
21634ecc5b8b9af49df5727cfc357db1fddc674cb44Jacob Bramley  VIXL_NO_RETURN_IN_DEBUG_MODE Operand(uint64_t) {  // NOLINT(runtime/explicit)
217f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois    VIXL_UNREACHABLE();
218f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois  }
21934ecc5b8b9af49df5727cfc357db1fddc674cb44Jacob Bramley  VIXL_NO_RETURN_IN_DEBUG_MODE Operand(float) {  // NOLINT
220f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois    VIXL_UNREACHABLE();
221f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois  }
22234ecc5b8b9af49df5727cfc357db1fddc674cb44Jacob Bramley  VIXL_NO_RETURN_IN_DEBUG_MODE Operand(double) {  // NOLINT
223f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois    VIXL_UNREACHABLE();
224f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois  }
225f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois#endif
226f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois
22788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t imm_;
22888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register rm_;
22988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Shift shift_;
23088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t amount_;
23188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register rs_;
23288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
23388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
23488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, const Operand& operand);
23588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
23688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass NeonImmediate {
23788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  template <typename T>
23888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  struct DataTypeIdentity {
23988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    T data_type_;
24088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  };
24188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
24288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
24388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // { #<immediate> }
24488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where <immediate> is 32 bit number.
24588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // This is allowed to be an implicit constructor because NeonImmediate is
24688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // a wrapper class that doesn't normally perform any type conversion.
24760241a544be0ebf48347789bf0ec268414364627Vincent Belliard  NeonImmediate(uint32_t immediate)  // NOLINT(runtime/explicit)
24888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(immediate),
24988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        immediate_type_(I32) {}
25060241a544be0ebf48347789bf0ec268414364627Vincent Belliard  NeonImmediate(int immediate)  // NOLINT(runtime/explicit)
25188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(immediate),
25288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        immediate_type_(I32) {}
25388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
25488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // { #<immediate> }
25588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where <immediate> is a 64 bit number
25688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // This is allowed to be an implicit constructor because NeonImmediate is
25788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // a wrapper class that doesn't normally perform any type conversion.
25860241a544be0ebf48347789bf0ec268414364627Vincent Belliard  NeonImmediate(int64_t immediate)  // NOLINT(runtime/explicit)
25988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(immediate),
26088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        immediate_type_(I64) {}
26160241a544be0ebf48347789bf0ec268414364627Vincent Belliard  NeonImmediate(uint64_t immediate)  // NOLINT(runtime/explicit)
26288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(immediate),
26388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        immediate_type_(I64) {}
26488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
26588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // { #<immediate> }
26688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where <immediate> is a non zero floating point number which can be encoded
26788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // as an 8 bit floating point (checked by the constructor).
26888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // This is allowed to be an implicit constructor because NeonImmediate is
26988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // a wrapper class that doesn't normally perform any type conversion.
27060241a544be0ebf48347789bf0ec268414364627Vincent Belliard  NeonImmediate(float immediate)  // NOLINT(runtime/explicit)
27188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(immediate),
27288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        immediate_type_(F32) {}
27360241a544be0ebf48347789bf0ec268414364627Vincent Belliard  NeonImmediate(double immediate)  // NOLINT(runtime/explicit)
27488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(immediate),
27588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        immediate_type_(F64) {}
27688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
27788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NeonImmediate(const NeonImmediate& src)
27888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(src.imm_), immediate_type_(src.immediate_type_) {}
27988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
28088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  template <typename T>
28188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  T GetImmediate() const {
28288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return GetImmediate(DataTypeIdentity<T>());
28388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
28488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
28588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  template <typename T>
28688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  T GetImmediate(const DataTypeIdentity<T>&) const {
28788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(sizeof(T) <= sizeof(uint32_t));
28888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(CanConvert<T>());
28988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (immediate_type_.Is(I64))
29088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      return static_cast<T>(imm_.u64_ & static_cast<T>(-1));
29188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (immediate_type_.Is(F64) || immediate_type_.Is(F32)) return 0;
29288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return static_cast<T>(imm_.u32_ & static_cast<T>(-1));
29388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
29488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
29588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint64_t GetImmediate(const DataTypeIdentity<uint64_t>&) const {
29688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(CanConvert<uint64_t>());
29788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (immediate_type_.Is(I32)) return imm_.u32_;
29888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (immediate_type_.Is(F64) || immediate_type_.Is(F32)) return 0;
29988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return imm_.u64_;
30088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
30188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  float GetImmediate(const DataTypeIdentity<float>&) const {
30288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(CanConvert<float>());
30388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (immediate_type_.Is(F64)) return static_cast<float>(imm_.d_);
30488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return imm_.f_;
30588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
30688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  double GetImmediate(const DataTypeIdentity<double>&) const {
30788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(CanConvert<double>());
30888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (immediate_type_.Is(F32)) return static_cast<double>(imm_.f_);
30988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return imm_.d_;
31088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
31188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
31288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsInteger32() const { return immediate_type_.Is(I32); }
31388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsInteger64() const { return immediate_type_.Is(I64); }
31488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsInteger() const { return IsInteger32() | IsInteger64(); }
31588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsFloat() const { return immediate_type_.Is(F32); }
31688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsDouble() const { return immediate_type_.Is(F64); }
31788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
31888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  template <typename T>
31988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool CanConvert() const {
32088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return CanConvert(DataTypeIdentity<T>());
32188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
32288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
32388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  template <typename T>
32488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool CanConvert(const DataTypeIdentity<T>&) const {
32588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(sizeof(T) < sizeof(uint32_t));
32688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (immediate_type_.Is(I32) && ((imm_.u32_ >> (8 * sizeof(T))) == 0)) ||
32788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           (immediate_type_.Is(I64) && ((imm_.u64_ >> (8 * sizeof(T))) == 0)) ||
32888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           (immediate_type_.Is(F32) && (imm_.f_ == 0.0f)) ||
32988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           (immediate_type_.Is(F64) && (imm_.d_ == 0.0));
33088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
33188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool CanConvert(const DataTypeIdentity<uint32_t>&) const {
33288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return immediate_type_.Is(I32) ||
33388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           (immediate_type_.Is(I64) && ((imm_.u64_ >> 32) == 0)) ||
33488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           (immediate_type_.Is(F32) && (imm_.f_ == 0.0f)) ||
33588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           (immediate_type_.Is(F64) && (imm_.d_ == 0.0));
33688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
33788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool CanConvert(const DataTypeIdentity<uint64_t>&) const {
33888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return IsInteger() || CanConvert<uint32_t>();
33988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
34088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool CanConvert(const DataTypeIdentity<float>&) const {
34188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return IsFloat() || IsDouble();
34288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
34388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool CanConvert(const DataTypeIdentity<double>&) const {
34488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return IsFloat() || IsDouble();
34588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
34688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  friend std::ostream& operator<<(std::ostream& os,
34788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                  const NeonImmediate& operand);
34888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
34988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
35088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  union NeonImmediateType {
35188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    uint64_t u64_;
35288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    double d_;
35388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    uint32_t u32_;
35488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    float f_;
35588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    NeonImmediateType(uint64_t u) : u64_(u) {}
35688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    NeonImmediateType(int64_t u) : u64_(u) {}
35788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    NeonImmediateType(uint32_t u) : u32_(u) {}
35888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    NeonImmediateType(int32_t u) : u32_(u) {}
35988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    NeonImmediateType(double d) : d_(d) {}
36088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    NeonImmediateType(float f) : f_(f) {}
36188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    NeonImmediateType(const NeonImmediateType& ref) : u64_(ref.u64_) {}
36288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  } imm_;
36388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
36488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DataType immediate_type_;
36588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
36688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
36788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, const NeonImmediate& operand);
36888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
36988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass NeonOperand {
37088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
37160241a544be0ebf48347789bf0ec268414364627Vincent Belliard  NeonOperand(int32_t immediate)  // NOLINT(runtime/explicit)
37288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(immediate),
37388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(NoDReg) {}
37460241a544be0ebf48347789bf0ec268414364627Vincent Belliard  NeonOperand(uint32_t immediate)  // NOLINT(runtime/explicit)
37588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(immediate),
37688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(NoDReg) {}
37760241a544be0ebf48347789bf0ec268414364627Vincent Belliard  NeonOperand(int64_t immediate)  // NOLINT(runtime/explicit)
37888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(immediate),
37988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(NoDReg) {}
38060241a544be0ebf48347789bf0ec268414364627Vincent Belliard  NeonOperand(uint64_t immediate)  // NOLINT(runtime/explicit)
38188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(immediate),
38288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(NoDReg) {}
38360241a544be0ebf48347789bf0ec268414364627Vincent Belliard  NeonOperand(float immediate)  // NOLINT(runtime/explicit)
38488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(immediate),
38588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(NoDReg) {}
38660241a544be0ebf48347789bf0ec268414364627Vincent Belliard  NeonOperand(double immediate)  // NOLINT(runtime/explicit)
38788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(immediate),
38888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(NoDReg) {}
38960241a544be0ebf48347789bf0ec268414364627Vincent Belliard  NeonOperand(const NeonImmediate& imm)  // NOLINT(runtime/explicit)
39088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(imm),
39188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(NoDReg) {}
392cf4d2842eb8d63c621d7003e240ec094a357cad0Jacob Bramley  NeonOperand(const VRegister& rm)  // NOLINT(runtime/explicit)
39388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_(0),
39488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(rm) {
39588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rm_.IsValid());
39688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
39788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
39888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsImmediate() const { return !rm_.IsValid(); }
39988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsRegister() const { return rm_.IsValid(); }
40088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
40188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const NeonImmediate& GetNeonImmediate() const { return imm_; }
40288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
403cf4d2842eb8d63c621d7003e240ec094a357cad0Jacob Bramley  VRegister GetRegister() const {
404cf4d2842eb8d63c621d7003e240ec094a357cad0Jacob Bramley    VIXL_ASSERT(IsRegister());
405cf4d2842eb8d63c621d7003e240ec094a357cad0Jacob Bramley    return rm_;
406cf4d2842eb8d63c621d7003e240ec094a357cad0Jacob Bramley  }
407cf4d2842eb8d63c621d7003e240ec094a357cad0Jacob Bramley
40888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois protected:
40988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NeonImmediate imm_;
410cf4d2842eb8d63c621d7003e240ec094a357cad0Jacob Bramley  VRegister rm_;
41188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
41288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
41388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, const NeonOperand& operand);
41488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
41588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// SOperand represents either an immediate or a SRegister.
41688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass SOperand : public NeonOperand {
41788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
41888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // #<immediate>
41988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where <immediate> is 32bit int
42088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // This is allowed to be an implicit constructor because SOperand is
42188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // a wrapper class that doesn't normally perform any type conversion.
42260241a544be0ebf48347789bf0ec268414364627Vincent Belliard  SOperand(int32_t immediate)  // NOLINT(runtime/explicit)
42388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(immediate) {}
42460241a544be0ebf48347789bf0ec268414364627Vincent Belliard  SOperand(uint32_t immediate)  // NOLINT(runtime/explicit)
42588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(immediate) {}
42688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // #<immediate>
42788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where <immediate> is 32bit float
42860241a544be0ebf48347789bf0ec268414364627Vincent Belliard  SOperand(float immediate)  // NOLINT(runtime/explicit)
42988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(immediate) {}
43088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
43188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SOperand(const NeonImmediate& imm)  // NOLINT(runtime/explicit)
43288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(imm) {}
43388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
43488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // rm
43588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // This is allowed to be an implicit constructor because SOperand is
43688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // a wrapper class that doesn't normally perform any type conversion.
43760241a544be0ebf48347789bf0ec268414364627Vincent Belliard  SOperand(SRegister rm)  // NOLINT(runtime/explicit)
43888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(rm) {}
43988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SRegister GetRegister() const {
44088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsRegister() && (rm_.GetType() == CPURegister::kSRegister));
44188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return SRegister(rm_.GetCode());
44288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
44388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
44488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
44588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// DOperand represents either an immediate or a DRegister.
44688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, const SOperand& operand);
44788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
44888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass DOperand : public NeonOperand {
44988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
45088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // #<immediate>
45188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where <immediate> is uint32_t.
45288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // This is allowed to be an implicit constructor because DOperand is
45388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // a wrapper class that doesn't normally perform any type conversion.
45460241a544be0ebf48347789bf0ec268414364627Vincent Belliard  DOperand(int32_t immediate)  // NOLINT(runtime/explicit)
45588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(immediate) {}
45660241a544be0ebf48347789bf0ec268414364627Vincent Belliard  DOperand(uint32_t immediate)  // NOLINT(runtime/explicit)
45788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(immediate) {}
45860241a544be0ebf48347789bf0ec268414364627Vincent Belliard  DOperand(int64_t immediate)  // NOLINT(runtime/explicit)
45988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(immediate) {}
46060241a544be0ebf48347789bf0ec268414364627Vincent Belliard  DOperand(uint64_t immediate)  // NOLINT(runtime/explicit)
46188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(immediate) {}
46288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
46388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // #<immediate>
46488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where <immediate> is a non zero floating point number which can be encoded
46588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // as an 8 bit floating point (checked by the constructor).
46688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // This is allowed to be an implicit constructor because DOperand is
46788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // a wrapper class that doesn't normally perform any type conversion.
46860241a544be0ebf48347789bf0ec268414364627Vincent Belliard  DOperand(float immediate)  // NOLINT(runtime/explicit)
46988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(immediate) {}
47060241a544be0ebf48347789bf0ec268414364627Vincent Belliard  DOperand(double immediate)  // NOLINT(runtime/explicit)
47188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(immediate) {}
47288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
47388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DOperand(const NeonImmediate& imm)  // NOLINT(runtime/explicit)
47488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(imm) {}
47588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // rm
47688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // This is allowed to be an implicit constructor because DOperand is
47788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // a wrapper class that doesn't normally perform any type conversion.
47860241a544be0ebf48347789bf0ec268414364627Vincent Belliard  DOperand(DRegister rm)  // NOLINT(runtime/explicit)
47988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(rm) {}
48088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
48188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegister GetRegister() const {
48288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsRegister() && (rm_.GetType() == CPURegister::kDRegister));
48388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return DRegister(rm_.GetCode());
48488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
48588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
48688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
48788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, const DOperand& operand);
48888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
48988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// QOperand represents either an immediate or a QRegister.
49088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass QOperand : public NeonOperand {
49188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
49288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // #<immediate>
49388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where <immediate> is uint32_t.
49488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // This is allowed to be an implicit constructor because QOperand is
49588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // a wrapper class that doesn't normally perform any type conversion.
49660241a544be0ebf48347789bf0ec268414364627Vincent Belliard  QOperand(int32_t immediate)  // NOLINT(runtime/explicit)
49788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(immediate) {}
49860241a544be0ebf48347789bf0ec268414364627Vincent Belliard  QOperand(uint32_t immediate)  // NOLINT(runtime/explicit)
49988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(immediate) {}
50060241a544be0ebf48347789bf0ec268414364627Vincent Belliard  QOperand(int64_t immediate)  // NOLINT(runtime/explicit)
50188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(immediate) {}
50260241a544be0ebf48347789bf0ec268414364627Vincent Belliard  QOperand(uint64_t immediate)  // NOLINT(runtime/explicit)
50388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(immediate) {}
50460241a544be0ebf48347789bf0ec268414364627Vincent Belliard  QOperand(float immediate)  // NOLINT(runtime/explicit)
50588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(immediate) {}
50660241a544be0ebf48347789bf0ec268414364627Vincent Belliard  QOperand(double immediate)  // NOLINT(runtime/explicit)
50788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(immediate) {}
50888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
50988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  QOperand(const NeonImmediate& imm)  // NOLINT(runtime/explicit)
51088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(imm) {}
51188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
51288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // rm
51388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // This is allowed to be an implicit constructor because QOperand is
51488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // a wrapper class that doesn't normally perform any type conversion.
51560241a544be0ebf48347789bf0ec268414364627Vincent Belliard  QOperand(QRegister rm)  // NOLINT(runtime/explicit)
51688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : NeonOperand(rm) {
51788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rm_.IsValid());
51888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
51988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
52088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  QRegister GetRegister() const {
52188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsRegister() && (rm_.GetType() == CPURegister::kQRegister));
52288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return QRegister(rm_.GetCode());
52388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
52488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
52588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
52688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, const QOperand& operand);
52788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
52888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass ImmediateVFP : public EncodingValue {
52988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  template <typename T>
53088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  struct FloatType {
53188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    typedef T base_type;
53288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  };
53388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
53488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
53588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit ImmediateVFP(const NeonImmediate& neon_imm) {
53688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (neon_imm.IsFloat()) {
53788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      const float imm = neon_imm.GetImmediate<float>();
53888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (VFP::IsImmFP32(imm)) {
53988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        SetEncodingValue(VFP::FP32ToImm8(imm));
54088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      }
54188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    } else if (neon_imm.IsDouble()) {
54288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      const double imm = neon_imm.GetImmediate<double>();
54388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (VFP::IsImmFP64(imm)) {
54488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        SetEncodingValue(VFP::FP32ToImm8(imm));
54588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      }
54688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
54788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
54888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
54988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  template <typename T>
55088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static T Decode(uint32_t v) {
55188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Decode(v, FloatType<T>());
55288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
55388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
55488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static float Decode(uint32_t imm8, const FloatType<float>&) {
55588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return VFP::Imm8ToFP32(imm8);
55688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
55788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
55888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static double Decode(uint32_t imm8, const FloatType<double>&) {
55988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return VFP::Imm8ToFP64(imm8);
56088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
56188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
56288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
56388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
56488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass ImmediateVbic : public EncodingValueAndImmediate {
56588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
56688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ImmediateVbic(DataType dt, const NeonImmediate& neon_imm);
56788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static DataType DecodeDt(uint32_t cmode);
56888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static NeonImmediate DecodeImmediate(uint32_t cmode, uint32_t immediate);
56988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
57088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
57188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass ImmediateVand : public ImmediateVbic {
57288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
57388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ImmediateVand(DataType dt, const NeonImmediate neon_imm)
57488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : ImmediateVbic(dt, neon_imm) {
57588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (IsValid()) {
57688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      SetEncodedImmediate(~GetEncodedImmediate() & 0xff);
57788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
57888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
57988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
58088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
58188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass ImmediateVmov : public EncodingValueAndImmediate {
58288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
58388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ImmediateVmov(DataType dt, const NeonImmediate& neon_imm);
58488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static DataType DecodeDt(uint32_t cmode);
58588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static NeonImmediate DecodeImmediate(uint32_t cmode, uint32_t immediate);
58688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
58788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
58888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass ImmediateVmvn : public EncodingValueAndImmediate {
58988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
59088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ImmediateVmvn(DataType dt, const NeonImmediate& neon_imm);
59188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static DataType DecodeDt(uint32_t cmode);
59288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static NeonImmediate DecodeImmediate(uint32_t cmode, uint32_t immediate);
59388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
59488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
59588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass ImmediateVorr : public EncodingValueAndImmediate {
59688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
59788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ImmediateVorr(DataType dt, const NeonImmediate& neon_imm);
59888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static DataType DecodeDt(uint32_t cmode);
59988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static NeonImmediate DecodeImmediate(uint32_t cmode, uint32_t immediate);
60088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
60188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
60288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass ImmediateVorn : public ImmediateVorr {
60388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
60488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ImmediateVorn(DataType dt, const NeonImmediate& neon_imm)
60588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : ImmediateVorr(dt, neon_imm) {
60688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (IsValid()) {
60788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      SetEncodedImmediate(~GetEncodedImmediate() & 0xff);
60888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
60988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
61088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
61188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
61288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// MemOperand represents the addressing mode of a load or store instruction.
61388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
61488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   Usage: <instr> <Rt> , <MemOperand>
61588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
61688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   where <instr> is the instruction to use (e.g., Ldr(), Str(), etc.),
61788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//         <Rt> is general purpose register to be transferred,
61888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//         <MemOperand> is the rest of the arguments to the instruction
61988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
62088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   <MemOperand> can be in one of 3 addressing modes:
62188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
62288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   [ <Rn>, <offset> ]   ==  offset addressing
62388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   [ <Rn>, <offset> ]!  ==  pre-indexed addressing
62488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   [ <Rn> ], <offset>   ==  post-indexed addressing
62588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
62688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   where <offset> can be one of:
62788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     - an immediate constant, such as <imm8>, <imm12>
62888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     - an index register <Rm>
62988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     - a shifted index register <Rm>, <shift> #<amount>
63088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
63188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   The index register may have an associated {+/-} sign,
63288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   which if ommitted, defaults to + .
63388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
6347f24bc630745306bf9be3881b510e00bbbf19ae3Vincent Belliard//   We have two constructors for the offset:
6357f24bc630745306bf9be3881b510e00bbbf19ae3Vincent Belliard//
6367f24bc630745306bf9be3881b510e00bbbf19ae3Vincent Belliard//   One with a signed value offset parameter. The value of sign_ is
6377f24bc630745306bf9be3881b510e00bbbf19ae3Vincent Belliard//   "sign_of(constructor's offset parameter) and the value of offset_ is
6387f24bc630745306bf9be3881b510e00bbbf19ae3Vincent Belliard//   "constructor's offset parameter".
6397f24bc630745306bf9be3881b510e00bbbf19ae3Vincent Belliard//
6407f24bc630745306bf9be3881b510e00bbbf19ae3Vincent Belliard//   The other with a sign and a positive value offset parameters. The value of
6417f24bc630745306bf9be3881b510e00bbbf19ae3Vincent Belliard//   sign_ is "constructor's sign parameter" and the value of offset_ is
6427f24bc630745306bf9be3881b510e00bbbf19ae3Vincent Belliard//   "constructor's sign parameter * constructor's offset parameter".
6437f24bc630745306bf9be3881b510e00bbbf19ae3Vincent Belliard//
6447f24bc630745306bf9be3881b510e00bbbf19ae3Vincent Belliard//   The value of offset_ reflects the effective offset. For an offset_ of 0,
6457f24bc630745306bf9be3881b510e00bbbf19ae3Vincent Belliard//   sign_ can be positive or negative. Otherwise, sign_ always agrees with
6467f24bc630745306bf9be3881b510e00bbbf19ae3Vincent Belliard//   the sign of offset_.
64788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass MemOperand {
64888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
64988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // rn
65088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where rn is the general purpose base register only
651024aa58e9d83147f57a2509cf115b9fc9d260477Alexandre Rames  explicit MemOperand(Register rn, AddrMode addrmode = Offset)
65288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : rn_(rn),
65388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        offset_(0),
65488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        sign_(plus),
65588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(NoReg),
65688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_(LSL),
65788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_amount_(0),
65888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        addrmode_(addrmode | kMemOperandRegisterOnly) {
65988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rn_.IsValid());
66088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
66188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
66288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // rn, #<imm>
66388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where rn is the general purpose base register,
66488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       <imm> is a 32-bit offset to add to rn
66588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //
66688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Note: if rn is PC, then this form is equivalent to a "label"
66788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Note: the second constructor allow minus zero (-0).
66888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MemOperand(Register rn, int32_t offset, AddrMode addrmode = Offset)
66988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : rn_(rn),
67088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        offset_(offset),
67188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        sign_((offset < 0) ? minus : plus),
67288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(NoReg),
67388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_(LSL),
67488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_amount_(0),
67588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        addrmode_(addrmode) {
67688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rn_.IsValid());
67788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
67888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MemOperand(Register rn, Sign sign, int32_t offset, AddrMode addrmode = Offset)
67988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : rn_(rn),
68088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        offset_(sign.IsPlus() ? offset : -offset),
68188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        sign_(sign),
68288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(NoReg),
68388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_(LSL),
68488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_amount_(0),
68588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        addrmode_(addrmode) {
68688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rn_.IsValid());
68788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    // With this constructor, the sign must only be specified by "sign".
68888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(offset >= 0);
68988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
69088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
69188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // rn, {+/-}rm
69288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where rn is the general purpose base register,
69388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       {+/-} is the sign of the index register,
69488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       rm is the general purpose index register,
69588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MemOperand(Register rn, Sign sign, Register rm, AddrMode addrmode = Offset)
69688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : rn_(rn),
69788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        offset_(0),
69888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        sign_(sign),
69988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(rm),
70088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_(LSL),
70188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_amount_(0),
70288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        addrmode_(addrmode) {
70388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rn_.IsValid() && rm_.IsValid());
70488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
70588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
70688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // rn, rm
70788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where rn is the general purpose base register,
70888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       rm is the general purpose index register,
70988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MemOperand(Register rn, Register rm, AddrMode addrmode = Offset)
71088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : rn_(rn),
71188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        offset_(0),
71288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        sign_(plus),
71388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(rm),
71488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_(LSL),
71588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_amount_(0),
71688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        addrmode_(addrmode) {
71788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rn_.IsValid() && rm_.IsValid());
71888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
71988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
72088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // rn, {+/-}rm, <shift>
72188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where rn is the general purpose base register,
72288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       {+/-} is the sign of the index register,
72388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       rm is the general purpose index register,
72488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       <shift> is RRX, applied to value from rm
72588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MemOperand(Register rn,
72688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             Sign sign,
72788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             Register rm,
72888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             Shift shift,
72988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             AddrMode addrmode = Offset)
73088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : rn_(rn),
73188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        offset_(0),
73288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        sign_(sign),
73388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(rm),
73488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_(shift),
73588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_amount_(0),
73688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        addrmode_(addrmode) {
73788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rn_.IsValid() && rm_.IsValid());
73888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(shift_.IsRRX());
73988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
74088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
74188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // rn, rm, <shift>
74288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where rn is the general purpose base register,
74388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       rm is the general purpose index register,
74488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       <shift> is RRX, applied to value from rm
74588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MemOperand(Register rn, Register rm, Shift shift, AddrMode addrmode = Offset)
74688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : rn_(rn),
74788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        offset_(0),
74888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        sign_(plus),
74988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(rm),
75088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_(shift),
75188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_amount_(0),
75288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        addrmode_(addrmode) {
75388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rn_.IsValid() && rm_.IsValid());
75488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(shift_.IsRRX());
75588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
75688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
75788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // rn, {+/-}rm, <shift> #<amount>
75888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where rn is the general purpose base register,
75988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       {+/-} is the sign of the index register,
76088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       rm is the general purpose index register,
76188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       <shift> is one of {LSL, LSR, ASR, ROR}, applied to value from rm
76288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       <shift_amount> is optional size to apply to value from rm
76388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MemOperand(Register rn,
76488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             Sign sign,
76588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             Register rm,
76688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             Shift shift,
76788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             uint32_t shift_amount,
76888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             AddrMode addrmode = Offset)
76988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : rn_(rn),
77088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        offset_(0),
77188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        sign_(sign),
77288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(rm),
77388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_(shift),
77488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_amount_(shift_amount),
77588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        addrmode_(addrmode) {
77688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rn_.IsValid() && rm_.IsValid());
77788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    CheckShift();
77888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
77988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
78088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // rn, rm, <shift> #<amount>
78188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where rn is the general purpose base register,
78288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       rm is the general purpose index register,
78388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       <shift> is one of {LSL, LSR, ASR, ROR}, applied to value from rm
78488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //       <shift_amount> is optional size to apply to value from rm
78588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MemOperand(Register rn,
78688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             Register rm,
78788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             Shift shift,
78888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             uint32_t shift_amount,
78988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             AddrMode addrmode = Offset)
79088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : rn_(rn),
79188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        offset_(0),
79288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        sign_(plus),
79388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        rm_(rm),
79488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_(shift),
79588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        shift_amount_(shift_amount),
79688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        addrmode_(addrmode) {
79788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rn_.IsValid() && rm_.IsValid());
79888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    CheckShift();
79988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
80088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
80188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register GetBaseRegister() const { return rn_; }
80288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int32_t GetOffsetImmediate() const { return offset_; }
80388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsOffsetImmediateWithinRange(int min,
80488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                    int max,
80588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                    int multiple_of = 1) const {
80688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (offset_ >= min) && (offset_ <= max) &&
80788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           ((offset_ % multiple_of) == 0);
80888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
80988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Sign GetSign() const { return sign_; }
81088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register GetOffsetRegister() const { return rm_; }
81188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Shift GetShift() const { return shift_; }
81288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  unsigned GetShiftAmount() const { return shift_amount_; }
81388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  AddrMode GetAddrMode() const {
81488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return static_cast<AddrMode>(addrmode_ & kMemOperandAddrModeMask);
81588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
81688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsRegisterOnly() const {
81788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (addrmode_ & kMemOperandRegisterOnly) != 0;
81888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
81988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
82088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsImmediate() const { return !rm_.IsValid(); }
82188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsImmediateZero() const { return !rm_.IsValid() && (offset_ == 0); }
82288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsPlainRegister() const {
82388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return rm_.IsValid() && shift_.IsLSL() && (shift_amount_ == 0);
82488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
82588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsShiftedRegister() const { return rm_.IsValid(); }
82688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsImmediateOffset() const {
82788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (GetAddrMode() == Offset) && !rm_.IsValid();
82888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
82988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsImmediateZeroOffset() const {
83088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (GetAddrMode() == Offset) && !rm_.IsValid() && (offset_ == 0);
83188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
83288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsRegisterOffset() const {
83388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (GetAddrMode() == Offset) && rm_.IsValid() && shift_.IsLSL() &&
83488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           (shift_amount_ == 0);
83588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
83688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsShiftedRegisterOffset() const {
83788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (GetAddrMode() == Offset) && rm_.IsValid();
83888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
83988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetTypeEncodingValue() const {
84088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return shift_.IsRRX() ? kRRXEncodedValue : shift_.GetValue();
84188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
84288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsOffset() const { return GetAddrMode() == Offset; }
84388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsPreIndex() const { return GetAddrMode() == PreIndex; }
84488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsPostIndex() const { return GetAddrMode() == PostIndex; }
84588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsShiftValid() const { return shift_.IsValidAmount(shift_amount_); }
84688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
84788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
84888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const int kMemOperandRegisterOnly = 0x1000;
84988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const int kMemOperandAddrModeMask = 0xfff;
85088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void CheckShift() {
85188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#ifdef VIXL_DEBUG
85288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    // Disallow any zero shift other than RRX #0 and LSL #0 .
85388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if ((shift_amount_ == 0) && shift_.IsRRX()) return;
85488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if ((shift_amount_ == 0) && !shift_.IsLSL()) {
85588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      VIXL_ABORT_WITH_MSG(
85688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          "A shift by 0 is only accepted in "
857028fb0566f6af6d839d34ccfec754ba394510302Jacob Bramley          "the case of lsl and will be treated as "
858028fb0566f6af6d839d34ccfec754ba394510302Jacob Bramley          "no shift.\n");
85988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
86088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    switch (shift_.GetType()) {
86188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case LSL:
86288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(shift_amount_ <= 31);
86388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
86488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case ROR:
86588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(shift_amount_ <= 31);
86688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
86788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case LSR:
86888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case ASR:
86988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(shift_amount_ <= 32);
87088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
87188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case RRX:
87288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      default:
87388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_UNREACHABLE();
87488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
87588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
87688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#endif
87788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
87888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register rn_;
87988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int32_t offset_;
88088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Sign sign_;
88188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register rm_;
88288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Shift shift_;
88388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t shift_amount_;
88488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t addrmode_;
88588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
88688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
88788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, const MemOperand& operand);
88888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
88988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass AlignedMemOperand : public MemOperand {
89088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
89188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  AlignedMemOperand(Register rn, Alignment align, AddrMode addrmode = Offset)
89288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : MemOperand(rn, addrmode), align_(align) {
89388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(addrmode != PreIndex);
89488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
89588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
89688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  AlignedMemOperand(Register rn,
89788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    Alignment align,
89888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    Register rm,
89988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    AddrMode addrmode)
90088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : MemOperand(rn, rm, addrmode), align_(align) {
90188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(addrmode != PreIndex);
90288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
90388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
90488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Alignment GetAlignment() const { return align_; }
90588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
90688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
90788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Alignment align_;
90888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
90988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
91088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, const AlignedMemOperand& operand);
91188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
91288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}  // namespace aarch32
91388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}  // namespace vixl
91488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
915989663e3cb7be8ac458d71f8e8d99afd29b13a39Pierre Langlois#endif  // VIXL_AARCH32_OPERANDS_AARCH32_H_
916