1ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu/*
2ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu * Copyright (C) 2014 The Android Open Source Project
3ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu *
4ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu * Licensed under the Apache License, Version 2.0 (the "License");
5ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu * you may not use this file except in compliance with the License.
6ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu * You may obtain a copy of the License at
7ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu *
8ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu *      http://www.apache.org/licenses/LICENSE-2.0
9ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu *
10ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu * Unless required by applicable law or agreed to in writing, software
11ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu * distributed under the License is distributed on an "AS IS" BASIS,
12ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu* See the License for the specific language governing permissions and
14ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu * limitations under the License.
15ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu */
16ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
17ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#ifndef ART_COMPILER_UTILS_ARM64_ASSEMBLER_ARM64_H_
18ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#define ART_COMPILER_UTILS_ARM64_ASSEMBLER_ARM64_H_
19ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
20b95a5345ae4217b70ca36f0cced92f68dda7caf5Stuart Monteith#include <stdint.h>
21700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers#include <memory>
22700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers#include <vector>
23ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
24ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "base/logging.h"
25ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "constants_arm64.h"
26ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "utils/arm64/managed_register_arm64.h"
27ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "utils/assembler.h"
28ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "offsets.h"
29ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "utils.h"
30ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "a64/macro-assembler-a64.h"
31ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "a64/disasm-a64.h"
32ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
33ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescunamespace art {
34ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescunamespace arm64 {
35ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
36ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#define MEM_OP(x...)      vixl::MemOperand(x)
37ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#define COND_OP(x)        static_cast<vixl::Condition>(x)
38ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
39ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuenum Condition {
40ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kNoCondition = -1,
41ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  EQ = 0,
42ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  NE = 1,
43ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  HS = 2,
44ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  LO = 3,
45ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  MI = 4,
46ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  PL = 5,
47ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  VS = 6,
48ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  VC = 7,
49ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  HI = 8,
50ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  LS = 9,
51ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  GE = 10,
52ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  LT = 11,
53ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  GT = 12,
54ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  LE = 13,
55ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  AL = 14,    // Always.
56ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  NV = 15,    // Behaves as always/al.
57ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kMaxCondition = 16,
58ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu};
59ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
60ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuenum LoadOperandType {
61ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadSignedByte,
62ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadUnsignedByte,
63ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadSignedHalfword,
64ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadUnsignedHalfword,
65ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadWord,
66ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadCoreWord,
67ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadSWord,
68ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadDWord
69ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu};
70ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
71ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuenum StoreOperandType {
72ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kStoreByte,
73ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kStoreHalfword,
74ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kStoreWord,
75ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kStoreCoreWord,
76ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kStoreSWord,
77ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kStoreDWord
78ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu};
79ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
80ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuclass Arm64Exception;
81ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
82dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogersclass Arm64Assembler FINAL : public Assembler {
83ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu public:
8475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  Arm64Assembler() : vixl_buf_(new byte[kBufferSizeArm64]),
8575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  vixl_masm_(new vixl::MacroAssembler(vixl_buf_, kBufferSizeArm64)) {}
86ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
87ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  virtual ~Arm64Assembler() {
880f89dac7336251f7921621a926319d461837840fSerban Constantinescu    delete vixl_masm_;
89ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu    delete[] vixl_buf_;
90ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  }
91ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
92ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Emit slow paths queued during assembly.
93ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void EmitSlowPaths();
94ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
95ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Size of generated code.
96ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  size_t CodeSize() const;
97ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
98ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Copy instructions out of assembly buffer into the given region of memory.
99ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void FinalizeInstructions(const MemoryRegion& region);
100ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
101ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Emit code that will create an activation on the stack.
102ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void BuildFrame(size_t frame_size, ManagedRegister method_reg,
103ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu                  const std::vector<ManagedRegister>& callee_save_regs,
104dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                  const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
105ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
106ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Emit code that will remove an activation from the stack.
107dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
108dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      OVERRIDE;
109ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
110dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void IncreaseFrameSize(size_t adjust) OVERRIDE;
111dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void DecreaseFrameSize(size_t adjust) OVERRIDE;
112ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
113ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Store routines.
114dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
115dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
116dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
117dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
11875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void StoreImmediateToThread64(ThreadOffset<8> dest, uint32_t imm, ManagedRegister scratch)
119dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      OVERRIDE;
12075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void StoreStackOffsetToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs,
121dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                                  ManagedRegister scratch) OVERRIDE;
12275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void StoreStackPointerToThread64(ThreadOffset<8> thr_offs) OVERRIDE;
123dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
124dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                     ManagedRegister scratch) OVERRIDE;
125ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
126ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Load routines.
127dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
12875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void LoadFromThread64(ManagedRegister dest, ThreadOffset<8> src, size_t size) OVERRIDE;
129dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void LoadRef(ManagedRegister dest, FrameOffset  src) OVERRIDE;
130dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) OVERRIDE;
131dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
13275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void LoadRawPtrFromThread64(ManagedRegister dest, ThreadOffset<8> offs) OVERRIDE;
133dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers
134ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Copying routines.
135dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE;
13675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void CopyRawPtrFromThread64(FrameOffset fr_offs, ThreadOffset<8> thr_offs,
137dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                              ManagedRegister scratch) OVERRIDE;
13875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void CopyRawPtrToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
139dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      OVERRIDE;
140dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
141dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
142dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
143dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers            size_t size) OVERRIDE;
144dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
145dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers            size_t size) OVERRIDE;
146dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch,
147dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers            size_t size) OVERRIDE;
148dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
149dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers            ManagedRegister scratch, size_t size) OVERRIDE;
150ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
151dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers            ManagedRegister scratch, size_t size) OVERRIDE;
152dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void MemoryBarrier(ManagedRegister scratch) OVERRIDE;
153ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
154ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Sign extension.
155dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
156ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
157ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Zero extension.
158dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
159ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
160ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Exploit fast access in managed code to Thread::Current().
161dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void GetCurrentThread(ManagedRegister tr) OVERRIDE;
162dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
163ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
164eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  // Set up out_reg to hold a Object** into the handle scope, or to be NULL if the
165ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // value is null and null_allowed. in_reg holds a possibly stale reference
166eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  // that can be used to avoid loading the handle scope entry to see if the value is
167ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // NULL.
168eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset,
169dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                       ManagedRegister in_reg, bool null_allowed) OVERRIDE;
170ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
171eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  // Set up out_off to hold a Object** into the handle scope, or to be NULL if the
172ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // value is null and null_allowed.
173eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset,
174dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                       ManagedRegister scratch, bool null_allowed) OVERRIDE;
175ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
176eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  // src holds a handle scope entry (Object**) load this into dst.
177eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
178ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
179ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Heap::VerifyObject on src. In some cases (such as a reference to this) we
180ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // know that src may not be null.
181dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
182dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
183ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
184ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Call to address held at [base+offset].
185dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
186dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
18775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void CallFromThread64(ThreadOffset<8> offset, ManagedRegister scratch) OVERRIDE;
188ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
189c6ee54e9a9fd67d24c63bd802ef2fe540a4f86a5Andreas Gampe  // Jump to address (not setting link register)
190c6ee54e9a9fd67d24c63bd802ef2fe540a4f86a5Andreas Gampe  void JumpTo(ManagedRegister m_base, Offset offs, ManagedRegister m_scratch);
191c6ee54e9a9fd67d24c63bd802ef2fe540a4f86a5Andreas Gampe
192ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Generate code to check if Thread::Current()->exception_ is non-null
193ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // and branch to a ExceptionSlowPath if it is.
194dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
195ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
196ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu private:
197ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  static vixl::Register reg_x(int code) {
198ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu    CHECK(code < kNumberOfCoreRegisters) << code;
199ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu    if (code == SP) {
200ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu      return vixl::sp;
20115523731549152276f23dcf94d81b1a9ce9c5038Serban Constantinescu    } else if (code == XZR) {
20215523731549152276f23dcf94d81b1a9ce9c5038Serban Constantinescu      return vixl::xzr;
203ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu    }
204ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu    return vixl::Register::XRegFromCode(code);
205ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  }
206ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
207ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  static vixl::Register reg_w(int code) {
208ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu    return vixl::Register::WRegFromCode(code);
209ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  }
210ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
211ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  static vixl::FPRegister reg_d(int code) {
212ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu    return vixl::FPRegister::DRegFromCode(code);
213ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  }
214ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
215ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  static vixl::FPRegister reg_s(int code) {
216ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu    return vixl::FPRegister::SRegFromCode(code);
217ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  }
218ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
219ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Emits Exception block.
220ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void EmitExceptionPoll(Arm64Exception *exception);
221ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
222ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void StoreWToOffset(StoreOperandType type, WRegister source,
223ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu                      Register base, int32_t offset);
224ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void StoreToOffset(Register source, Register base, int32_t offset);
225ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void StoreSToOffset(SRegister source, Register base, int32_t offset);
226ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void StoreDToOffset(DRegister source, Register base, int32_t offset);
227ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
228ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void LoadImmediate(Register dest, int32_t value, Condition cond = AL);
229ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void Load(Arm64ManagedRegister dst, Register src, int32_t src_offset, size_t size);
230ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void LoadWFromOffset(LoadOperandType type, WRegister dest,
231ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu                      Register base, int32_t offset);
232ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void LoadFromOffset(Register dest, Register base, int32_t offset);
233ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void LoadSFromOffset(SRegister dest, Register base, int32_t offset);
234ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void LoadDFromOffset(DRegister dest, Register base, int32_t offset);
235ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void AddConstant(Register rd, int32_t value, Condition cond = AL);
236ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void AddConstant(Register rd, Register rn, int32_t value, Condition cond = AL);
237ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
238ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Vixl buffer.
239ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  byte* vixl_buf_;
240ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
2410f89dac7336251f7921621a926319d461837840fSerban Constantinescu  // Vixl assembler.
2420f89dac7336251f7921621a926319d461837840fSerban Constantinescu  vixl::MacroAssembler* vixl_masm_;
243ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
244ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // List of exception blocks to generate at the end of the code cache.
245ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  std::vector<Arm64Exception*> exception_blocks_;
24615523731549152276f23dcf94d81b1a9ce9c5038Serban Constantinescu
24715523731549152276f23dcf94d81b1a9ce9c5038Serban Constantinescu  // Used for testing.
24815523731549152276f23dcf94d81b1a9ce9c5038Serban Constantinescu  friend class Arm64ManagedRegister_VixlRegisters_Test;
249ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu};
250ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
251ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuclass Arm64Exception {
252ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu private:
253ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  explicit Arm64Exception(Arm64ManagedRegister scratch, size_t stack_adjust)
254ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu      : scratch_(scratch), stack_adjust_(stack_adjust) {
255ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu    }
256ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
257ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  vixl::Label* Entry() { return &exception_entry_; }
258ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
259ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Register used for passing Thread::Current()->exception_ .
260ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  const Arm64ManagedRegister scratch_;
261ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
262ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Stack adjust for ExceptionPool.
263ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  const size_t stack_adjust_;
264ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
265ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  vixl::Label exception_entry_;
266ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
267ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  friend class Arm64Assembler;
268ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  DISALLOW_COPY_AND_ASSIGN(Arm64Exception);
269ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu};
270ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
271ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu}  // namespace arm64
272ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu}  // namespace art
273ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
274ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#endif  // ART_COMPILER_UTILS_ARM64_ASSEMBLER_ARM64_H_
275