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.
134d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain * 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
24d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko#include "base/arena_containers.h"
25ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "base/logging.h"
26ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "constants_arm64.h"
27ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "utils/arm64/managed_register_arm64.h"
28ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "utils/assembler.h"
29ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "offsets.h"
30277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe
31277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe// TODO: make vixl clean wrt -Wshadow.
32277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#pragma GCC diagnostic push
3365b798ea10dd716c1bb3dda029f9bf255435af72Andreas Gampe#pragma GCC diagnostic ignored "-Wunknown-pragmas"
34277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#pragma GCC diagnostic ignored "-Wshadow"
3565b798ea10dd716c1bb3dda029f9bf255435af72Andreas Gampe#pragma GCC diagnostic ignored "-Wmissing-noreturn"
3682e52ce8364e3e1c644d0d3b3b4f61364bf7089aSerban Constantinescu#include "vixl/a64/macro-assembler-a64.h"
3782e52ce8364e3e1c644d0d3b3b4f61364bf7089aSerban Constantinescu#include "vixl/a64/disasm-a64.h"
38277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#pragma GCC diagnostic pop
39ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
40ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescunamespace art {
41ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescunamespace arm64 {
42ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
43c8ccf68b805c92674545f63e0341ba47e8d9701cAndreas Gampe#define MEM_OP(...)      vixl::MemOperand(__VA_ARGS__)
44ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
45ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuenum LoadOperandType {
46ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadSignedByte,
47ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadUnsignedByte,
48ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadSignedHalfword,
49ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadUnsignedHalfword,
50ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadWord,
51ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadCoreWord,
52ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadSWord,
53ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kLoadDWord
54ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu};
55ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
56ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuenum StoreOperandType {
57ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kStoreByte,
58ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kStoreHalfword,
59ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kStoreWord,
60ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kStoreCoreWord,
61ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kStoreSWord,
62ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  kStoreDWord
63ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu};
64ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
65c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Ramesclass Arm64Exception {
66c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames private:
67c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  Arm64Exception(Arm64ManagedRegister scratch, size_t stack_adjust)
68c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames      : scratch_(scratch), stack_adjust_(stack_adjust) {
69c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames    }
70c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames
71c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  vixl::Label* Entry() { return &exception_entry_; }
72c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames
73c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  // Register used for passing Thread::Current()->exception_ .
74c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  const Arm64ManagedRegister scratch_;
75c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames
76c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  // Stack adjust for ExceptionPool.
77c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  const size_t stack_adjust_;
78c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames
79c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  vixl::Label exception_entry_;
80c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames
81c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  friend class Arm64Assembler;
82c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  DISALLOW_COPY_AND_ASSIGN(Arm64Exception);
83c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames};
84ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
85dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogersclass Arm64Assembler FINAL : public Assembler {
86ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu public:
87cee7524afa53216fcd13df8122ece495548a829cAlexandre Rames  // We indicate the size of the initial code generation buffer to the VIXL
88cee7524afa53216fcd13df8122ece495548a829cAlexandre Rames  // assembler. From there we it will automatically manage the buffer.
89d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko  explicit Arm64Assembler(ArenaAllocator* arena)
90d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko      : Assembler(arena),
91d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko        exception_blocks_(arena->Adapter(kArenaAllocAssembler)),
92d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko        vixl_masm_(new vixl::MacroAssembler(kArm64BaseBufferSize)) {}
93ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
94ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  virtual ~Arm64Assembler() {
950f89dac7336251f7921621a926319d461837840fSerban Constantinescu    delete vixl_masm_;
96ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  }
97ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
98cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // Finalize the code.
99cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  void FinalizeCode() OVERRIDE;
100ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
101ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Size of generated code.
102eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  size_t CodeSize() const OVERRIDE;
103eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  const uint8_t* CodeBufferBaseAddress() const OVERRIDE;
104ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
105ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Copy instructions out of assembly buffer into the given region of memory.
106ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void FinalizeInstructions(const MemoryRegion& region);
107ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
10869a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu  void SpillRegisters(vixl::CPURegList registers, int offset);
10969a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu  void UnspillRegisters(vixl::CPURegList registers, int offset);
11069a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu
111ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Emit code that will create an activation on the stack.
112ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void BuildFrame(size_t frame_size, ManagedRegister method_reg,
113ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu                  const std::vector<ManagedRegister>& callee_save_regs,
114dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                  const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
115ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
116ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Emit code that will remove an activation from the stack.
117dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
118dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      OVERRIDE;
119ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
120dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void IncreaseFrameSize(size_t adjust) OVERRIDE;
121dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void DecreaseFrameSize(size_t adjust) OVERRIDE;
122ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
123ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Store routines.
124dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
125dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
126dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
127dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
12875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void StoreImmediateToThread64(ThreadOffset<8> dest, uint32_t imm, ManagedRegister scratch)
129dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      OVERRIDE;
13075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void StoreStackOffsetToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs,
131dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                                  ManagedRegister scratch) OVERRIDE;
13275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void StoreStackPointerToThread64(ThreadOffset<8> thr_offs) OVERRIDE;
133dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
134dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                     ManagedRegister scratch) OVERRIDE;
135ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
136ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Load routines.
137dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
13875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void LoadFromThread64(ManagedRegister dest, ThreadOffset<8> src, size_t size) OVERRIDE;
139e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
140e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs,
1414d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain               bool unpoison_reference) OVERRIDE;
142dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
14375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void LoadRawPtrFromThread64(ManagedRegister dest, ThreadOffset<8> offs) OVERRIDE;
144dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers
145ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Copying routines.
146dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE;
14775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void CopyRawPtrFromThread64(FrameOffset fr_offs, ThreadOffset<8> thr_offs,
148dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                              ManagedRegister scratch) OVERRIDE;
14975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void CopyRawPtrToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
150dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      OVERRIDE;
151dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
152dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
153dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
154dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers            size_t size) OVERRIDE;
155dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
156dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers            size_t size) OVERRIDE;
157dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch,
158dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers            size_t size) OVERRIDE;
159dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
160dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers            ManagedRegister scratch, size_t size) OVERRIDE;
161ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
162dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers            ManagedRegister scratch, size_t size) OVERRIDE;
163dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void MemoryBarrier(ManagedRegister scratch) OVERRIDE;
164ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
165ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Sign extension.
166dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
167ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
168ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Zero extension.
169dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
170ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
171ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Exploit fast access in managed code to Thread::Current().
172dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void GetCurrentThread(ManagedRegister tr) OVERRIDE;
173dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
174ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
1752cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  // Set up out_reg to hold a Object** into the handle scope, or to be null if the
176ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // value is null and null_allowed. in_reg holds a possibly stale reference
177eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  // that can be used to avoid loading the handle scope entry to see if the value is
1782cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  // null.
179eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset,
180dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                       ManagedRegister in_reg, bool null_allowed) OVERRIDE;
181ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
1822cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  // Set up out_off to hold a Object** into the handle scope, or to be null if the
183ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // value is null and null_allowed.
184eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset,
185dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                       ManagedRegister scratch, bool null_allowed) OVERRIDE;
186ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
187eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  // src holds a handle scope entry (Object**) load this into dst.
188eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
189ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
190ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Heap::VerifyObject on src. In some cases (such as a reference to this) we
191ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // know that src may not be null.
192dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
193dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
194ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
195ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Call to address held at [base+offset].
196dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
197dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
19875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu  void CallFromThread64(ThreadOffset<8> offset, ManagedRegister scratch) OVERRIDE;
199ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
200c6ee54e9a9fd67d24c63bd802ef2fe540a4f86a5Andreas Gampe  // Jump to address (not setting link register)
201c6ee54e9a9fd67d24c63bd802ef2fe540a4f86a5Andreas Gampe  void JumpTo(ManagedRegister m_base, Offset offs, ManagedRegister m_scratch);
202c6ee54e9a9fd67d24c63bd802ef2fe540a4f86a5Andreas Gampe
203ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Generate code to check if Thread::Current()->exception_ is non-null
204ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // and branch to a ExceptionSlowPath if it is.
205dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
206ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
2074d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain  //
2084d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain  // Heap poisoning.
2094d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain  //
2104d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain
2114d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain  // Poison a heap reference contained in `reg`.
2124d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain  void PoisonHeapReference(vixl::Register reg);
2134d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain  // Unpoison a heap reference contained in `reg`.
2144d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain  void UnpoisonHeapReference(vixl::Register reg);
2154d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain  // Unpoison a heap reference contained in `reg` if heap poisoning is enabled.
2164d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain  void MaybeUnpoisonHeapReference(vixl::Register reg);
2174d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain
21885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  void Bind(Label* label ATTRIBUTE_UNUSED) OVERRIDE {
21985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    UNIMPLEMENTED(FATAL) << "Do not use Bind for ARM64";
22085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  }
22185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  void Jump(Label* label ATTRIBUTE_UNUSED) OVERRIDE {
22285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe    UNIMPLEMENTED(FATAL) << "Do not use Jump for ARM64";
22385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  }
22485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
225ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu private:
226ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  static vixl::Register reg_x(int code) {
22737c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames    CHECK(code < kNumberOfXRegisters) << code;
228ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu    if (code == SP) {
229ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu      return vixl::sp;
23015523731549152276f23dcf94d81b1a9ce9c5038Serban Constantinescu    } else if (code == XZR) {
23115523731549152276f23dcf94d81b1a9ce9c5038Serban Constantinescu      return vixl::xzr;
232ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu    }
233ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu    return vixl::Register::XRegFromCode(code);
234ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  }
235ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
236ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  static vixl::Register reg_w(int code) {
23737c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames    CHECK(code < kNumberOfWRegisters) << code;
238a304f97c97d38af73afe6b49259ac4faf0902123Alexandre Rames    if (code == WSP) {
239a304f97c97d38af73afe6b49259ac4faf0902123Alexandre Rames      return vixl::wsp;
240a304f97c97d38af73afe6b49259ac4faf0902123Alexandre Rames    } else if (code == WZR) {
241a304f97c97d38af73afe6b49259ac4faf0902123Alexandre Rames      return vixl::wzr;
242a304f97c97d38af73afe6b49259ac4faf0902123Alexandre Rames    }
243ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu    return vixl::Register::WRegFromCode(code);
244ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  }
245ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
246ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  static vixl::FPRegister reg_d(int code) {
247ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu    return vixl::FPRegister::DRegFromCode(code);
248ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  }
249ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
250ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  static vixl::FPRegister reg_s(int code) {
251ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu    return vixl::FPRegister::SRegFromCode(code);
252ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  }
253ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
254ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // Emits Exception block.
255ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void EmitExceptionPoll(Arm64Exception *exception);
256ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
257ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void StoreWToOffset(StoreOperandType type, WRegister source,
25837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames                      XRegister base, int32_t offset);
25937c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames  void StoreToOffset(XRegister source, XRegister base, int32_t offset);
26037c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames  void StoreSToOffset(SRegister source, XRegister base, int32_t offset);
26137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames  void StoreDToOffset(DRegister source, XRegister base, int32_t offset);
262ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
26337c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames  void LoadImmediate(XRegister dest, int32_t value, vixl::Condition cond = vixl::al);
26437c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames  void Load(Arm64ManagedRegister dst, XRegister src, int32_t src_offset, size_t size);
265ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  void LoadWFromOffset(LoadOperandType type, WRegister dest,
26637c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames                      XRegister base, int32_t offset);
26737c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames  void LoadFromOffset(XRegister dest, XRegister base, int32_t offset);
26837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames  void LoadSFromOffset(SRegister dest, XRegister base, int32_t offset);
26937c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames  void LoadDFromOffset(DRegister dest, XRegister base, int32_t offset);
27037c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames  void AddConstant(XRegister rd, int32_t value, vixl::Condition cond = vixl::al);
27137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames  void AddConstant(XRegister rd, XRegister rn, int32_t value, vixl::Condition cond = vixl::al);
272ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
273ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  // List of exception blocks to generate at the end of the code cache.
274c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames  ArenaVector<std::unique_ptr<Arm64Exception>> exception_blocks_;
27515523731549152276f23dcf94d81b1a9ce9c5038Serban Constantinescu
2765319defdf502fc4569316473846b83180ec08035Alexandre Rames public:
2775319defdf502fc4569316473846b83180ec08035Alexandre Rames  // Vixl assembler.
2785319defdf502fc4569316473846b83180ec08035Alexandre Rames  vixl::MacroAssembler* const vixl_masm_;
2795319defdf502fc4569316473846b83180ec08035Alexandre Rames
28015523731549152276f23dcf94d81b1a9ce9c5038Serban Constantinescu  // Used for testing.
28115523731549152276f23dcf94d81b1a9ce9c5038Serban Constantinescu  friend class Arm64ManagedRegister_VixlRegisters_Test;
282ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu};
283ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
284ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu}  // namespace arm64
285ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu}  // namespace art
286ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu
287ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#endif  // ART_COMPILER_UTILS_ARM64_ASSEMBLER_ARM64_H_
288