instructions-aarch32.h revision adbb4a746d2d90dd2920a8e0b7cd2397e93d17b9
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 notice,
1088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     this list of conditions and the following disclaimer in the documentation
1188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     and/or other materials provided with the distribution.
1288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   * Neither the name of ARM Limited nor the names of its contributors may be
1388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     used to endorse or promote products derived from this software without
1488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     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 IMPLIED
1888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
2088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
27d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#ifndef VIXL_AARCH32_INSTRUCTIONS_AARCH32_H_
28d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#define VIXL_AARCH32_INSTRUCTIONS_AARCH32_H_
2988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
3078973f258039f6e96eba85f1b5ecdb14b3c51dbbPierre Langloisextern "C" {
3188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#include <stdint.h>
3278973f258039f6e96eba85f1b5ecdb14b3c51dbbPierre Langlois}
3378973f258039f6e96eba85f1b5ecdb14b3c51dbbPierre Langlois
3488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#include <algorithm>
3578973f258039f6e96eba85f1b5ecdb14b3c51dbbPierre Langlois#include <ostream>
3678973f258039f6e96eba85f1b5ecdb14b3c51dbbPierre Langlois
3788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#include "utils-vixl.h"
383e1b899f48c1328ac748b1f5fa78f417f7ec6581Vincent Belliard#include "code-buffer-vixl.h"
39d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#include "aarch32/constants-aarch32.h"
40d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#include "aarch32/label-aarch32.h"
4188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
4288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#ifdef __arm__
4388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define HARDFLOAT __attribute__((noinline, pcs("aapcs-vfp")))
4488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#else
4588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define HARDFLOAT __attribute__((noinline))
4688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#endif
4788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
4888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisnamespace vixl {
4988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisnamespace aarch32 {
5088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
5188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Operand;
5288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass SOperand;
5388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass DOperand;
5488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass QOperand;
5588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass MemOperand;
5688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass AlignedMemOperand;
5788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
5888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum AddrMode { Offset = 0, PreIndex = 1, PostIndex = 2 };
5910dae1a549308bddc1931f29754d6a4459f70c9bJacob Bramleyenum InstructionSet { A32, T32 };
6088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
6188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass CPURegister {
6288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
6388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  enum RegisterType {
6488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    kNoRegister = 0,
6588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    kRRegister = 1,
6688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    kSRegister = 2,
6788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    kDRegister = 3,
6888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    kQRegister = 4
6988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  };
7088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
7188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
7288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const int kCodeBits = 5;
7388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const int kTypeBits = 4;
7488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const int kSizeBits = 8;
7588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const int kCodeShift = 0;
7688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const int kTypeShift = kCodeShift + kCodeBits;
7788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const int kSizeShift = kTypeShift + kTypeBits;
7888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const uint32_t kCodeMask = ((1 << kCodeBits) - 1) << kCodeShift;
7988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const uint32_t kTypeMask = ((1 << kTypeBits) - 1) << kTypeShift;
8088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const uint32_t kSizeMask = ((1 << kSizeBits) - 1) << kSizeShift;
8188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t value_;
8288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
8388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
8488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPURegister(RegisterType type, uint32_t code, int size)
8588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : value_((type << kTypeShift) | (code << kCodeShift) |
8688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois               (size << kSizeShift)) {
8788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#ifdef VIXL_DEBUG
8888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    switch (type) {
8988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case kNoRegister:
9088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
9188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case kRRegister:
9288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(code < kNumberOfRegisters);
9388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(size == kRegSizeInBits);
9488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
9588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case kSRegister:
9688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(code < kNumberOfSRegisters);
9788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(size == kSRegSizeInBits);
9888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
9988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case kDRegister:
10088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(code < kMaxNumberOfDRegisters);
10188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(size == kDRegSizeInBits);
10288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
10388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case kQRegister:
10488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(code < kNumberOfQRegisters);
10588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(size == kQRegSizeInBits);
10688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
10788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      default:
10888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_UNREACHABLE();
10988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
11088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
11188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#endif
11288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
11388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegisterType GetType() const {
11488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return static_cast<RegisterType>((value_ & kTypeMask) >> kTypeShift);
11588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
116f678618ae35a43dab65455f446c3de324994c204Vincent Belliard  bool IsRegister() const { return GetType() == kRRegister; }
117f678618ae35a43dab65455f446c3de324994c204Vincent Belliard  bool IsS() const { return GetType() == kSRegister; }
118f678618ae35a43dab65455f446c3de324994c204Vincent Belliard  bool IsD() const { return GetType() == kDRegister; }
119f678618ae35a43dab65455f446c3de324994c204Vincent Belliard  bool IsQ() const { return GetType() == kQRegister; }
120f678618ae35a43dab65455f446c3de324994c204Vincent Belliard  bool IsVRegister() const { return IsS() || IsD() || IsQ(); }
121f678618ae35a43dab65455f446c3de324994c204Vincent Belliard  bool IsFPRegister() const { return IsS() || IsD(); }
12288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetCode() const { return (value_ & kCodeMask) >> kCodeShift; }
12388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetReg() const { return value_; }
12488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int GetSizeInBits() const { return (value_ & kSizeMask) >> kSizeShift; }
12588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int GetRegSizeInBytes() const {
12688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (GetType() == kNoRegister) ? 0 : (GetSizeInBits() / 8);
12788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
12888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is64Bits() const { return GetSizeInBits() == 64; }
12988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is128Bits() const { return GetSizeInBits() == 128; }
13088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsSameFormat(CPURegister reg) {
13188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (value_ & ~kCodeMask) == (reg.value_ & ~kCodeMask);
13288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
13388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(CPURegister ref) const { return GetReg() == ref.GetReg(); }
13488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsValid() const { return GetType() != kNoRegister; }
13588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
13688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
13788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Register : public CPURegister {
13888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
13988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register() : CPURegister(kNoRegister, 0, kRegSizeInBits) {}
14088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit Register(uint32_t code)
14188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : CPURegister(kRRegister, code % kNumberOfRegisters, kRegSizeInBits) {
14288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetCode() < kNumberOfRegisters);
14388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
14488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(Register ref) const { return GetCode() == ref.GetCode(); }
14588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsLow() const { return GetCode() < kNumberOfT32LowRegisters; }
14688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsLR() const { return GetCode() == kLrCode; }
14788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsPC() const { return GetCode() == kPcCode; }
14888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsSP() const { return GetCode() == kSpCode; }
14988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
15088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
15188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, const Register reg);
15288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
153adbb4a746d2d90dd2920a8e0b7cd2397e93d17b9Vincent Belliardclass RegisterOrAPSR_nzcv {
154adbb4a746d2d90dd2920a8e0b7cd2397e93d17b9Vincent Belliard  uint32_t code_;
155adbb4a746d2d90dd2920a8e0b7cd2397e93d17b9Vincent Belliard
15688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
157adbb4a746d2d90dd2920a8e0b7cd2397e93d17b9Vincent Belliard  explicit RegisterOrAPSR_nzcv(uint32_t code) : code_(code) {
158adbb4a746d2d90dd2920a8e0b7cd2397e93d17b9Vincent Belliard    VIXL_ASSERT(code_ < kNumberOfRegisters);
159adbb4a746d2d90dd2920a8e0b7cd2397e93d17b9Vincent Belliard  }
160adbb4a746d2d90dd2920a8e0b7cd2397e93d17b9Vincent Belliard  bool IsAPSR_nzcv() const { return code_ == kPcCode; }
161adbb4a746d2d90dd2920a8e0b7cd2397e93d17b9Vincent Belliard  uint32_t GetCode() const { return code_; }
162adbb4a746d2d90dd2920a8e0b7cd2397e93d17b9Vincent Belliard  Register AsRegister() const {
163adbb4a746d2d90dd2920a8e0b7cd2397e93d17b9Vincent Belliard    VIXL_ASSERT(!IsAPSR_nzcv());
164adbb4a746d2d90dd2920a8e0b7cd2397e93d17b9Vincent Belliard    return Register(code_);
165adbb4a746d2d90dd2920a8e0b7cd2397e93d17b9Vincent Belliard  }
16688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
16788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
16888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os,
16988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                const RegisterOrAPSR_nzcv reg) {
170adbb4a746d2d90dd2920a8e0b7cd2397e93d17b9Vincent Belliard  if (reg.IsAPSR_nzcv()) return os << "APSR_nzcv";
171adbb4a746d2d90dd2920a8e0b7cd2397e93d17b9Vincent Belliard  return os << reg.AsRegister();
17288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
17388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
17488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass SRegister;
17588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass DRegister;
17688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass QRegister;
17788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
17888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass VRegister : public CPURegister {
17988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
18088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VRegister() : CPURegister(kNoRegister, 0, 0) {}
18188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VRegister(RegisterType type, uint32_t code, int size)
18288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : CPURegister(type, code, size) {}
18388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
18488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SRegister S() const;
18588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegister D() const;
18688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  QRegister Q() const;
18788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
18888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
18988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass SRegister : public VRegister {
19088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
19188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SRegister() : VRegister(kNoRegister, 0, kSRegSizeInBits) {}
19288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit SRegister(uint32_t code)
19388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : VRegister(kSRegister, code, kSRegSizeInBits) {}
19488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t Encode(int single_bit_field, int four_bit_field_lowest_bit) const {
19588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (four_bit_field_lowest_bit == 0) {
19688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      return ((GetCode() & 0x1) << single_bit_field) |
19788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             ((GetCode() & 0x1e) >> 1);
19888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
19988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return ((GetCode() & 0x1) << single_bit_field) |
20088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           ((GetCode() & 0x1e) << (four_bit_field_lowest_bit - 1));
20188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
20288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
20388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
20488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline unsigned ExtractSRegister(uint32_t instr,
20588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                 int single_bit_field,
20688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                 int four_bit_field_lowest_bit) {
20788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(single_bit_field > 0);
20888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (four_bit_field_lowest_bit == 0) {
20988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return ((instr << 1) & 0x1e) | ((instr >> single_bit_field) & 0x1);
21088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
21188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return ((instr >> (four_bit_field_lowest_bit - 1)) & 0x1e) |
21288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois         ((instr >> single_bit_field) & 0x1);
21388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
21488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
21588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, const SRegister reg) {
21688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << "s" << reg.GetCode();
21788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
21888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
21988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass DRegister : public VRegister {
22088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
22188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegister() : VRegister(kNoRegister, 0, kDRegSizeInBits) {}
22288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit DRegister(uint32_t code)
22388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : VRegister(kDRegister, code, kDRegSizeInBits) {}
22497a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard  SRegister GetLane(uint32_t lane) const {
22597a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    uint32_t lane_count = kDRegSizeInBits / kSRegSizeInBits;
22697a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    VIXL_ASSERT(lane < lane_count);
22797a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    VIXL_ASSERT(GetCode() * lane_count < kNumberOfSRegisters);
22897a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    return SRegister(GetCode() * lane_count + lane);
22997a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard  }
23088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t Encode(int single_bit_field, int four_bit_field_lowest_bit) const {
23188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(single_bit_field >= 4);
23288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return ((GetCode() & 0x10) << (single_bit_field - 4)) |
23388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           ((GetCode() & 0xf) << four_bit_field_lowest_bit);
23488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
23588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
23688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
23788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline unsigned ExtractDRegister(uint32_t instr,
23888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                 int single_bit_field,
23988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                 int four_bit_field_lowest_bit) {
24088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(single_bit_field >= 4);
24188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return ((instr >> (single_bit_field - 4)) & 0x10) |
24288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois         ((instr >> four_bit_field_lowest_bit) & 0xf);
24388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
24488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
24588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, const DRegister reg) {
24688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << "d" << reg.GetCode();
24788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
24888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
24988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum DataTypeType {
25088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeS = 0x100,
25188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeU = 0x200,
25288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeF = 0x300,
25388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeI = 0x400,
25488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeP = 0x500,
25588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeUntyped = 0x600
25688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
25788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst int kDataTypeSizeMask = 0x0ff;
25888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst int kDataTypeTypeMask = 0x100;
25988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum DataTypeValue {
26088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeValueInvalid = 0x000,
26188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeValueNone = 0x001,  // value used when dt is ignored.
26288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  S8 = kDataTypeS | 8,
26388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  S16 = kDataTypeS | 16,
26488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  S32 = kDataTypeS | 32,
26588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  S64 = kDataTypeS | 64,
26688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  U8 = kDataTypeU | 8,
26788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  U16 = kDataTypeU | 16,
26888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  U32 = kDataTypeU | 32,
26988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  U64 = kDataTypeU | 64,
27088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  F16 = kDataTypeF | 16,
27188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  F32 = kDataTypeF | 32,
27288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  F64 = kDataTypeF | 64,
27388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  I8 = kDataTypeI | 8,
27488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  I16 = kDataTypeI | 16,
27588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  I32 = kDataTypeI | 32,
27688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  I64 = kDataTypeI | 64,
27788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  P8 = kDataTypeP | 8,
27888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  P64 = kDataTypeP | 64,
27988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Untyped8 = kDataTypeUntyped | 8,
28088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Untyped16 = kDataTypeUntyped | 16,
28188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Untyped32 = kDataTypeUntyped | 32,
28288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Untyped64 = kDataTypeUntyped | 64
28388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
28488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
28588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass DataType {
28688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DataTypeValue value_;
28788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
28888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
28960241a544be0ebf48347789bf0ec268414364627Vincent Belliard  DataType(DataTypeValue value) : value_(value) {}  // NOLINT(runtime/explicit)
29060241a544be0ebf48347789bf0ec268414364627Vincent Belliard  DataType(uint32_t size)                           // NOLINT(runtime/explicit)
29188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : value_(static_cast<DataTypeValue>(kDataTypeUntyped | size)) {
29288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT((size == 8) || (size == 16) || (size == 32) || (size == 64));
29388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
29488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DataTypeValue GetValue() const { return value_; }
29588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DataTypeType GetType() const {
29688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return static_cast<DataTypeType>(value_ & kDataTypeTypeMask);
29788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
29888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetSize() const { return value_ & kDataTypeSizeMask; }
29988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsSize(uint32_t size) const {
30088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (value_ & kDataTypeSizeMask) == size;
30188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
30288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
30388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(DataTypeValue value) const { return value_ == value; }
30488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(DataTypeType type) const { return GetType() == type; }
30588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNoneOr(DataTypeValue value) const {
30688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (value_ == value) || (value_ == kDataTypeValueNone);
30788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
30888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(DataTypeType type, uint32_t size) const {
30988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return value_ == static_cast<DataTypeValue>(type | size);
31088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
31188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNoneOr(DataTypeType type, uint32_t size) const {
31288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Is(type, size) || Is(kDataTypeValueNone);
31388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
31488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
31588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
31688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, DataType dt) {
31788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << dt.GetName();
31888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
31988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
32088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass DRegisterLane : public DRegister {
32188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t lane_;
32288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
32388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
32488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegisterLane(DRegister reg, uint32_t lane)
32588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : DRegister(reg.GetCode()), lane_(lane) {}
32688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegisterLane(uint32_t code, uint32_t lane) : DRegister(code), lane_(lane) {}
32788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetLane() const { return lane_; }
32888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t EncodeX(DataType dt,
32988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   int single_bit_field,
33088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   int four_bit_field_lowest_bit) const {
33188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(single_bit_field >= 4);
33288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    uint32_t value = lane_ << ((dt.GetSize() == 16) ? 3 : 4) | GetCode();
33388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return ((value & 0x10) << (single_bit_field - 4)) |
33488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           ((value & 0xf) << four_bit_field_lowest_bit);
33588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
33688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
33788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
33888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline unsigned ExtractDRegisterAndLane(uint32_t instr,
33988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                        DataType dt,
34088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                        int single_bit_field,
34188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                        int four_bit_field_lowest_bit,
34288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                        int* lane) {
34388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(single_bit_field >= 4);
34488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t value = ((instr >> (single_bit_field - 4)) & 0x10) |
34588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   ((instr >> four_bit_field_lowest_bit) & 0xf);
34688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (dt.GetSize() == 16) {
34788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    *lane = value >> 3;
34888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return value & 0x7;
34988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
35088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  *lane = value >> 4;
35188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return value & 0xf;
35288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
35388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
35488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, const DRegisterLane lane) {
35588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  os << "d" << lane.GetCode() << "[";
35688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (lane.GetLane() == static_cast<uint32_t>(-1)) return os << "??]";
35788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << lane.GetLane() << "]";
35888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
35988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
36088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass QRegister : public VRegister {
36188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
36288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  QRegister() : VRegister(kNoRegister, 0, kQRegSizeInBits) {}
36388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit QRegister(uint32_t code)
36488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : VRegister(kQRegister, code, kQRegSizeInBits) {}
36588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t Encode(int offset) { return GetCode() << offset; }
36697a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard  DRegister GetDLane(uint32_t lane) const {
36797a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    uint32_t lane_count = kQRegSizeInBits / kDRegSizeInBits;
36897a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    VIXL_ASSERT(lane < lane_count);
36997a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    return DRegister(GetCode() * lane_count + lane);
37097a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard  }
37188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegister GetLowDRegister() const { return DRegister(GetCode() * 2); }
37288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegister GetHighDRegister() const { return DRegister(1 + GetCode() * 2); }
37397a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard  SRegister GetSLane(uint32_t lane) const {
37497a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    uint32_t lane_count = kQRegSizeInBits / kSRegSizeInBits;
37597a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    VIXL_ASSERT(lane < lane_count);
37697a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    VIXL_ASSERT(GetCode() * lane_count < kNumberOfSRegisters);
37797a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    return SRegister(GetCode() * lane_count + lane);
37897a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard  }
37988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t Encode(int single_bit_field, int four_bit_field_lowest_bit) {
38088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    // Encode "code * 2".
38188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(single_bit_field >= 3);
38288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return ((GetCode() & 0x8) << (single_bit_field - 3)) |
38388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           ((GetCode() & 0x7) << (four_bit_field_lowest_bit + 1));
38488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
38588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
38688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
38788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline unsigned ExtractQRegister(uint32_t instr,
38888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                 int single_bit_field,
38988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                 int four_bit_field_lowest_bit) {
39088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(single_bit_field >= 3);
39188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return ((instr >> (single_bit_field - 3)) & 0x8) |
39288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois         ((instr >> (four_bit_field_lowest_bit + 1)) & 0x7);
39388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
39488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
39588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, const QRegister reg) {
39688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << "q" << reg.GetCode();
39788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
39888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
39988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format off
4001107e04f82d4809214ff6592b3727298dee1fe45Alexandre Rames#define AARCH32_REGISTER_CODE_LIST(R)                                          \
40188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                               \
40288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)
40388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format on
40488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define DEFINE_REGISTER(N) const Register r##N(N);
4051107e04f82d4809214ff6592b3727298dee1fe45Alexandre RamesAARCH32_REGISTER_CODE_LIST(DEFINE_REGISTER)
40688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#undef DEFINE_REGISTER
4071107e04f82d4809214ff6592b3727298dee1fe45Alexandre Rames#undef AARCH32_REGISTER_CODE_LIST
40888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
40988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum RegNum { kIPRegNum = 12, kSPRegNum = 13, kLRRegNum = 14, kPCRegNum = 15 };
41088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
41188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst Register ip(kIPRegNum);
41288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst Register sp(kSPRegNum);
41388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst Register pc(kPCRegNum);
41488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst Register lr(kLRRegNum);
41588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst Register NoReg;
41688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst VRegister NoVReg;
41788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
41888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format off
41988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define SREGISTER_CODE_LIST(R)                                                 \
42088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                               \
42188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)                              \
42288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)                              \
42388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
42488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format on
42588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define DEFINE_REGISTER(N) const SRegister s##N(N);
42688c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisSREGISTER_CODE_LIST(DEFINE_REGISTER)
42788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#undef DEFINE_REGISTER
42888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#undef SREGISTER_CODE_LIST
42988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst SRegister NoSReg;
43088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
43188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format off
43288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define DREGISTER_CODE_LIST(R)                                                 \
43388c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisR(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                                 \
43488c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisR(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)                                \
43588c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisR(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)                                \
43688c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisR(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
43788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format on
43888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define DEFINE_REGISTER(N) const DRegister d##N(N);
43988c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisDREGISTER_CODE_LIST(DEFINE_REGISTER)
44088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#undef DEFINE_REGISTER
44188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#undef DREGISTER_CODE_LIST
44288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst DRegister NoDReg;
44388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
44488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format off
44588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define QREGISTER_CODE_LIST(R)                                                 \
44688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                               \
44788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)
44888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format on
44988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define DEFINE_REGISTER(N) const QRegister q##N(N);
45088c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisQREGISTER_CODE_LIST(DEFINE_REGISTER)
45188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#undef DEFINE_REGISTER
45288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#undef QREGISTER_CODE_LIST
45388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst QRegister NoQReg;
45488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
45588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass RegisterList {
45688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
45788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegisterList() : list_(0) {}
45860241a544be0ebf48347789bf0ec268414364627Vincent Belliard  RegisterList(Register reg)  // NOLINT(runtime/explicit)
45960241a544be0ebf48347789bf0ec268414364627Vincent Belliard      : list_(RegisterToList(reg)) {}
46088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegisterList(Register reg1, Register reg2)
46188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : list_(RegisterToList(reg1) | RegisterToList(reg2)) {}
46288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegisterList(Register reg1, Register reg2, Register reg3)
46388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : list_(RegisterToList(reg1) | RegisterToList(reg2) |
46488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              RegisterToList(reg3)) {}
46588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegisterList(Register reg1, Register reg2, Register reg3, Register reg4)
46688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : list_(RegisterToList(reg1) | RegisterToList(reg2) |
46788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              RegisterToList(reg3) | RegisterToList(reg4)) {}
46888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit RegisterList(uint32_t list) : list_(list) {}
46988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetList() const { return list_; }
47088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void SetList(uint32_t list) { list_ = list; }
47188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Includes(const Register& reg) const {
47288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (list_ & RegisterToList(reg)) != 0;
47388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
47488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Combine(const RegisterList& other) { list_ |= other.GetList(); }
47588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Combine(const Register& reg) { list_ |= RegisterToList(reg); }
47688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Remove(const RegisterList& other) { list_ &= ~other.GetList(); }
47788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Remove(const Register& reg) { list_ &= ~RegisterToList(reg); }
47888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Overlaps(const RegisterList& other) const {
47988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (list_ & other.list_) != 0;
48088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
48188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsR0toR7orPC() const {
48288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    // True if all the registers from the list are not from r8-r14.
48388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (list_ & 0x7f00) == 0;
48488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
48588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsR0toR7orLR() const {
48688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    // True if all the registers from the list are not from r8-r13 nor from r15.
48788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (list_ & 0xbf00) == 0;
48888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
48988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register GetFirstAvailableRegister() const;
49088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsEmpty() const { return list_ == 0; }
49188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static RegisterList Union(const RegisterList& list_1,
49288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                            const RegisterList& list_2) {
49388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return RegisterList(list_1.list_ | list_2.list_);
49488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
49588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static RegisterList Union(const RegisterList& list_1,
49688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                            const RegisterList& list_2,
49788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                            const RegisterList& list_3) {
49888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Union(list_1, Union(list_2, list_3));
49988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
50088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static RegisterList Union(const RegisterList& list_1,
50188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                            const RegisterList& list_2,
50288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                            const RegisterList& list_3,
50388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                            const RegisterList& list_4) {
50488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Union(Union(list_1, list_2), Union(list_3, list_4));
50588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
50688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static RegisterList Intersection(const RegisterList& list_1,
50788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                   const RegisterList& list_2) {
50888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return RegisterList(list_1.list_ & list_2.list_);
50988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
51088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static RegisterList Intersection(const RegisterList& list_1,
51188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                   const RegisterList& list_2,
51288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                   const RegisterList& list_3) {
51388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Intersection(list_1, Intersection(list_2, list_3));
51488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
51588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static RegisterList Intersection(const RegisterList& list_1,
51688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                   const RegisterList& list_2,
51788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                   const RegisterList& list_3,
51888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                   const RegisterList& list_4) {
51988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Intersection(Intersection(list_1, list_2),
52088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                        Intersection(list_3, list_4));
52188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
52288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
52388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
52488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static uint32_t RegisterToList(Register reg) {
52588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (reg.GetType() == CPURegister::kNoRegister) {
52688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      return 0;
52788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    } else {
52888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      return UINT32_C(1) << reg.GetCode();
52988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
53088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
53188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
53288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Bitfield representation of all registers in the list
53388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // (1 for r0, 2 for r1, 4 for r2, ...).
53488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t list_;
53588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
53688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
53788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline uint32_t GetRegisterListEncoding(const RegisterList& registers,
53888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                        int first,
53988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                        int count) {
54088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return (registers.GetList() >> first) & ((1 << count) - 1);
54188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
54288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
54388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, RegisterList registers);
54488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
54588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass VRegisterList {
54688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
54788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VRegisterList() : list_(0) {}
54888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit VRegisterList(VRegister reg) : list_(RegisterToList(reg)) {}
54988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VRegisterList(VRegister reg1, VRegister reg2)
55088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : list_(RegisterToList(reg1) | RegisterToList(reg2)) {}
55188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VRegisterList(VRegister reg1, VRegister reg2, VRegister reg3)
55288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : list_(RegisterToList(reg1) | RegisterToList(reg2) |
55388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              RegisterToList(reg3)) {}
55488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VRegisterList(VRegister reg1, VRegister reg2, VRegister reg3, VRegister reg4)
55588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : list_(RegisterToList(reg1) | RegisterToList(reg2) |
55688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              RegisterToList(reg3) | RegisterToList(reg4)) {}
55788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit VRegisterList(uint64_t list) : list_(list) {}
55888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint64_t GetList() const { return list_; }
55988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void SetList(uint64_t list) { list_ = list; }
560e6c6319611916b73b227075c7a7c2f76bec50745Jacob Bramley  // Because differently-sized V registers overlap with one another, there is no
561e6c6319611916b73b227075c7a7c2f76bec50745Jacob Bramley  // way to implement a single 'Includes' function in a way that is unsurprising
562e6c6319611916b73b227075c7a7c2f76bec50745Jacob Bramley  // for all existing uses.
563e6c6319611916b73b227075c7a7c2f76bec50745Jacob Bramley  bool IncludesAllOf(const VRegister& reg) const {
564e6c6319611916b73b227075c7a7c2f76bec50745Jacob Bramley    return (list_ & RegisterToList(reg)) == RegisterToList(reg);
565e6c6319611916b73b227075c7a7c2f76bec50745Jacob Bramley  }
566e6c6319611916b73b227075c7a7c2f76bec50745Jacob Bramley  bool IncludesAliasOf(const VRegister& reg) const {
56788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (list_ & RegisterToList(reg)) != 0;
56888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
56988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Combine(const VRegisterList& other) { list_ |= other.GetList(); }
57088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Combine(const VRegister& reg) { list_ |= RegisterToList(reg); }
57188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Remove(const VRegisterList& other) { list_ &= ~other.GetList(); }
57288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Remove(const VRegister& reg) { list_ &= ~RegisterToList(reg); }
57388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Overlaps(const VRegisterList& other) const {
57488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (list_ & other.list_) != 0;
57588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
57688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  QRegister GetFirstAvailableQRegister() const;
57788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegister GetFirstAvailableDRegister() const;
57888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SRegister GetFirstAvailableSRegister() const;
57988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsEmpty() const { return list_ == 0; }
58088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static VRegisterList Union(const VRegisterList& list_1,
58188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                             const VRegisterList& list_2) {
58288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return VRegisterList(list_1.list_ | list_2.list_);
58388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
58488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static VRegisterList Union(const VRegisterList& list_1,
58588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                             const VRegisterList& list_2,
58688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                             const VRegisterList& list_3) {
58788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Union(list_1, Union(list_2, list_3));
58888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
58988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static VRegisterList Union(const VRegisterList& list_1,
59088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                             const VRegisterList& list_2,
59188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                             const VRegisterList& list_3,
59288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                             const VRegisterList& list_4) {
59388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Union(Union(list_1, list_2), Union(list_3, list_4));
59488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
59588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static VRegisterList Intersection(const VRegisterList& list_1,
59688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                    const VRegisterList& list_2) {
59788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return VRegisterList(list_1.list_ & list_2.list_);
59888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
59988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static VRegisterList Intersection(const VRegisterList& list_1,
60088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                    const VRegisterList& list_2,
60188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                    const VRegisterList& list_3) {
60288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Intersection(list_1, Intersection(list_2, list_3));
60388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
60488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static VRegisterList Intersection(const VRegisterList& list_1,
60588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                    const VRegisterList& list_2,
60688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                    const VRegisterList& list_3,
60788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                    const VRegisterList& list_4) {
60888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Intersection(Intersection(list_1, list_2),
60988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                        Intersection(list_3, list_4));
61088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
61188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
61288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
61388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static uint64_t RegisterToList(VRegister reg) {
61488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (reg.GetType() == CPURegister::kNoRegister) {
61588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      return 0;
61688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    } else {
61788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      switch (reg.GetSizeInBits()) {
61888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        case kQRegSizeInBits:
61988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          return UINT64_C(0xf) << (reg.GetCode() * 4);
62088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        case kDRegSizeInBits:
62188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          return UINT64_C(0x3) << (reg.GetCode() * 2);
62288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        case kSRegSizeInBits:
62388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          return UINT64_C(0x1) << reg.GetCode();
62488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        default:
62588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          VIXL_UNREACHABLE();
62688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          return 0;
62788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      }
62888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
62988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
63088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
63188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Bitfield representation of all registers in the list.
63288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // (0x3 for d0, 0xc0 for d1, 0x30 for d2, ...). We have one, two or four bits
63388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // per register according to their size. This way we can make sure that we
634e6c6319611916b73b227075c7a7c2f76bec50745Jacob Bramley  // account for overlapping registers.
635e6c6319611916b73b227075c7a7c2f76bec50745Jacob Bramley  // A register is wholly included in this list only if all of its bits are set.
636e6c6319611916b73b227075c7a7c2f76bec50745Jacob Bramley  // A register is aliased by the list if at least one of its bits are set.
637e6c6319611916b73b227075c7a7c2f76bec50745Jacob Bramley  // The IncludesAllOf and IncludesAliasOf helpers are provided to make this
638e6c6319611916b73b227075c7a7c2f76bec50745Jacob Bramley  // distinction clear.
63988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint64_t list_;
64088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
64188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
64288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass SRegisterList {
64371bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  SRegister first_;
64471bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  int length_;
64588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
64688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
64771bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  explicit SRegisterList(SRegister reg) : first_(reg.GetCode()), length_(1) {}
64871bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  SRegisterList(SRegister first, int length)
64971bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois      : first_(first.GetCode()), length_(length) {
65071bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois    VIXL_ASSERT(length >= 0);
65188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
65229f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley  SRegister GetSRegister(int n) const {
65329f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    VIXL_ASSERT(n >= 0);
65429f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    VIXL_ASSERT(n < length_);
65529f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    return SRegister((first_.GetCode() + n) % kNumberOfSRegisters);
65671bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  }
65729f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley  const SRegister& GetFirstSRegister() const { return first_; }
65829f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley  SRegister GetLastSRegister() const { return GetSRegister(length_ - 1); }
65971bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  int GetLength() const { return length_; }
66088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
66188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
66288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, SRegisterList registers);
66388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
66488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass DRegisterList {
66571bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  DRegister first_;
66671bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  int length_;
66788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
66888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
66971bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  explicit DRegisterList(DRegister reg) : first_(reg.GetCode()), length_(1) {}
67071bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  DRegisterList(DRegister first, int length)
67171bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois      : first_(first.GetCode()), length_(length) {
67271bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois    VIXL_ASSERT(length >= 0);
67388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
67429f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley  DRegister GetDRegister(int n) const {
67529f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    VIXL_ASSERT(n >= 0);
67629f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    VIXL_ASSERT(n < length_);
67729f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    return DRegister((first_.GetCode() + n) % kMaxNumberOfDRegisters);
67871bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  }
67929f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley  const DRegister& GetFirstDRegister() const { return first_; }
68029f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley  DRegister GetLastDRegister() const { return GetDRegister(length_ - 1); }
68171bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  int GetLength() const { return length_; }
68288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
68388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
68488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, DRegisterList registers);
68588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
68688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum SpacingType { kSingle, kDouble };
68788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
68888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum TransferType { kMultipleLanes, kOneLane, kAllLanes };
68988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
69088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass NeonRegisterList {
69129f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley  DRegister first_;
69288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SpacingType spacing_;
69388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  TransferType type_;
69488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int lane_;
69529f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley  int length_;
69688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
69788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
69888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NeonRegisterList(DRegister reg, TransferType type)
69988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : first_(reg.GetCode()),
70088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        spacing_(kSingle),
70188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        type_(type),
70229f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley        lane_(-1),
70329f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley        length_(1) {
70488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(type_ != kOneLane);
70588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
70688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NeonRegisterList(DRegister reg, int lane)
70788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : first_(reg.GetCode()),
70888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        spacing_(kSingle),
70988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        type_(kOneLane),
71029f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley        lane_(lane),
71129f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley        length_(1) {
71288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT((lane_ >= 0) && (lane_ < 4));
71388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
71488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NeonRegisterList(DRegister first,
71588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   DRegister last,
71688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   SpacingType spacing,
71788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   TransferType type)
71829f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley      : first_(first.GetCode()), spacing_(spacing), type_(type), lane_(-1) {
71929f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    VIXL_ASSERT(type != kOneLane);
72029f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    VIXL_ASSERT(first.GetCode() <= last.GetCode());
72129f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley
72229f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    int range = last.GetCode() - first.GetCode();
72329f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    VIXL_ASSERT(IsSingleSpaced() || IsMultiple(range, 2));
72429f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    length_ = (IsDoubleSpaced() ? (range / 2) : range) + 1;
72529f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley
72629f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    VIXL_ASSERT(length_ <= 4);
72788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
72888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NeonRegisterList(DRegister first,
72988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   DRegister last,
73088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   SpacingType spacing,
73188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   int lane)
73288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : first_(first.GetCode()),
73388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        spacing_(spacing),
73488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        type_(kOneLane),
73588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        lane_(lane) {
73629f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    VIXL_ASSERT((lane >= 0) && (lane < 4));
73729f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    VIXL_ASSERT(first.GetCode() <= last.GetCode());
73829f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley
73929f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    int range = last.GetCode() - first.GetCode();
74029f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    VIXL_ASSERT(IsSingleSpaced() || IsMultiple(range, 2));
74129f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    length_ = (IsDoubleSpaced() ? (range / 2) : range) + 1;
74229f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley
74329f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    VIXL_ASSERT(length_ <= 4);
74488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
74529f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley  DRegister GetDRegister(int n) const {
74629f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    VIXL_ASSERT(n >= 0);
74729f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    VIXL_ASSERT(n < length_);
74829f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    unsigned code = first_.GetCode() + (IsDoubleSpaced() ? (2 * n) : n);
74929f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    VIXL_ASSERT(code < kMaxNumberOfDRegisters);
75029f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley    return DRegister(code);
75188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
75229f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley  const DRegister& GetFirstDRegister() const { return first_; }
75329f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley  DRegister GetLastDRegister() const { return GetDRegister(length_ - 1); }
75429f71f91fc1282d12fd2d5eb87eec8cf0147f043Jacob Bramley  int GetLength() const { return length_; }
75588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsSingleSpaced() const { return spacing_ == kSingle; }
75688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsDoubleSpaced() const { return spacing_ == kDouble; }
75788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsTransferAllLanes() const { return type_ == kAllLanes; }
75888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsTransferOneLane() const { return type_ == kOneLane; }
75988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsTransferMultipleLanes() const { return type_ == kMultipleLanes; }
76088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int GetTransferLane() const { return lane_; }
76188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
76288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
76388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, NeonRegisterList registers);
76488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
76588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum SpecialRegisterType { APSR = 0, CPSR = 0, SPSR = 1 };
76688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
76788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass SpecialRegister {
76888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t reg_;
76988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
77088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
77188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit SpecialRegister(uint32_t reg) : reg_(reg) {}
77260241a544be0ebf48347789bf0ec268414364627Vincent Belliard  SpecialRegister(SpecialRegisterType reg)  // NOLINT(runtime/explicit)
77360241a544be0ebf48347789bf0ec268414364627Vincent Belliard      : reg_(reg) {}
77488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetReg() const { return reg_; }
77588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
77688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(SpecialRegister value) const { return reg_ == value.reg_; }
77788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(uint32_t value) const { return reg_ == value; }
77888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNot(uint32_t value) const { return reg_ != value; }
77988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
78088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
78188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, SpecialRegister reg) {
78288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << reg.GetName();
78388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
78488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
78588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum BankedRegisterType {
78688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R8_usr = 0x00,
78788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R9_usr = 0x01,
78888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R10_usr = 0x02,
78988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R11_usr = 0x03,
79088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R12_usr = 0x04,
79188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_usr = 0x05,
79288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LR_usr = 0x06,
79388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R8_fiq = 0x08,
79488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R9_fiq = 0x09,
79588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R10_fiq = 0x0a,
79688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R11_fiq = 0x0b,
79788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R12_fiq = 0x0c,
79888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_fiq = 0x0d,
79988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LR_fiq = 0x0e,
80088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LR_irq = 0x10,
80188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_irq = 0x11,
80288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LR_svc = 0x12,
80388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_svc = 0x13,
80488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LR_abt = 0x14,
80588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_abt = 0x15,
80688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LR_und = 0x16,
80788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_und = 0x17,
80888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LR_mon = 0x1c,
80988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_mon = 0x1d,
81088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ELR_hyp = 0x1e,
81188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_hyp = 0x1f,
81288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fiq = 0x2e,
81388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_irq = 0x30,
81488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_svc = 0x32,
81588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_abt = 0x34,
81688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_und = 0x36,
81788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_mon = 0x3c,
81888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_hyp = 0x3e
81988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
82088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
82188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass BankedRegister {
82288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t reg_;
82388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
82488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
82588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit BankedRegister(unsigned reg) : reg_(reg) {}
82660241a544be0ebf48347789bf0ec268414364627Vincent Belliard  BankedRegister(BankedRegisterType reg)  // NOLINT(runtime/explicit)
82760241a544be0ebf48347789bf0ec268414364627Vincent Belliard      : reg_(reg) {}
82888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetCode() const { return reg_; }
82988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
83088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
83188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
83288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, BankedRegister reg) {
83388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << reg.GetName();
83488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
83588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
83688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum MaskedSpecialRegisterType {
83788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  APSR_nzcvq = 0x08,
83888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  APSR_g = 0x04,
83988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  APSR_nzcvqg = 0x0c,
84088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_c = 0x01,
84188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_x = 0x02,
84288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_xc = 0x03,
84388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_s = APSR_g,
84488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_sc = 0x05,
84588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_sx = 0x06,
84688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_sxc = 0x07,
84788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_f = APSR_nzcvq,
84888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_fc = 0x09,
84988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_fx = 0x0a,
85088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_fxc = 0x0b,
85188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_fs = APSR_nzcvqg,
85288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_fsc = 0x0d,
85388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_fsx = 0x0e,
85488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_fsxc = 0x0f,
85588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_c = 0x11,
85688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_x = 0x12,
85788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_xc = 0x13,
85888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_s = 0x14,
85988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_sc = 0x15,
86088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_sx = 0x16,
86188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_sxc = 0x17,
86288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_f = 0x18,
86388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fc = 0x19,
86488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fx = 0x1a,
86588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fxc = 0x1b,
86688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fs = 0x1c,
86788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fsc = 0x1d,
86888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fsx = 0x1e,
86988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fsxc = 0x1f
87088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
87188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
87288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass MaskedSpecialRegister {
87388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t reg_;
87488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
87588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
87688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit MaskedSpecialRegister(uint32_t reg) : reg_(reg) {
87788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(reg <= SPSR_fsxc);
87888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
87960241a544be0ebf48347789bf0ec268414364627Vincent Belliard  MaskedSpecialRegister(
88060241a544be0ebf48347789bf0ec268414364627Vincent Belliard      MaskedSpecialRegisterType reg)  // NOLINT(runtime/explicit)
88188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : reg_(reg) {}
88288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetReg() const { return reg_; }
88388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
88488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(MaskedSpecialRegister value) const { return reg_ == value.reg_; }
88588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(uint32_t value) const { return reg_ == value; }
88688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNot(uint32_t value) const { return reg_ != value; }
88788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
88888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
88988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, MaskedSpecialRegister reg) {
89088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << reg.GetName();
89188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
89288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
89388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum SpecialFPRegisterType {
89488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  FPSID = 0x0,
89588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  FPSCR = 0x1,
89688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MVFR2 = 0x5,
89788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MVFR1 = 0x6,
89888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MVFR0 = 0x7,
89988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  FPEXC = 0x8
90088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
90188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
90288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass SpecialFPRegister {
90388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t reg_;
90488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
90588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
90688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit SpecialFPRegister(uint32_t reg) : reg_(reg) {
90788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#ifdef VIXL_DEBUG
90888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    switch (reg) {
90988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case FPSID:
91088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case FPSCR:
91188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case MVFR2:
91288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case MVFR1:
91388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case MVFR0:
91488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case FPEXC:
91588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
91688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      default:
91788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_UNREACHABLE();
91888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
91988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#endif
92088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
92160241a544be0ebf48347789bf0ec268414364627Vincent Belliard  SpecialFPRegister(SpecialFPRegisterType reg)  // NOLINT(runtime/explicit)
92260241a544be0ebf48347789bf0ec268414364627Vincent Belliard      : reg_(reg) {}
92388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetReg() const { return reg_; }
92488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
92588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(SpecialFPRegister value) const { return reg_ == value.reg_; }
92688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(uint32_t value) const { return reg_ == value; }
92788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNot(uint32_t value) const { return reg_ != value; }
92888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
92988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
93088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, SpecialFPRegister reg) {
93188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << reg.GetName();
93288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
93388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
93488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass CRegister {
93588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t code_;
93688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
93788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
93888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit CRegister(uint32_t code) : code_(code) {
93988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(code < kNumberOfRegisters);
94088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
94188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetCode() const { return code_; }
94288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(CRegister value) const { return code_ == value.code_; }
94388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
94488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
94588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, const CRegister reg) {
94688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << "c" << reg.GetCode();
94788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
94888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
94988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format off
95088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define CREGISTER_CODE_LIST(R)                                                 \
95188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                               \
95288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)
95388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format on
95488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define DEFINE_CREGISTER(N) const CRegister c##N(N);
95588c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisCREGISTER_CODE_LIST(DEFINE_CREGISTER)
95688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
95788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum CoprocessorName { p10 = 10, p11 = 11, p14 = 14, p15 = 15 };
95888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
95988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Coprocessor {
96088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t coproc_;
96188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
96288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
96388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit Coprocessor(uint32_t coproc) : coproc_(coproc) {}
96460241a544be0ebf48347789bf0ec268414364627Vincent Belliard  Coprocessor(CoprocessorName coproc)  // NOLINT(runtime/explicit)
96588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : coproc_(static_cast<uint32_t>(coproc)) {}
96688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(Coprocessor coproc) const { return coproc_ == coproc.coproc_; }
96788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(CoprocessorName coproc) const { return coproc_ == coproc; }
96888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetCoprocessor() const { return coproc_; }
96988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
97088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
97188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, Coprocessor coproc) {
97288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << "p" << coproc.GetCoprocessor();
97388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
97488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
97588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum ConditionType {
97688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  eq = 0,
97788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ne = 1,
97888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  cs = 2,
97988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  cc = 3,
98088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  mi = 4,
98188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  pl = 5,
98288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  vs = 6,
98388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  vc = 7,
98488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  hi = 8,
98588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ls = 9,
98688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ge = 10,
98788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  lt = 11,
98888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  gt = 12,
98988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  le = 13,
99088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  al = 14,
99188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  hs = cs,
99288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  lo = cc
99388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
99488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
99588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Condition {
99688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t condition_;
99788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const uint32_t kNever = 15;
99888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const uint32_t kMask = 0xf;
999fad350715bbb9f13ea85c84da4e6095dfee3cd15Vincent Belliard  static const uint32_t kNone = 0x10 | al;
100088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
100188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
1002fad350715bbb9f13ea85c84da4e6095dfee3cd15Vincent Belliard  static const Condition None() { return Condition(kNone); }
100388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit Condition(uint32_t condition) : condition_(condition) {
100488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(condition <= kNone);
100588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
100660241a544be0ebf48347789bf0ec268414364627Vincent Belliard  Condition(ConditionType condition)  // NOLINT(runtime/explicit)
100760241a544be0ebf48347789bf0ec268414364627Vincent Belliard      : condition_(condition) {}
100888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetCondition() const { return condition_ & kMask; }
100988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNone() const { return condition_ == kNone; }
101088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
101188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(Condition value) const { return condition_ == value.condition_; }
101288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(uint32_t value) const { return condition_ == value; }
101388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNot(uint32_t value) const { return condition_ != value; }
101488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNever() const { return condition_ == kNever; }
101588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNotNever() const { return condition_ != kNever; }
101688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Condition Negate() const {
101788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsNot(al) && IsNot(kNever));
101888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Condition(condition_ ^ 1);
101988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
102088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
102188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
102288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, Condition condition) {
102388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << condition.GetName();
102488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
102588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
102688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum SignType { plus, minus };
102788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
102888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Sign {
102988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
103088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Sign() : sign_(plus) {}
103160241a544be0ebf48347789bf0ec268414364627Vincent Belliard  Sign(SignType sign) : sign_(sign) {}  // NOLINT(runtime/explicit)
103288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const { return (IsPlus() ? "" : "-"); }
103388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsPlus() const { return sign_ == plus; }
103488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsMinus() const { return sign_ == minus; }
103588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int32_t ApplyTo(uint32_t value) { return IsPlus() ? value : -value; }
103688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
103788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
103888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SignType sign_;
103988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
104088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
104188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, Sign sign) {
104288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << sign.GetName();
104388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
104488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
104588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum ShiftType { LSL = 0x0, LSR = 0x1, ASR = 0x2, ROR = 0x3, RRX = 0x4 };
104688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
104788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Shift {
104888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
104988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Shift() : shift_(LSL) {}
105060241a544be0ebf48347789bf0ec268414364627Vincent Belliard  Shift(ShiftType shift) : shift_(shift) {}  // NOLINT(runtime/explicit)
105188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit Shift(uint32_t shift) : shift_(static_cast<ShiftType>(shift)) {}
105288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const Shift& GetShift() const { return *this; }
105388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ShiftType GetType() const { return shift_; }
105488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetValue() const { return shift_; }
105588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
105688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsLSL() const { return shift_ == LSL; }
105788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsLSR() const { return shift_ == LSR; }
105888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsASR() const { return shift_ == ASR; }
105988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsROR() const { return shift_ == ROR; }
106088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsRRX() const { return shift_ == RRX; }
106188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(Shift value) const { return shift_ == value.shift_; }
106288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNot(Shift value) const { return shift_ != value.shift_; }
106388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsValidAmount(uint32_t amount) const;
106488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const Shift NoShift;
106588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
106688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois protected:
106788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void SetType(ShiftType s) { shift_ = s; }
106888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
106988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
107088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ShiftType shift_;
107188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
107288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
107388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, Shift shift) {
107488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << shift.GetName();
107588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
107688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
107788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass ImmediateShiftOperand : public Shift {
107888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
107988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Constructor used for assembly.
108088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ImmediateShiftOperand(Shift shift, uint32_t amount)
108188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : Shift(shift), amount_(amount) {
108288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#ifdef VIXL_DEBUG
108388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    switch (shift.GetType()) {
108488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case LSL:
108588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(amount <= 31);
108688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
108788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case ROR:
108888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(amount > 0);
108988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(amount <= 31);
109088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
109188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case LSR:
109288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case ASR:
109388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(amount > 0);
109488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(amount <= 32);
109588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
109688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case RRX:
109788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(amount == 0);
109888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
109988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      default:
110088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_UNREACHABLE();
110188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
110288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
110388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#endif
110488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
110588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Constructor used for disassembly.
110688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ImmediateShiftOperand(int shift, int amount);
110788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetAmount() const { return amount_; }
110888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(const ImmediateShiftOperand& rhs) const {
110988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return amount_ == (rhs.amount_) && Shift::Is(*this);
111088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
111188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
111288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
111388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t amount_;
111488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
111588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
111688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os,
111788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                ImmediateShiftOperand const& shift_operand) {
111888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (shift_operand.IsLSL() && shift_operand.GetAmount() == 0) return os;
111988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (shift_operand.IsRRX()) return os << ", rrx";
112088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << ", " << shift_operand.GetName() << " #"
112188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois            << shift_operand.GetAmount();
112288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
112388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
112488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass RegisterShiftOperand : public Shift {
112588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
112688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegisterShiftOperand(ShiftType shift, Register shift_register)
112788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : Shift(shift), shift_register_(shift_register) {
112888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(!IsRRX() && shift_register_.IsValid());
112988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
113088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const Register GetShiftRegister() const { return shift_register_; }
113188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(const RegisterShiftOperand& rhs) const {
113288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return shift_register_.Is(rhs.shift_register_) && Shift::Is(*this);
113388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
113488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
113588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
113688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register shift_register_;
113788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
113888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
113988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& s,
114088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                const RegisterShiftOperand& shift_operand) {
114188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return s << shift_operand.GetName() << " "
114288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           << shift_operand.GetShiftRegister();
114388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
114488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
114588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum EncodingSizeType { Best, Narrow, Wide };
114688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
114788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass EncodingSize {
114888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t size_;
114988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
115088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
115188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit EncodingSize(uint32_t size) : size_(size) {}
115260241a544be0ebf48347789bf0ec268414364627Vincent Belliard  EncodingSize(EncodingSizeType size)  // NOLINT(runtime/explicit)
115360241a544be0ebf48347789bf0ec268414364627Vincent Belliard      : size_(size) {}
115488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetSize() const { return size_; }
115588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
115688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsBest() const { return size_ == Best; }
115788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNarrow() const { return size_ == Narrow; }
115888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsWide() const { return size_ == Wide; }
115988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
116088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
116188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, EncodingSize size) {
116288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << size.GetName();
116388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
116488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
116588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum WriteBackValue { NO_WRITE_BACK, WRITE_BACK };
116688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
116788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass WriteBack {
116888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  WriteBackValue value_;
116988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
117088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
117160241a544be0ebf48347789bf0ec268414364627Vincent Belliard  WriteBack(WriteBackValue value)  // NOLINT(runtime/explicit)
117260241a544be0ebf48347789bf0ec268414364627Vincent Belliard      : value_(value) {}
117388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit WriteBack(int value)
117488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : value_((value == 0) ? NO_WRITE_BACK : WRITE_BACK) {}
117588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetWriteBackUint32() const { return (value_ == WRITE_BACK) ? 1 : 0; }
117688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool DoesWriteBack() const { return value_ == WRITE_BACK; }
117788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
117888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
117988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, WriteBack write_back) {
118088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (write_back.DoesWriteBack()) return os << "!";
118188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os;
118288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
118388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
118488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass EncodingValue {
118588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool valid_;
118688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t encoding_value_;
118788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
118888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
118988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  EncodingValue() {
119088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    valid_ = false;
119188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    encoding_value_ = 0;
119288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
119388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsValid() const { return valid_; }
119488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetEncodingValue() const { return encoding_value_; }
119588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void SetEncodingValue(uint32_t encoding_value) {
119688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    valid_ = true;
119788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    encoding_value_ = encoding_value;
119888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
119988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
120088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
120188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass EncodingValueAndImmediate : public EncodingValue {
120288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t encoded_immediate_;
120388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
120488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
120588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  EncodingValueAndImmediate() { encoded_immediate_ = 0; }
120688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetEncodedImmediate() const { return encoded_immediate_; }
120788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void SetEncodedImmediate(uint32_t encoded_immediate) {
120888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    encoded_immediate_ = encoded_immediate;
120988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
121088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
121188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
121288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass ImmediateT32 : public EncodingValue {
121388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
121488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit ImmediateT32(uint32_t imm);
121588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static bool IsImmediateT32(uint32_t imm);
121688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static uint32_t Decode(uint32_t value);
121788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
121888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
121988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass ImmediateA32 : public EncodingValue {
122088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
122188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit ImmediateA32(uint32_t imm);
122288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static bool IsImmediateA32(uint32_t imm);
122388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static uint32_t Decode(uint32_t value);
122488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
122588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
122688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// Return the encoding value of a shift type.
122788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisuint32_t TypeEncodingValue(Shift shift);
122888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// Return the encoding value for a shift amount depending on the shift type.
122988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisuint32_t AmountEncodingValue(Shift shift, uint32_t amount);
123088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
123188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum MemoryBarrierType {
123288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  OSHLD = 0x1,
123388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  OSHST = 0x2,
123488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  OSH = 0x3,
123588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NSHLD = 0x5,
123688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NSHST = 0x6,
123788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NSH = 0x7,
123888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ISHLD = 0x9,
123988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ISHST = 0xa,
124088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ISH = 0xb,
124188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LD = 0xd,
124288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ST = 0xe,
124388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SY = 0xf
124488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
124588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
124688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass MemoryBarrier {
124788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MemoryBarrierType type_;
124888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
124988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
125060241a544be0ebf48347789bf0ec268414364627Vincent Belliard  MemoryBarrier(MemoryBarrierType type)  // NOLINT(runtime/explicit)
125160241a544be0ebf48347789bf0ec268414364627Vincent Belliard      : type_(type) {}
125260241a544be0ebf48347789bf0ec268414364627Vincent Belliard  MemoryBarrier(uint32_t type)  // NOLINT(runtime/explicit)
125388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : type_(static_cast<MemoryBarrierType>(type)) {
125488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT((type & 0x3) != 0);
125588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
125688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MemoryBarrierType GetType() const { return type_; }
125788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
125888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
125988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
126088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, MemoryBarrier option) {
126188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << option.GetName();
126288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
126388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
126488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum InterruptFlagsType {
126588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  F = 0x1,
126688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  I = 0x2,
126788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  IF = 0x3,
126888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  A = 0x4,
126988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  AF = 0x5,
127088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  AI = 0x6,
127188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  AIF = 0x7
127288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
127388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
127488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass InterruptFlags {
127588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  InterruptFlagsType type_;
127688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
127788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
127860241a544be0ebf48347789bf0ec268414364627Vincent Belliard  InterruptFlags(InterruptFlagsType type)  // NOLINT(runtime/explicit)
127960241a544be0ebf48347789bf0ec268414364627Vincent Belliard      : type_(type) {}
128060241a544be0ebf48347789bf0ec268414364627Vincent Belliard  InterruptFlags(uint32_t type)  // NOLINT(runtime/explicit)
128188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : type_(static_cast<InterruptFlagsType>(type)) {
128288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(type <= 7);
128388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
128488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  InterruptFlagsType GetType() const { return type_; }
128588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
128688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
128788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
128888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, InterruptFlags option) {
128988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << option.GetName();
129088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
129188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
129288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum EndiannessType { LE = 0, BE = 1 };
129388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
129488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Endianness {
129588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  EndiannessType type_;
129688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
129788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
129860241a544be0ebf48347789bf0ec268414364627Vincent Belliard  Endianness(EndiannessType type) : type_(type) {}  // NOLINT(runtime/explicit)
129960241a544be0ebf48347789bf0ec268414364627Vincent Belliard  Endianness(uint32_t type)                         // NOLINT(runtime/explicit)
130088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : type_(static_cast<EndiannessType>(type)) {
130188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(type <= 1);
130288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
130388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  EndiannessType GetType() const { return type_; }
130488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
130588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
130688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
130788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, Endianness endian_specifier) {
130888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << endian_specifier.GetName();
130988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
131088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
131188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum AlignmentType {
131288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  k16BitAlign = 0,
131388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  k32BitAlign = 1,
131488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  k64BitAlign = 2,
131588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  k128BitAlign = 3,
131688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  k256BitAlign = 4,
131788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kNoAlignment = 5,
131888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kBadAlignment = 6
131988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
132088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
132188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Alignment {
132288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  AlignmentType align_;
132388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
132488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
132588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Alignment(AlignmentType align)  // NOLINT(runtime/explicit)
132688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : align_(align) {}
132788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Alignment(uint32_t align)  // NOLINT(runtime/explicit)
132888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : align_(static_cast<AlignmentType>(align)) {
132988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(align <= static_cast<uint32_t>(k256BitAlign));
133088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
133188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  AlignmentType GetType() const { return align_; }
133288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(AlignmentType type) { return align_ == type; }
133388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
133488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
133588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, Alignment align) {
133688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (align.GetType() == kBadAlignment) return os << " :??";
133788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (align.GetType() == kNoAlignment) return os;
133888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << " :" << (0x10 << static_cast<uint32_t>(align.GetType()));
133988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
134088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
134188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass RawLiteral : public Label {
134288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
134351d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  enum PlacementPolicy { kPlacedWhenUsed, kManuallyPlaced };
134451d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard
134588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  enum DeletionPolicy {
134688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    kDeletedOnPlacementByPool,
134788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    kDeletedOnPoolDestruction,
134888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    kManuallyDeleted
134988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  };
135088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
135188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
135288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RawLiteral(const void* addr,
135388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             size_t size,
135451d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard             PlacementPolicy placement_policy = kPlacedWhenUsed,
135588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             DeletionPolicy deletion_policy = kManuallyDeleted)
135688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : addr_(addr),
135788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        size_(size),
135888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        position_(kMaxOffset),
135951d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard        manually_placed_(placement_policy == kManuallyPlaced),
136051d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard        deletion_policy_(deletion_policy) {}
136151d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  RawLiteral(const void* addr, size_t size, DeletionPolicy deletion_policy)
136251d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard      : addr_(addr),
136351d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard        size_(size),
136451d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard        position_(kMaxOffset),
136551d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard        manually_placed_(false),
136688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        deletion_policy_(deletion_policy) {}
136788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ~RawLiteral() {}
136851d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  const void* GetDataAddress() const { return addr_; }
136988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  size_t GetSize() const { return size_; }
137088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  size_t GetAlignedSize() const { return (size_ + 3) & ~0x3; }
137188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
137288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Offset GetPositionInPool() const { return position_; }
137388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void SetPositionInPool(Offset position_in_pool) {
137488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    // Assumed that the literal has not already been added to
137588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    // the pool.
137688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(position_ == Label::kMaxOffset);
137788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    position_ = position_in_pool;
137888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
137988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
138051d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  bool IsManuallyPlaced() const { return manually_placed_; }
138151d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  DeletionPolicy GetDeletionPolicy() const { return deletion_policy_; }
138251d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard
138388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
138488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Data address before it's moved into the code buffer.
138588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const void* const addr_;
138688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Data size before it's moved into the code buffer.
138788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const size_t size_;
138888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Position in the pool, if not in a pool: Label::kMaxOffset.
138988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Offset position_;
139051d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  // When this flag is true, the label will be placed manually.
139151d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  bool manually_placed_;
139288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // When is the literal to be removed from the memory
139388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Can be delete'd when:
139488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //   moved into the code buffer: kDeletedOnPlacementByPool
139588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //   the pool is delete'd: kDeletedOnPoolDestruction
139688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //   or left to the application: kManuallyDeleted.
139788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DeletionPolicy deletion_policy_;
139888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
139988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
140088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloistemplate <typename T>
140188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Literal : public RawLiteral {
140288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
140388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit Literal(const T& value,
140451d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard                   PlacementPolicy placement_policy = kPlacedWhenUsed,
140588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   DeletionPolicy deletion_policy = kManuallyDeleted)
140651d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard      : RawLiteral(&value_, sizeof(T), placement_policy, deletion_policy),
140751d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard        value_(value) {}
140851d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  explicit Literal(const T& value, DeletionPolicy deletion_policy)
140988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : RawLiteral(&value_, sizeof(T), deletion_policy), value_(value) {}
14103e1b899f48c1328ac748b1f5fa78f417f7ec6581Vincent Belliard  void UpdateValue(const T& value, CodeBuffer* buffer) {
14113e1b899f48c1328ac748b1f5fa78f417f7ec6581Vincent Belliard    value_ = value;
14123e1b899f48c1328ac748b1f5fa78f417f7ec6581Vincent Belliard    if (IsBound()) {
14133e1b899f48c1328ac748b1f5fa78f417f7ec6581Vincent Belliard      buffer->UpdateData(GetLocation(), GetDataAddress(), GetSize());
14143e1b899f48c1328ac748b1f5fa78f417f7ec6581Vincent Belliard    }
14153e1b899f48c1328ac748b1f5fa78f417f7ec6581Vincent Belliard  }
141688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
141788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
141888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  T value_;
141988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
142088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
142125e3987b3b684df88edc8069d60b483b95587be5Pierre Langloisclass StringLiteral : public RawLiteral {
142288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
142325e3987b3b684df88edc8069d60b483b95587be5Pierre Langlois  explicit StringLiteral(const char* str,
142425e3987b3b684df88edc8069d60b483b95587be5Pierre Langlois                         PlacementPolicy placement_policy = kPlacedWhenUsed,
142525e3987b3b684df88edc8069d60b483b95587be5Pierre Langlois                         DeletionPolicy deletion_policy = kManuallyDeleted)
142651d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard      : RawLiteral(str, strlen(str) + 1, placement_policy, deletion_policy) {}
142725e3987b3b684df88edc8069d60b483b95587be5Pierre Langlois  explicit StringLiteral(const char* str, DeletionPolicy deletion_policy)
142888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : RawLiteral(str, strlen(str) + 1, deletion_policy) {}
142988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
143088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
143188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}  // namespace aarch32
143288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}  // namespace vixl
143388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
1434d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#endif  // VIXL_AARCH32_INSTRUCTIONS_AARCH32_H_
1435