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