instructions-aarch32.h revision fad350715bbb9f13ea85c84da4e6095dfee3cd15
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
15388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass RegisterOrAPSR_nzcv : public Register {
15488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
15588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit RegisterOrAPSR_nzcv(uint32_t code) : Register(code) {}
15688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
15788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
15888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os,
15988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                const RegisterOrAPSR_nzcv reg) {
16088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (reg.IsPC()) return os << "APSR_nzcv";
16188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << Register(reg.GetCode());
16288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
16388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
16488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass SRegister;
16588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass DRegister;
16688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass QRegister;
16788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
16888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass VRegister : public CPURegister {
16988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
17088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VRegister() : CPURegister(kNoRegister, 0, 0) {}
17188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VRegister(RegisterType type, uint32_t code, int size)
17288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : CPURegister(type, code, size) {}
17388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
17488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SRegister S() const;
17588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegister D() const;
17688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  QRegister Q() const;
17788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
17888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
17988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass SRegister : public VRegister {
18088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
18188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SRegister() : VRegister(kNoRegister, 0, kSRegSizeInBits) {}
18288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit SRegister(uint32_t code)
18388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : VRegister(kSRegister, code, kSRegSizeInBits) {}
18488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t Encode(int single_bit_field, int four_bit_field_lowest_bit) const {
18588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (four_bit_field_lowest_bit == 0) {
18688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      return ((GetCode() & 0x1) << single_bit_field) |
18788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             ((GetCode() & 0x1e) >> 1);
18888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
18988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return ((GetCode() & 0x1) << single_bit_field) |
19088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           ((GetCode() & 0x1e) << (four_bit_field_lowest_bit - 1));
19188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
19288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
19388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
19488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline unsigned ExtractSRegister(uint32_t instr,
19588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                 int single_bit_field,
19688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                 int four_bit_field_lowest_bit) {
19788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(single_bit_field > 0);
19888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (four_bit_field_lowest_bit == 0) {
19988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return ((instr << 1) & 0x1e) | ((instr >> single_bit_field) & 0x1);
20088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
20188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return ((instr >> (four_bit_field_lowest_bit - 1)) & 0x1e) |
20288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois         ((instr >> single_bit_field) & 0x1);
20388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
20488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
20588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, const SRegister reg) {
20688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << "s" << reg.GetCode();
20788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
20888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
20988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass DRegister : public VRegister {
21088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
21188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegister() : VRegister(kNoRegister, 0, kDRegSizeInBits) {}
21288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit DRegister(uint32_t code)
21388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : VRegister(kDRegister, code, kDRegSizeInBits) {}
21497a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard  SRegister GetLane(uint32_t lane) const {
21597a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    uint32_t lane_count = kDRegSizeInBits / kSRegSizeInBits;
21697a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    VIXL_ASSERT(lane < lane_count);
21797a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    VIXL_ASSERT(GetCode() * lane_count < kNumberOfSRegisters);
21897a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    return SRegister(GetCode() * lane_count + lane);
21997a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard  }
22088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t Encode(int single_bit_field, int four_bit_field_lowest_bit) const {
22188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(single_bit_field >= 4);
22288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return ((GetCode() & 0x10) << (single_bit_field - 4)) |
22388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           ((GetCode() & 0xf) << four_bit_field_lowest_bit);
22488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
22588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
22688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
22788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline unsigned ExtractDRegister(uint32_t instr,
22888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                 int single_bit_field,
22988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                 int four_bit_field_lowest_bit) {
23088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(single_bit_field >= 4);
23188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return ((instr >> (single_bit_field - 4)) & 0x10) |
23288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois         ((instr >> four_bit_field_lowest_bit) & 0xf);
23388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
23488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
23588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, const DRegister reg) {
23688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << "d" << reg.GetCode();
23788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
23888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
23988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum DataTypeType {
24088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeS = 0x100,
24188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeU = 0x200,
24288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeF = 0x300,
24388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeI = 0x400,
24488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeP = 0x500,
24588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeUntyped = 0x600
24688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
24788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst int kDataTypeSizeMask = 0x0ff;
24888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst int kDataTypeTypeMask = 0x100;
24988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum DataTypeValue {
25088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeValueInvalid = 0x000,
25188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kDataTypeValueNone = 0x001,  // value used when dt is ignored.
25288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  S8 = kDataTypeS | 8,
25388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  S16 = kDataTypeS | 16,
25488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  S32 = kDataTypeS | 32,
25588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  S64 = kDataTypeS | 64,
25688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  U8 = kDataTypeU | 8,
25788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  U16 = kDataTypeU | 16,
25888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  U32 = kDataTypeU | 32,
25988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  U64 = kDataTypeU | 64,
26088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  F16 = kDataTypeF | 16,
26188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  F32 = kDataTypeF | 32,
26288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  F64 = kDataTypeF | 64,
26388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  I8 = kDataTypeI | 8,
26488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  I16 = kDataTypeI | 16,
26588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  I32 = kDataTypeI | 32,
26688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  I64 = kDataTypeI | 64,
26788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  P8 = kDataTypeP | 8,
26888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  P64 = kDataTypeP | 64,
26988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Untyped8 = kDataTypeUntyped | 8,
27088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Untyped16 = kDataTypeUntyped | 16,
27188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Untyped32 = kDataTypeUntyped | 32,
27288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Untyped64 = kDataTypeUntyped | 64
27388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
27488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
27588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass DataType {
27688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DataTypeValue value_;
27788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
27888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
27988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DataType(DataTypeValue value) : value_(value) {}  // NOLINT
28088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DataType(uint32_t size)                           // NOLINT
28188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : value_(static_cast<DataTypeValue>(kDataTypeUntyped | size)) {
28288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT((size == 8) || (size == 16) || (size == 32) || (size == 64));
28388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
28488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DataTypeValue GetValue() const { return value_; }
28588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DataTypeType GetType() const {
28688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return static_cast<DataTypeType>(value_ & kDataTypeTypeMask);
28788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
28888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetSize() const { return value_ & kDataTypeSizeMask; }
28988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsSize(uint32_t size) const {
29088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (value_ & kDataTypeSizeMask) == size;
29188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
29288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
29388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(DataTypeValue value) const { return value_ == value; }
29488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(DataTypeType type) const { return GetType() == type; }
29588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNoneOr(DataTypeValue value) const {
29688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (value_ == value) || (value_ == kDataTypeValueNone);
29788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
29888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(DataTypeType type, uint32_t size) const {
29988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return value_ == static_cast<DataTypeValue>(type | size);
30088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
30188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNoneOr(DataTypeType type, uint32_t size) const {
30288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Is(type, size) || Is(kDataTypeValueNone);
30388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
30488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
30588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
30688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, DataType dt) {
30788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << dt.GetName();
30888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
30988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
31088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass DRegisterLane : public DRegister {
31188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t lane_;
31288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
31388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
31488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegisterLane(DRegister reg, uint32_t lane)
31588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : DRegister(reg.GetCode()), lane_(lane) {}
31688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegisterLane(uint32_t code, uint32_t lane) : DRegister(code), lane_(lane) {}
31788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetLane() const { return lane_; }
31888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t EncodeX(DataType dt,
31988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   int single_bit_field,
32088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   int four_bit_field_lowest_bit) const {
32188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(single_bit_field >= 4);
32288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    uint32_t value = lane_ << ((dt.GetSize() == 16) ? 3 : 4) | GetCode();
32388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return ((value & 0x10) << (single_bit_field - 4)) |
32488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           ((value & 0xf) << four_bit_field_lowest_bit);
32588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
32688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
32788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
32888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline unsigned ExtractDRegisterAndLane(uint32_t instr,
32988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                        DataType dt,
33088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                        int single_bit_field,
33188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                        int four_bit_field_lowest_bit,
33288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                        int* lane) {
33388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(single_bit_field >= 4);
33488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t value = ((instr >> (single_bit_field - 4)) & 0x10) |
33588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   ((instr >> four_bit_field_lowest_bit) & 0xf);
33688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (dt.GetSize() == 16) {
33788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    *lane = value >> 3;
33888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return value & 0x7;
33988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
34088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  *lane = value >> 4;
34188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return value & 0xf;
34288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
34388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
34488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, const DRegisterLane lane) {
34588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  os << "d" << lane.GetCode() << "[";
34688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (lane.GetLane() == static_cast<uint32_t>(-1)) return os << "??]";
34788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << lane.GetLane() << "]";
34888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
34988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
35088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass QRegister : public VRegister {
35188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
35288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  QRegister() : VRegister(kNoRegister, 0, kQRegSizeInBits) {}
35388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit QRegister(uint32_t code)
35488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : VRegister(kQRegister, code, kQRegSizeInBits) {}
35588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t Encode(int offset) { return GetCode() << offset; }
35697a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard  DRegister GetDLane(uint32_t lane) const {
35797a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    uint32_t lane_count = kQRegSizeInBits / kDRegSizeInBits;
35897a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    VIXL_ASSERT(lane < lane_count);
35997a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    return DRegister(GetCode() * lane_count + lane);
36097a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard  }
36188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegister GetLowDRegister() const { return DRegister(GetCode() * 2); }
36288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegister GetHighDRegister() const { return DRegister(1 + GetCode() * 2); }
36397a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard  SRegister GetSLane(uint32_t lane) const {
36497a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    uint32_t lane_count = kQRegSizeInBits / kSRegSizeInBits;
36597a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    VIXL_ASSERT(lane < lane_count);
36697a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    VIXL_ASSERT(GetCode() * lane_count < kNumberOfSRegisters);
36797a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard    return SRegister(GetCode() * lane_count + lane);
36897a5640aedb2d193ff27b9e7324a2412ed502a59Vincent Belliard  }
36988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t Encode(int single_bit_field, int four_bit_field_lowest_bit) {
37088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    // Encode "code * 2".
37188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(single_bit_field >= 3);
37288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return ((GetCode() & 0x8) << (single_bit_field - 3)) |
37388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           ((GetCode() & 0x7) << (four_bit_field_lowest_bit + 1));
37488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
37588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
37688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
37788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline unsigned ExtractQRegister(uint32_t instr,
37888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                 int single_bit_field,
37988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                 int four_bit_field_lowest_bit) {
38088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(single_bit_field >= 3);
38188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return ((instr >> (single_bit_field - 3)) & 0x8) |
38288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois         ((instr >> (four_bit_field_lowest_bit + 1)) & 0x7);
38388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
38488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
38588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, const QRegister reg) {
38688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << "q" << reg.GetCode();
38788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
38888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
38988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format off
3901107e04f82d4809214ff6592b3727298dee1fe45Alexandre Rames#define AARCH32_REGISTER_CODE_LIST(R)                                          \
39188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                               \
39288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)
39388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format on
39488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define DEFINE_REGISTER(N) const Register r##N(N);
3951107e04f82d4809214ff6592b3727298dee1fe45Alexandre RamesAARCH32_REGISTER_CODE_LIST(DEFINE_REGISTER)
39688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#undef DEFINE_REGISTER
3971107e04f82d4809214ff6592b3727298dee1fe45Alexandre Rames#undef AARCH32_REGISTER_CODE_LIST
39888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
39988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum RegNum { kIPRegNum = 12, kSPRegNum = 13, kLRRegNum = 14, kPCRegNum = 15 };
40088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
40188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst Register ip(kIPRegNum);
40288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst Register sp(kSPRegNum);
40388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst Register pc(kPCRegNum);
40488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst Register lr(kLRRegNum);
40588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst Register NoReg;
40688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst VRegister NoVReg;
40788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
40888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format off
40988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define SREGISTER_CODE_LIST(R)                                                 \
41088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                               \
41188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)                              \
41288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)                              \
41388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
41488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format on
41588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define DEFINE_REGISTER(N) const SRegister s##N(N);
41688c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisSREGISTER_CODE_LIST(DEFINE_REGISTER)
41788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#undef DEFINE_REGISTER
41888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#undef SREGISTER_CODE_LIST
41988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst SRegister NoSReg;
42088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
42188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format off
42288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define DREGISTER_CODE_LIST(R)                                                 \
42388c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisR(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                                 \
42488c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisR(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)                                \
42588c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisR(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)                                \
42688c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisR(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
42788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format on
42888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define DEFINE_REGISTER(N) const DRegister d##N(N);
42988c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisDREGISTER_CODE_LIST(DEFINE_REGISTER)
43088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#undef DEFINE_REGISTER
43188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#undef DREGISTER_CODE_LIST
43288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst DRegister NoDReg;
43388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
43488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format off
43588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define QREGISTER_CODE_LIST(R)                                                 \
43688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                               \
43788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)
43888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format on
43988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define DEFINE_REGISTER(N) const QRegister q##N(N);
44088c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisQREGISTER_CODE_LIST(DEFINE_REGISTER)
44188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#undef DEFINE_REGISTER
44288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#undef QREGISTER_CODE_LIST
44388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisconst QRegister NoQReg;
44488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
44588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass RegisterList {
44688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
44788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegisterList() : list_(0) {}
44888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegisterList(Register reg) : list_(RegisterToList(reg)) {}  // NOLINT
44988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegisterList(Register reg1, Register reg2)
45088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : list_(RegisterToList(reg1) | RegisterToList(reg2)) {}
45188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegisterList(Register reg1, Register reg2, Register reg3)
45288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : list_(RegisterToList(reg1) | RegisterToList(reg2) |
45388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              RegisterToList(reg3)) {}
45488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegisterList(Register reg1, Register reg2, Register reg3, Register reg4)
45588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : list_(RegisterToList(reg1) | RegisterToList(reg2) |
45688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              RegisterToList(reg3) | RegisterToList(reg4)) {}
45788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit RegisterList(uint32_t list) : list_(list) {}
45888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetList() const { return list_; }
45988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void SetList(uint32_t list) { list_ = list; }
46088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Includes(const Register& reg) const {
46188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (list_ & RegisterToList(reg)) != 0;
46288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
46388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Combine(const RegisterList& other) { list_ |= other.GetList(); }
46488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Combine(const Register& reg) { list_ |= RegisterToList(reg); }
46588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Remove(const RegisterList& other) { list_ &= ~other.GetList(); }
46688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Remove(const Register& reg) { list_ &= ~RegisterToList(reg); }
46788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Overlaps(const RegisterList& other) const {
46888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (list_ & other.list_) != 0;
46988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
47088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsR0toR7orPC() const {
47188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    // True if all the registers from the list are not from r8-r14.
47288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (list_ & 0x7f00) == 0;
47388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
47488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsR0toR7orLR() const {
47588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    // True if all the registers from the list are not from r8-r13 nor from r15.
47688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (list_ & 0xbf00) == 0;
47788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
47888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register GetFirstAvailableRegister() const;
47988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsEmpty() const { return list_ == 0; }
48088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static RegisterList Union(const RegisterList& list_1,
48188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                            const RegisterList& list_2) {
48288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return RegisterList(list_1.list_ | list_2.list_);
48388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
48488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static RegisterList Union(const RegisterList& list_1,
48588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                            const RegisterList& list_2,
48688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                            const RegisterList& list_3) {
48788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Union(list_1, Union(list_2, list_3));
48888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
48988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static RegisterList Union(const RegisterList& list_1,
49088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                            const RegisterList& list_2,
49188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                            const RegisterList& list_3,
49288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                            const RegisterList& list_4) {
49388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Union(Union(list_1, list_2), Union(list_3, list_4));
49488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
49588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static RegisterList Intersection(const RegisterList& list_1,
49688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                   const RegisterList& list_2) {
49788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return RegisterList(list_1.list_ & list_2.list_);
49888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
49988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static RegisterList Intersection(const RegisterList& list_1,
50088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                   const RegisterList& list_2,
50188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                   const RegisterList& list_3) {
50288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Intersection(list_1, Intersection(list_2, list_3));
50388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
50488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static RegisterList Intersection(const RegisterList& list_1,
50588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                   const RegisterList& list_2,
50688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                   const RegisterList& list_3,
50788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                   const RegisterList& list_4) {
50888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Intersection(Intersection(list_1, list_2),
50988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                        Intersection(list_3, list_4));
51088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
51188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
51288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
51388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static uint32_t RegisterToList(Register reg) {
51488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (reg.GetType() == CPURegister::kNoRegister) {
51588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      return 0;
51688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    } else {
51788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      return UINT32_C(1) << reg.GetCode();
51888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
51988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
52088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
52188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Bitfield representation of all registers in the list
52288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // (1 for r0, 2 for r1, 4 for r2, ...).
52388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t list_;
52488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
52588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
52688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline uint32_t GetRegisterListEncoding(const RegisterList& registers,
52788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                        int first,
52888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                        int count) {
52988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return (registers.GetList() >> first) & ((1 << count) - 1);
53088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
53188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
53288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, RegisterList registers);
53388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
53488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass VRegisterList {
53588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
53688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VRegisterList() : list_(0) {}
53788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit VRegisterList(VRegister reg) : list_(RegisterToList(reg)) {}
53888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VRegisterList(VRegister reg1, VRegister reg2)
53988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : list_(RegisterToList(reg1) | RegisterToList(reg2)) {}
54088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VRegisterList(VRegister reg1, VRegister reg2, VRegister reg3)
54188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : list_(RegisterToList(reg1) | RegisterToList(reg2) |
54288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              RegisterToList(reg3)) {}
54388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VRegisterList(VRegister reg1, VRegister reg2, VRegister reg3, VRegister reg4)
54488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : list_(RegisterToList(reg1) | RegisterToList(reg2) |
54588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              RegisterToList(reg3) | RegisterToList(reg4)) {}
54688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit VRegisterList(uint64_t list) : list_(list) {}
54788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint64_t GetList() const { return list_; }
54888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void SetList(uint64_t list) { list_ = list; }
54988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Includes(const VRegister& reg) const {
55088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (list_ & RegisterToList(reg)) != 0;
55188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
55288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Combine(const VRegisterList& other) { list_ |= other.GetList(); }
55388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Combine(const VRegister& reg) { list_ |= RegisterToList(reg); }
55488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Remove(const VRegisterList& other) { list_ &= ~other.GetList(); }
55588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void Remove(const VRegister& reg) { list_ &= ~RegisterToList(reg); }
55688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Overlaps(const VRegisterList& other) const {
55788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return (list_ & other.list_) != 0;
55888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
55988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  QRegister GetFirstAvailableQRegister() const;
56088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegister GetFirstAvailableDRegister() const;
56188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SRegister GetFirstAvailableSRegister() const;
56288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsEmpty() const { return list_ == 0; }
56388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static VRegisterList Union(const VRegisterList& list_1,
56488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                             const VRegisterList& list_2) {
56588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return VRegisterList(list_1.list_ | list_2.list_);
56688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
56788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static VRegisterList Union(const VRegisterList& list_1,
56888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                             const VRegisterList& list_2,
56988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                             const VRegisterList& list_3) {
57088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Union(list_1, Union(list_2, list_3));
57188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
57288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static VRegisterList Union(const VRegisterList& list_1,
57388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                             const VRegisterList& list_2,
57488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                             const VRegisterList& list_3,
57588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                             const VRegisterList& list_4) {
57688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Union(Union(list_1, list_2), Union(list_3, list_4));
57788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
57888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static VRegisterList Intersection(const VRegisterList& list_1,
57988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                    const VRegisterList& list_2) {
58088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return VRegisterList(list_1.list_ & list_2.list_);
58188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
58288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static VRegisterList Intersection(const VRegisterList& list_1,
58388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                    const VRegisterList& list_2,
58488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                    const VRegisterList& list_3) {
58588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Intersection(list_1, Intersection(list_2, list_3));
58688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
58788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static VRegisterList Intersection(const VRegisterList& list_1,
58888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                    const VRegisterList& list_2,
58988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                    const VRegisterList& list_3,
59088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                    const VRegisterList& list_4) {
59188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Intersection(Intersection(list_1, list_2),
59288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                        Intersection(list_3, list_4));
59388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
59488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
59588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
59688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static uint64_t RegisterToList(VRegister reg) {
59788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (reg.GetType() == CPURegister::kNoRegister) {
59888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      return 0;
59988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    } else {
60088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      switch (reg.GetSizeInBits()) {
60188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        case kQRegSizeInBits:
60288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          return UINT64_C(0xf) << (reg.GetCode() * 4);
60388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        case kDRegSizeInBits:
60488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          return UINT64_C(0x3) << (reg.GetCode() * 2);
60588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        case kSRegSizeInBits:
60688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          return UINT64_C(0x1) << reg.GetCode();
60788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        default:
60888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          VIXL_UNREACHABLE();
60988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          return 0;
61088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      }
61188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
61288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
61388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
61488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Bitfield representation of all registers in the list.
61588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // (0x3 for d0, 0xc0 for d1, 0x30 for d2, ...). We have one, two or four bits
61688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // per register according to their size. This way we can make sure that we
61788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // account for overlapping registers. A register is included in this list if
61888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // any of its bits are set.  For example, adding s3 to the list implies d1 and
61988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // q0.
62088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint64_t list_;
62188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
62288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
62388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass SRegisterList {
62471bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  SRegister first_;
62571bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  int length_;
62688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
62788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
62871bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  explicit SRegisterList(SRegister reg) : first_(reg.GetCode()), length_(1) {}
62971bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  SRegisterList(SRegister first, int length)
63071bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois      : first_(first.GetCode()), length_(length) {
63171bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois    VIXL_ASSERT(length >= 0);
63288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
63388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const SRegister& GetFirstSRegister() const { return first_; }
63471bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  const SRegister GetLastSRegister() const {
635260c6b6a014af9932f308fa53b82fb2ada3acba8Vincent Belliard    return SRegister((first_.GetCode() + length_ - 1) % kNumberOfSRegisters);
63671bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  }
63771bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  int GetLength() const { return length_; }
63888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
63988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
64088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, SRegisterList registers);
64188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
64288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass DRegisterList {
64371bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  DRegister first_;
64471bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  int length_;
64588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
64688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
64771bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  explicit DRegisterList(DRegister reg) : first_(reg.GetCode()), length_(1) {}
64871bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  DRegisterList(DRegister first, int length)
64971bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois      : first_(first.GetCode()), length_(length) {
65071bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois    VIXL_ASSERT(length >= 0);
65188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
65288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const DRegister& GetFirstDRegister() const { return first_; }
65371bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  const DRegister GetLastDRegister() const {
654260c6b6a014af9932f308fa53b82fb2ada3acba8Vincent Belliard    return DRegister((first_.GetCode() + length_ - 1) % kMaxNumberOfDRegisters);
65571bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  }
65671bca307f4e94afdbc753e02c101b042cd218b4aPierre Langlois  int GetLength() const { return length_; }
65788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
65888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
65988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, DRegisterList registers);
66088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
66188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum SpacingType { kSingle, kDouble };
66288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
66388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum TransferType { kMultipleLanes, kOneLane, kAllLanes };
66488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
66588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass NeonRegisterList {
66688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DRegister first_, last_;
66788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SpacingType spacing_;
66888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  TransferType type_;
66988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int lane_;
67088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
67188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
67288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NeonRegisterList(DRegister reg, TransferType type)
67388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : first_(reg.GetCode()),
67488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        last_(reg.GetCode()),
67588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        spacing_(kSingle),
67688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        type_(type),
67788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        lane_(-1) {
67888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(type_ != kOneLane);
67988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
68088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NeonRegisterList(DRegister reg, int lane)
68188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : first_(reg.GetCode()),
68288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        last_(reg.GetCode()),
68388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        spacing_(kSingle),
68488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        type_(kOneLane),
68588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        lane_(lane) {
68688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT((lane_ >= 0) && (lane_ < 4));
68788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
68888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NeonRegisterList(DRegister first,
68988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   DRegister last,
69088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   SpacingType spacing,
69188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   TransferType type)
69288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : first_(first.GetCode()),
69388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        last_(last.GetCode()),
69488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        spacing_(spacing),
69588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        type_(type),
69688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        lane_(-1) {
69788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(type_ != kOneLane);
69888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(first_.GetCode() <= last_.GetCode());
69988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetLength() <= 4);
70088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT((spacing_ == kSingle) ||
70188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                (((last_.GetCode() - first_.GetCode()) & 1) == 0));
70288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
70388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NeonRegisterList(DRegister first,
70488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   DRegister last,
70588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   SpacingType spacing,
70688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   int lane)
70788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : first_(first.GetCode()),
70888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        last_(last.GetCode()),
70988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        spacing_(spacing),
71088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        type_(kOneLane),
71188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        lane_(lane) {
71288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT((lane_ >= 0) && (lane_ < 4));
71388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(first_.GetCode() <= last_.GetCode());
71488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetLength() <= 4);
71588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT((spacing_ == kSingle) ||
71688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                (((last_.GetCode() - first_.GetCode()) & 1) == 0));
71788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
71888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const DRegister& GetFirstDRegister() const { return first_; }
71988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const DRegister& GetLastDRegister() const { return last_; }
72088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetLength() const {
72188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    uint32_t length =
72288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        (last_.GetCode() - first_.GetCode()) % kMaxNumberOfDRegisters;
72388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (spacing_ == kDouble) length /= 2;
72488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return 1 + length;
72588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
72688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsSingleSpaced() const { return spacing_ == kSingle; }
72788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsDoubleSpaced() const { return spacing_ == kDouble; }
72888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsTransferAllLanes() const { return type_ == kAllLanes; }
72988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsTransferOneLane() const { return type_ == kOneLane; }
73088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsTransferMultipleLanes() const { return type_ == kMultipleLanes; }
73188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int GetTransferLane() const { return lane_; }
73288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
73388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
73488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisstd::ostream& operator<<(std::ostream& os, NeonRegisterList registers);
73588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
73688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum SpecialRegisterType { APSR = 0, CPSR = 0, SPSR = 1 };
73788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
73888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass SpecialRegister {
73988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t reg_;
74088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
74188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
74288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit SpecialRegister(uint32_t reg) : reg_(reg) {}
74388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SpecialRegister(SpecialRegisterType reg) : reg_(reg) {}  // NOLINT
74488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetReg() const { return reg_; }
74588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
74688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(SpecialRegister value) const { return reg_ == value.reg_; }
74788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(uint32_t value) const { return reg_ == value; }
74888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNot(uint32_t value) const { return reg_ != value; }
74988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
75088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
75188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, SpecialRegister reg) {
75288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << reg.GetName();
75388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
75488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
75588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum BankedRegisterType {
75688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R8_usr = 0x00,
75788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R9_usr = 0x01,
75888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R10_usr = 0x02,
75988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R11_usr = 0x03,
76088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R12_usr = 0x04,
76188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_usr = 0x05,
76288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LR_usr = 0x06,
76388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R8_fiq = 0x08,
76488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R9_fiq = 0x09,
76588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R10_fiq = 0x0a,
76688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R11_fiq = 0x0b,
76788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R12_fiq = 0x0c,
76888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_fiq = 0x0d,
76988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LR_fiq = 0x0e,
77088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LR_irq = 0x10,
77188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_irq = 0x11,
77288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LR_svc = 0x12,
77388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_svc = 0x13,
77488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LR_abt = 0x14,
77588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_abt = 0x15,
77688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LR_und = 0x16,
77788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_und = 0x17,
77888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LR_mon = 0x1c,
77988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_mon = 0x1d,
78088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ELR_hyp = 0x1e,
78188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SP_hyp = 0x1f,
78288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fiq = 0x2e,
78388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_irq = 0x30,
78488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_svc = 0x32,
78588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_abt = 0x34,
78688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_und = 0x36,
78788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_mon = 0x3c,
78888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_hyp = 0x3e
78988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
79088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
79188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass BankedRegister {
79288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t reg_;
79388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
79488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
79588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit BankedRegister(unsigned reg) : reg_(reg) {}
79688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  BankedRegister(BankedRegisterType reg) : reg_(reg) {}  // NOLINT
79788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetCode() const { return reg_; }
79888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
79988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
80088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
80188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, BankedRegister reg) {
80288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << reg.GetName();
80388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
80488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
80588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum MaskedSpecialRegisterType {
80688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  APSR_nzcvq = 0x08,
80788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  APSR_g = 0x04,
80888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  APSR_nzcvqg = 0x0c,
80988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_c = 0x01,
81088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_x = 0x02,
81188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_xc = 0x03,
81288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_s = APSR_g,
81388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_sc = 0x05,
81488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_sx = 0x06,
81588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_sxc = 0x07,
81688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_f = APSR_nzcvq,
81788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_fc = 0x09,
81888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_fx = 0x0a,
81988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_fxc = 0x0b,
82088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_fs = APSR_nzcvqg,
82188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_fsc = 0x0d,
82288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_fsx = 0x0e,
82388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  CPSR_fsxc = 0x0f,
82488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_c = 0x11,
82588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_x = 0x12,
82688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_xc = 0x13,
82788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_s = 0x14,
82888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_sc = 0x15,
82988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_sx = 0x16,
83088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_sxc = 0x17,
83188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_f = 0x18,
83288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fc = 0x19,
83388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fx = 0x1a,
83488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fxc = 0x1b,
83588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fs = 0x1c,
83688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fsc = 0x1d,
83788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fsx = 0x1e,
83888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SPSR_fsxc = 0x1f
83988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
84088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
84188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass MaskedSpecialRegister {
84288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t reg_;
84388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
84488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
84588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit MaskedSpecialRegister(uint32_t reg) : reg_(reg) {
84688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(reg <= SPSR_fsxc);
84788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
84888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MaskedSpecialRegister(MaskedSpecialRegisterType reg)  // NOLINT
84988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : reg_(reg) {}
85088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetReg() const { return reg_; }
85188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
85288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(MaskedSpecialRegister value) const { return reg_ == value.reg_; }
85388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(uint32_t value) const { return reg_ == value; }
85488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNot(uint32_t value) const { return reg_ != value; }
85588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
85688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
85788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, MaskedSpecialRegister reg) {
85888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << reg.GetName();
85988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
86088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
86188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum SpecialFPRegisterType {
86288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  FPSID = 0x0,
86388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  FPSCR = 0x1,
86488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MVFR2 = 0x5,
86588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MVFR1 = 0x6,
86688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MVFR0 = 0x7,
86788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  FPEXC = 0x8
86888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
86988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
87088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass SpecialFPRegister {
87188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t reg_;
87288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
87388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
87488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit SpecialFPRegister(uint32_t reg) : reg_(reg) {
87588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#ifdef VIXL_DEBUG
87688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    switch (reg) {
87788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case FPSID:
87888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case FPSCR:
87988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case MVFR2:
88088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case MVFR1:
88188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case MVFR0:
88288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case FPEXC:
88388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
88488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      default:
88588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_UNREACHABLE();
88688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
88788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#endif
88888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
88988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SpecialFPRegister(SpecialFPRegisterType reg) : reg_(reg) {}  // NOLINT
89088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetReg() const { return reg_; }
89188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
89288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(SpecialFPRegister value) const { return reg_ == value.reg_; }
89388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(uint32_t value) const { return reg_ == value; }
89488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNot(uint32_t value) const { return reg_ != value; }
89588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
89688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
89788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, SpecialFPRegister reg) {
89888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << reg.GetName();
89988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
90088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
90188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass CRegister {
90288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t code_;
90388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
90488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
90588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit CRegister(uint32_t code) : code_(code) {
90688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(code < kNumberOfRegisters);
90788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
90888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetCode() const { return code_; }
90988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(CRegister value) const { return code_ == value.code_; }
91088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
91188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
91288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, const CRegister reg) {
91388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << "c" << reg.GetCode();
91488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
91588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
91688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format off
91788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define CREGISTER_CODE_LIST(R)                                                 \
91888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                               \
91988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)
92088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// clang-format on
92188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#define DEFINE_CREGISTER(N) const CRegister c##N(N);
92288c46b84df005638546de5e4e965bdcc31352f48Pierre LangloisCREGISTER_CODE_LIST(DEFINE_CREGISTER)
92388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
92488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum CoprocessorName { p10 = 10, p11 = 11, p14 = 14, p15 = 15 };
92588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
92688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Coprocessor {
92788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t coproc_;
92888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
92988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
93088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit Coprocessor(uint32_t coproc) : coproc_(coproc) {}
93188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Coprocessor(CoprocessorName coproc)  // NOLINT
93288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : coproc_(static_cast<uint32_t>(coproc)) {}
93388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(Coprocessor coproc) const { return coproc_ == coproc.coproc_; }
93488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(CoprocessorName coproc) const { return coproc_ == coproc; }
93588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetCoprocessor() const { return coproc_; }
93688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
93788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
93888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, Coprocessor coproc) {
93988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << "p" << coproc.GetCoprocessor();
94088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
94188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
94288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum ConditionType {
94388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  eq = 0,
94488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ne = 1,
94588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  cs = 2,
94688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  cc = 3,
94788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  mi = 4,
94888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  pl = 5,
94988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  vs = 6,
95088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  vc = 7,
95188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  hi = 8,
95288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ls = 9,
95388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ge = 10,
95488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  lt = 11,
95588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  gt = 12,
95688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  le = 13,
95788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  al = 14,
95888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  hs = cs,
95988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  lo = cc
96088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
96188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
96288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Condition {
96388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t condition_;
96488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const uint32_t kNever = 15;
96588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const uint32_t kMask = 0xf;
966fad350715bbb9f13ea85c84da4e6095dfee3cd15Vincent Belliard  static const uint32_t kNone = 0x10 | al;
96788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
96888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
969fad350715bbb9f13ea85c84da4e6095dfee3cd15Vincent Belliard  static const Condition None() { return Condition(kNone); }
97088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit Condition(uint32_t condition) : condition_(condition) {
97188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(condition <= kNone);
97288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
97388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Condition(ConditionType condition) : condition_(condition) {}  // NOLINT
97488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetCondition() const { return condition_ & kMask; }
97588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNone() const { return condition_ == kNone; }
97688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
97788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(Condition value) const { return condition_ == value.condition_; }
97888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(uint32_t value) const { return condition_ == value; }
97988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNot(uint32_t value) const { return condition_ != value; }
98088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNever() const { return condition_ == kNever; }
98188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNotNever() const { return condition_ != kNever; }
98288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Condition Negate() const {
98388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsNot(al) && IsNot(kNever));
98488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return Condition(condition_ ^ 1);
98588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
98688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
98788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
98888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, Condition condition) {
98988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << condition.GetName();
99088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
99188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
99288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum SignType { plus, minus };
99388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
99488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Sign {
99588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
99688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Sign() : sign_(plus) {}
99788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Sign(SignType sign) : sign_(sign) {}  // NOLINT
99888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const { return (IsPlus() ? "" : "-"); }
99988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsPlus() const { return sign_ == plus; }
100088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsMinus() const { return sign_ == minus; }
100188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int32_t ApplyTo(uint32_t value) { return IsPlus() ? value : -value; }
100288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
100388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
100488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SignType sign_;
100588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
100688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
100788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, Sign sign) {
100888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << sign.GetName();
100988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
101088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
101188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum ShiftType { LSL = 0x0, LSR = 0x1, ASR = 0x2, ROR = 0x3, RRX = 0x4 };
101288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
101388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Shift {
101488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
101588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Shift() : shift_(LSL) {}
101688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Shift(ShiftType shift) : shift_(shift) {}  // NOLINT
101788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit Shift(uint32_t shift) : shift_(static_cast<ShiftType>(shift)) {}
101888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const Shift& GetShift() const { return *this; }
101988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ShiftType GetType() const { return shift_; }
102088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetValue() const { return shift_; }
102188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
102288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsLSL() const { return shift_ == LSL; }
102388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsLSR() const { return shift_ == LSR; }
102488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsASR() const { return shift_ == ASR; }
102588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsROR() const { return shift_ == ROR; }
102688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsRRX() const { return shift_ == RRX; }
102788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(Shift value) const { return shift_ == value.shift_; }
102888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNot(Shift value) const { return shift_ != value.shift_; }
102988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsValidAmount(uint32_t amount) const;
103088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const Shift NoShift;
103188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
103288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois protected:
103388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void SetType(ShiftType s) { shift_ = s; }
103488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
103588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
103688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ShiftType shift_;
103788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
103888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
103988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, Shift shift) {
104088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << shift.GetName();
104188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
104288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
104388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass ImmediateShiftOperand : public Shift {
104488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
104588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Constructor used for assembly.
104688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ImmediateShiftOperand(Shift shift, uint32_t amount)
104788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : Shift(shift), amount_(amount) {
104888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#ifdef VIXL_DEBUG
104988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    switch (shift.GetType()) {
105088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case LSL:
105188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(amount <= 31);
105288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
105388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case ROR:
105488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(amount > 0);
105588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(amount <= 31);
105688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
105788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case LSR:
105888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case ASR:
105988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(amount > 0);
106088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(amount <= 32);
106188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
106288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      case RRX:
106388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_ASSERT(amount == 0);
106488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
106588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      default:
106688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        VIXL_UNREACHABLE();
106788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        break;
106888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
106988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#endif
107088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
107188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Constructor used for disassembly.
107288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ImmediateShiftOperand(int shift, int amount);
107388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetAmount() const { return amount_; }
107488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(const ImmediateShiftOperand& rhs) const {
107588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return amount_ == (rhs.amount_) && Shift::Is(*this);
107688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
107788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
107888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
107988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t amount_;
108088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
108188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
108288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os,
108388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                ImmediateShiftOperand const& shift_operand) {
108488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (shift_operand.IsLSL() && shift_operand.GetAmount() == 0) return os;
108588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (shift_operand.IsRRX()) return os << ", rrx";
108688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << ", " << shift_operand.GetName() << " #"
108788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois            << shift_operand.GetAmount();
108888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
108988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
109088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass RegisterShiftOperand : public Shift {
109188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
109288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegisterShiftOperand(ShiftType shift, Register shift_register)
109388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : Shift(shift), shift_register_(shift_register) {
109488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(!IsRRX() && shift_register_.IsValid());
109588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
109688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const Register GetShiftRegister() const { return shift_register_; }
109788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(const RegisterShiftOperand& rhs) const {
109888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return shift_register_.Is(rhs.shift_register_) && Shift::Is(*this);
109988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
110088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
110188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
110288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register shift_register_;
110388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
110488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
110588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& s,
110688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                const RegisterShiftOperand& shift_operand) {
110788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return s << shift_operand.GetName() << " "
110888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois           << shift_operand.GetShiftRegister();
110988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
111088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
111188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum EncodingSizeType { Best, Narrow, Wide };
111288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
111388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass EncodingSize {
111488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t size_;
111588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
111688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
111788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit EncodingSize(uint32_t size) : size_(size) {}
111888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  EncodingSize(EncodingSizeType size) : size_(size) {}  // NOLINT
111988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetSize() const { return size_; }
112088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
112188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsBest() const { return size_ == Best; }
112288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsNarrow() const { return size_ == Narrow; }
112388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsWide() const { return size_ == Wide; }
112488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
112588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
112688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, EncodingSize size) {
112788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << size.GetName();
112888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
112988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
113088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum WriteBackValue { NO_WRITE_BACK, WRITE_BACK };
113188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
113288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass WriteBack {
113388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  WriteBackValue value_;
113488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
113588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
113688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  WriteBack(WriteBackValue value) : value_(value) {}  // NOLINT
113788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit WriteBack(int value)
113888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : value_((value == 0) ? NO_WRITE_BACK : WRITE_BACK) {}
113988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetWriteBackUint32() const { return (value_ == WRITE_BACK) ? 1 : 0; }
114088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool DoesWriteBack() const { return value_ == WRITE_BACK; }
114188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
114288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
114388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, WriteBack write_back) {
114488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (write_back.DoesWriteBack()) return os << "!";
114588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os;
114688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
114788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
114888c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass EncodingValue {
114988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool valid_;
115088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t encoding_value_;
115188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
115288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
115388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  EncodingValue() {
115488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    valid_ = false;
115588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    encoding_value_ = 0;
115688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
115788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsValid() const { return valid_; }
115888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetEncodingValue() const { return encoding_value_; }
115988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void SetEncodingValue(uint32_t encoding_value) {
116088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    valid_ = true;
116188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    encoding_value_ = encoding_value;
116288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
116388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
116488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
116588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass EncodingValueAndImmediate : public EncodingValue {
116688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t encoded_immediate_;
116788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
116888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
116988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  EncodingValueAndImmediate() { encoded_immediate_ = 0; }
117088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t GetEncodedImmediate() const { return encoded_immediate_; }
117188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void SetEncodedImmediate(uint32_t encoded_immediate) {
117288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    encoded_immediate_ = encoded_immediate;
117388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
117488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
117588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
117688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass ImmediateT32 : public EncodingValue {
117788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
117888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit ImmediateT32(uint32_t imm);
117988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static bool IsImmediateT32(uint32_t imm);
118088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static uint32_t Decode(uint32_t value);
118188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
118288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
118388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass ImmediateA32 : public EncodingValue {
118488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
118588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit ImmediateA32(uint32_t imm);
118688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static bool IsImmediateA32(uint32_t imm);
118788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static uint32_t Decode(uint32_t value);
118888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
118988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
119088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// Return the encoding value of a shift type.
119188c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisuint32_t TypeEncodingValue(Shift shift);
119288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// Return the encoding value for a shift amount depending on the shift type.
119388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisuint32_t AmountEncodingValue(Shift shift, uint32_t amount);
119488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
119588c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum MemoryBarrierType {
119688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  OSHLD = 0x1,
119788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  OSHST = 0x2,
119888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  OSH = 0x3,
119988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NSHLD = 0x5,
120088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NSHST = 0x6,
120188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  NSH = 0x7,
120288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ISHLD = 0x9,
120388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ISHST = 0xa,
120488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ISH = 0xb,
120588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  LD = 0xd,
120688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ST = 0xe,
120788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  SY = 0xf
120888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
120988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
121088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass MemoryBarrier {
121188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MemoryBarrierType type_;
121288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
121388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
121488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MemoryBarrier(MemoryBarrierType type) : type_(type) {}  // NOLINT
121588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MemoryBarrier(uint32_t type)                            // NOLINT
121688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : type_(static_cast<MemoryBarrierType>(type)) {
121788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT((type & 0x3) != 0);
121888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
121988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  MemoryBarrierType GetType() const { return type_; }
122088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
122188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
122288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
122388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, MemoryBarrier option) {
122488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << option.GetName();
122588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
122688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
122788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum InterruptFlagsType {
122888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  F = 0x1,
122988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  I = 0x2,
123088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  IF = 0x3,
123188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  A = 0x4,
123288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  AF = 0x5,
123388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  AI = 0x6,
123488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  AIF = 0x7
123588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
123688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
123788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass InterruptFlags {
123888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  InterruptFlagsType type_;
123988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
124088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
124188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  InterruptFlags(InterruptFlagsType type) : type_(type) {}  // NOLINT
124288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  InterruptFlags(uint32_t type)                             // NOLINT
124388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : type_(static_cast<InterruptFlagsType>(type)) {
124488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(type <= 7);
124588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
124688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  InterruptFlagsType GetType() const { return type_; }
124788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
124888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
124988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
125088c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, InterruptFlags option) {
125188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << option.GetName();
125288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
125388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
125488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum EndiannessType { LE = 0, BE = 1 };
125588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
125688c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Endianness {
125788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  EndiannessType type_;
125888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
125988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
126088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Endianness(EndiannessType type) : type_(type) {}  // NOLINT
126188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Endianness(uint32_t type)                         // NOLINT
126288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : type_(static_cast<EndiannessType>(type)) {
126388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(type <= 1);
126488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
126588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  EndiannessType GetType() const { return type_; }
126688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const char* GetName() const;
126788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
126888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
126988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, Endianness endian_specifier) {
127088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << endian_specifier.GetName();
127188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
127288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
127388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisenum AlignmentType {
127488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  k16BitAlign = 0,
127588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  k32BitAlign = 1,
127688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  k64BitAlign = 2,
127788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  k128BitAlign = 3,
127888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  k256BitAlign = 4,
127988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kNoAlignment = 5,
128088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  kBadAlignment = 6
128188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
128288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
128388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Alignment {
128488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  AlignmentType align_;
128588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
128688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
128788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Alignment(AlignmentType align)  // NOLINT(runtime/explicit)
128888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : align_(align) {}
128988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Alignment(uint32_t align)  // NOLINT(runtime/explicit)
129088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : align_(static_cast<AlignmentType>(align)) {
129188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(align <= static_cast<uint32_t>(k256BitAlign));
129288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
129388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  AlignmentType GetType() const { return align_; }
129488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool Is(AlignmentType type) { return align_ == type; }
129588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
129688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
129788c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisinline std::ostream& operator<<(std::ostream& os, Alignment align) {
129888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (align.GetType() == kBadAlignment) return os << " :??";
129988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (align.GetType() == kNoAlignment) return os;
130088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return os << " :" << (0x10 << static_cast<uint32_t>(align.GetType()));
130188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}
130288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
130388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass RawLiteral : public Label {
130488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
130551d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  enum PlacementPolicy { kPlacedWhenUsed, kManuallyPlaced };
130651d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard
130788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  enum DeletionPolicy {
130888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    kDeletedOnPlacementByPool,
130988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    kDeletedOnPoolDestruction,
131088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    kManuallyDeleted
131188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  };
131288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
131388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
131488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RawLiteral(const void* addr,
131588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             size_t size,
131651d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard             PlacementPolicy placement_policy = kPlacedWhenUsed,
131788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois             DeletionPolicy deletion_policy = kManuallyDeleted)
131888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : addr_(addr),
131988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        size_(size),
132088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        position_(kMaxOffset),
132151d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard        manually_placed_(placement_policy == kManuallyPlaced),
132251d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard        deletion_policy_(deletion_policy) {}
132351d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  RawLiteral(const void* addr, size_t size, DeletionPolicy deletion_policy)
132451d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard      : addr_(addr),
132551d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard        size_(size),
132651d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard        position_(kMaxOffset),
132751d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard        manually_placed_(false),
132888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        deletion_policy_(deletion_policy) {}
132988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ~RawLiteral() {}
133051d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  const void* GetDataAddress() const { return addr_; }
133188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  size_t GetSize() const { return size_; }
133288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  size_t GetAlignedSize() const { return (size_ + 3) & ~0x3; }
133388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
133488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Offset GetPositionInPool() const { return position_; }
133588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void SetPositionInPool(Offset position_in_pool) {
133688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    // Assumed that the literal has not already been added to
133788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    // the pool.
133888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(position_ == Label::kMaxOffset);
133988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    position_ = position_in_pool;
134088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
134188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
134251d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  bool IsManuallyPlaced() const { return manually_placed_; }
134351d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  DeletionPolicy GetDeletionPolicy() const { return deletion_policy_; }
134451d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard
134588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
134688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Data address before it's moved into the code buffer.
134788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const void* const addr_;
134888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Data size before it's moved into the code buffer.
134988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  const size_t size_;
135088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Position in the pool, if not in a pool: Label::kMaxOffset.
135188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Offset position_;
135251d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  // When this flag is true, the label will be placed manually.
135351d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  bool manually_placed_;
135488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // When is the literal to be removed from the memory
135588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Can be delete'd when:
135688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //   moved into the code buffer: kDeletedOnPlacementByPool
135788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //   the pool is delete'd: kDeletedOnPoolDestruction
135888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //   or left to the application: kManuallyDeleted.
135988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  DeletionPolicy deletion_policy_;
136088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
136188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
136288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloistemplate <typename T>
136388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Literal : public RawLiteral {
136488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
136588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit Literal(const T& value,
136651d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard                   PlacementPolicy placement_policy = kPlacedWhenUsed,
136788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                   DeletionPolicy deletion_policy = kManuallyDeleted)
136851d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard      : RawLiteral(&value_, sizeof(T), placement_policy, deletion_policy),
136951d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard        value_(value) {}
137051d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard  explicit Literal(const T& value, DeletionPolicy deletion_policy)
137188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : RawLiteral(&value_, sizeof(T), deletion_policy), value_(value) {}
13723e1b899f48c1328ac748b1f5fa78f417f7ec6581Vincent Belliard  void UpdateValue(const T& value, CodeBuffer* buffer) {
13733e1b899f48c1328ac748b1f5fa78f417f7ec6581Vincent Belliard    value_ = value;
13743e1b899f48c1328ac748b1f5fa78f417f7ec6581Vincent Belliard    if (IsBound()) {
13753e1b899f48c1328ac748b1f5fa78f417f7ec6581Vincent Belliard      buffer->UpdateData(GetLocation(), GetDataAddress(), GetSize());
13763e1b899f48c1328ac748b1f5fa78f417f7ec6581Vincent Belliard    }
13773e1b899f48c1328ac748b1f5fa78f417f7ec6581Vincent Belliard  }
137888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
137988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
138088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  T value_;
138188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
138288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
138325e3987b3b684df88edc8069d60b483b95587be5Pierre Langloisclass StringLiteral : public RawLiteral {
138488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
138525e3987b3b684df88edc8069d60b483b95587be5Pierre Langlois  explicit StringLiteral(const char* str,
138625e3987b3b684df88edc8069d60b483b95587be5Pierre Langlois                         PlacementPolicy placement_policy = kPlacedWhenUsed,
138725e3987b3b684df88edc8069d60b483b95587be5Pierre Langlois                         DeletionPolicy deletion_policy = kManuallyDeleted)
138851d1cccb2cbb843c41a586fbedad00ded8f0d6a0Vincent Belliard      : RawLiteral(str, strlen(str) + 1, placement_policy, deletion_policy) {}
138925e3987b3b684df88edc8069d60b483b95587be5Pierre Langlois  explicit StringLiteral(const char* str, DeletionPolicy deletion_policy)
139088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : RawLiteral(str, strlen(str) + 1, deletion_policy) {}
139188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
139288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
139388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}  // namespace aarch32
139488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}  // namespace vixl
139588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
1396d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#endif  // VIXL_AARCH32_INSTRUCTIONS_AARCH32_H_
1397