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#include "assembler_arm64.h" 18ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "base/logging.h" 19ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "entrypoints/quick/quick_entrypoints.h" 20ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "offsets.h" 21ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#include "thread.h" 22ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 23ba9388c14381400bcc3f6bc327331fbaca12602aAlexandre Ramesusing namespace vixl; // NOLINT(build/namespaces) 24ba9388c14381400bcc3f6bc327331fbaca12602aAlexandre Rames 25ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescunamespace art { 26ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescunamespace arm64 { 27ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 28ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#ifdef ___ 29ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#error "ARM64 Assembler macro already defined." 30ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#else 31ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#define ___ vixl_masm_-> 32ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu#endif 33ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 34cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Markovoid Arm64Assembler::FinalizeCode() { 35c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames for (const std::unique_ptr<Arm64Exception>& exception : exception_blocks_) { 36c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames EmitExceptionPoll(exception.get()); 37ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 38ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ FinalizeCode(); 39ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 40ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 41ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescusize_t Arm64Assembler::CodeSize() const { 42cee7524afa53216fcd13df8122ece495548a829cAlexandre Rames return vixl_masm_->BufferCapacity() - vixl_masm_->RemainingBufferSpace(); 43ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 44ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 45eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Ramesconst uint8_t* Arm64Assembler::CodeBufferBaseAddress() const { 46eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames return vixl_masm_->GetStartAddress<uint8_t*>(); 47eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames} 48eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames 49ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::FinalizeInstructions(const MemoryRegion& region) { 50ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu // Copy the instructions from the buffer. 51cee7524afa53216fcd13df8122ece495548a829cAlexandre Rames MemoryRegion from(vixl_masm_->GetStartAddress<void*>(), CodeSize()); 52ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu region.CopyFrom(0, from); 53ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 54ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 55ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::GetCurrentThread(ManagedRegister tr) { 569bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu ___ Mov(reg_x(tr.AsArm64().AsXRegister()), reg_x(TR)); 57ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 58ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 59ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::GetCurrentThread(FrameOffset offset, ManagedRegister /* scratch */) { 609bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu StoreToOffset(TR, SP, offset.Int32Value()); 61ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 62ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 63ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu// See Arm64 PCS Section 5.2.2.1. 64ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::IncreaseFrameSize(size_t adjust) { 65ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK_ALIGNED(adjust, kStackAlignment); 66ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu AddConstant(SP, -adjust); 67dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky cfi().AdjustCFAOffset(adjust); 68ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 69ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 70ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu// See Arm64 PCS Section 5.2.2.1. 71ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::DecreaseFrameSize(size_t adjust) { 72ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK_ALIGNED(adjust, kStackAlignment); 73ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu AddConstant(SP, adjust); 74dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky cfi().AdjustCFAOffset(-adjust); 75ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 76ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 7737c92df53979f9f6ab83155ab9521d554d717161Alexandre Ramesvoid Arm64Assembler::AddConstant(XRegister rd, int32_t value, Condition cond) { 78ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu AddConstant(rd, rd, value, cond); 79ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 80ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 8137c92df53979f9f6ab83155ab9521d554d717161Alexandre Ramesvoid Arm64Assembler::AddConstant(XRegister rd, XRegister rn, int32_t value, 82ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Condition cond) { 83ba9388c14381400bcc3f6bc327331fbaca12602aAlexandre Rames if ((cond == al) || (cond == nv)) { 84ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu // VIXL macro-assembler handles all variants. 85ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Add(reg_x(rd), reg_x(rn), value); 86ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else { 870f89dac7336251f7921621a926319d461837840fSerban Constantinescu // temp = rd + value 880f89dac7336251f7921621a926319d461837840fSerban Constantinescu // rd = cond ? temp : rn 890f89dac7336251f7921621a926319d461837840fSerban Constantinescu vixl::UseScratchRegisterScope temps(vixl_masm_); 900f89dac7336251f7921621a926319d461837840fSerban Constantinescu temps.Exclude(reg_x(rd), reg_x(rn)); 910f89dac7336251f7921621a926319d461837840fSerban Constantinescu vixl::Register temp = temps.AcquireX(); 920f89dac7336251f7921621a926319d461837840fSerban Constantinescu ___ Add(temp, reg_x(rn), value); 93ba9388c14381400bcc3f6bc327331fbaca12602aAlexandre Rames ___ Csel(reg_x(rd), temp, reg_x(rd), cond); 94ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 95ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 96ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 97ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::StoreWToOffset(StoreOperandType type, WRegister source, 9837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames XRegister base, int32_t offset) { 99ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu switch (type) { 100ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu case kStoreByte: 101ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Strb(reg_w(source), MEM_OP(reg_x(base), offset)); 102ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu break; 103ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu case kStoreHalfword: 104ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Strh(reg_w(source), MEM_OP(reg_x(base), offset)); 105ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu break; 106ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu case kStoreWord: 107ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Str(reg_w(source), MEM_OP(reg_x(base), offset)); 108ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu break; 109ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu default: 110ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu LOG(FATAL) << "UNREACHABLE"; 111ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 112ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 113ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 11437c92df53979f9f6ab83155ab9521d554d717161Alexandre Ramesvoid Arm64Assembler::StoreToOffset(XRegister source, XRegister base, int32_t offset) { 115ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK_NE(source, SP); 116ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Str(reg_x(source), MEM_OP(reg_x(base), offset)); 117ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 118ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 11937c92df53979f9f6ab83155ab9521d554d717161Alexandre Ramesvoid Arm64Assembler::StoreSToOffset(SRegister source, XRegister base, int32_t offset) { 120ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Str(reg_s(source), MEM_OP(reg_x(base), offset)); 121ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 122ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 12337c92df53979f9f6ab83155ab9521d554d717161Alexandre Ramesvoid Arm64Assembler::StoreDToOffset(DRegister source, XRegister base, int32_t offset) { 124ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Str(reg_d(source), MEM_OP(reg_x(base), offset)); 125ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 126ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 127ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::Store(FrameOffset offs, ManagedRegister m_src, size_t size) { 128ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister src = m_src.AsArm64(); 129ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu if (src.IsNoRegister()) { 130ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK_EQ(0u, size); 131ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else if (src.IsWRegister()) { 132ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK_EQ(4u, size); 133ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu StoreWToOffset(kStoreWord, src.AsWRegister(), SP, offs.Int32Value()); 13437c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames } else if (src.IsXRegister()) { 135ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK_EQ(8u, size); 13637c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreToOffset(src.AsXRegister(), SP, offs.Int32Value()); 137ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else if (src.IsSRegister()) { 138ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu StoreSToOffset(src.AsSRegister(), SP, offs.Int32Value()); 139ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else { 140ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK(src.IsDRegister()) << src; 141ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu StoreDToOffset(src.AsDRegister(), SP, offs.Int32Value()); 142ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 143ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 144ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 145ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::StoreRef(FrameOffset offs, ManagedRegister m_src) { 146ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister src = m_src.AsArm64(); 14737c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(src.IsXRegister()) << src; 14837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreWToOffset(kStoreWord, src.AsOverlappingWRegister(), SP, 14975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu offs.Int32Value()); 150ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 151ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 152ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::StoreRawPtr(FrameOffset offs, ManagedRegister m_src) { 153ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister src = m_src.AsArm64(); 15437c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(src.IsXRegister()) << src; 15537c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreToOffset(src.AsXRegister(), SP, offs.Int32Value()); 156ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 157ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 158ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::StoreImmediateToFrame(FrameOffset offs, uint32_t imm, 159ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ManagedRegister m_scratch) { 160ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister scratch = m_scratch.AsArm64(); 16137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(scratch.IsXRegister()) << scratch; 16237c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadImmediate(scratch.AsXRegister(), imm); 16337c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreWToOffset(kStoreWord, scratch.AsOverlappingWRegister(), SP, 16475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu offs.Int32Value()); 165ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 166ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 16775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescuvoid Arm64Assembler::StoreImmediateToThread64(ThreadOffset<8> offs, uint32_t imm, 168ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ManagedRegister m_scratch) { 169ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister scratch = m_scratch.AsArm64(); 17037c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(scratch.IsXRegister()) << scratch; 17137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadImmediate(scratch.AsXRegister(), imm); 1729bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu StoreToOffset(scratch.AsXRegister(), TR, offs.Int32Value()); 173ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 174ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 17575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescuvoid Arm64Assembler::StoreStackOffsetToThread64(ThreadOffset<8> tr_offs, 176ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu FrameOffset fr_offs, 177ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ManagedRegister m_scratch) { 178ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister scratch = m_scratch.AsArm64(); 17937c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(scratch.IsXRegister()) << scratch; 18037c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames AddConstant(scratch.AsXRegister(), SP, fr_offs.Int32Value()); 1819bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu StoreToOffset(scratch.AsXRegister(), TR, tr_offs.Int32Value()); 182ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 183ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 18475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescuvoid Arm64Assembler::StoreStackPointerToThread64(ThreadOffset<8> tr_offs) { 1850f89dac7336251f7921621a926319d461837840fSerban Constantinescu vixl::UseScratchRegisterScope temps(vixl_masm_); 1860f89dac7336251f7921621a926319d461837840fSerban Constantinescu vixl::Register temp = temps.AcquireX(); 1870f89dac7336251f7921621a926319d461837840fSerban Constantinescu ___ Mov(temp, reg_x(SP)); 1889bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu ___ Str(temp, MEM_OP(reg_x(TR), tr_offs.Int32Value())); 189ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 190ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 191ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::StoreSpanning(FrameOffset dest_off, ManagedRegister m_source, 192ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu FrameOffset in_off, ManagedRegister m_scratch) { 193ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister source = m_source.AsArm64(); 194ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister scratch = m_scratch.AsArm64(); 19537c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreToOffset(source.AsXRegister(), SP, dest_off.Int32Value()); 19637c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadFromOffset(scratch.AsXRegister(), SP, in_off.Int32Value()); 19737c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreToOffset(scratch.AsXRegister(), SP, dest_off.Int32Value() + 8); 198ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 199ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 200ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu// Load routines. 20137c92df53979f9f6ab83155ab9521d554d717161Alexandre Ramesvoid Arm64Assembler::LoadImmediate(XRegister dest, int32_t value, 202ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Condition cond) { 203ba9388c14381400bcc3f6bc327331fbaca12602aAlexandre Rames if ((cond == al) || (cond == nv)) { 204ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Mov(reg_x(dest), value); 205ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else { 2060f89dac7336251f7921621a926319d461837840fSerban Constantinescu // temp = value 2070f89dac7336251f7921621a926319d461837840fSerban Constantinescu // rd = cond ? temp : rd 208ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu if (value != 0) { 2090f89dac7336251f7921621a926319d461837840fSerban Constantinescu vixl::UseScratchRegisterScope temps(vixl_masm_); 2100f89dac7336251f7921621a926319d461837840fSerban Constantinescu temps.Exclude(reg_x(dest)); 2110f89dac7336251f7921621a926319d461837840fSerban Constantinescu vixl::Register temp = temps.AcquireX(); 2120f89dac7336251f7921621a926319d461837840fSerban Constantinescu ___ Mov(temp, value); 213ba9388c14381400bcc3f6bc327331fbaca12602aAlexandre Rames ___ Csel(reg_x(dest), temp, reg_x(dest), cond); 214ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else { 215ba9388c14381400bcc3f6bc327331fbaca12602aAlexandre Rames ___ Csel(reg_x(dest), reg_x(XZR), reg_x(dest), cond); 216ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 217ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 218ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 219ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 220ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::LoadWFromOffset(LoadOperandType type, WRegister dest, 22137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames XRegister base, int32_t offset) { 222ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu switch (type) { 223ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu case kLoadSignedByte: 224ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Ldrsb(reg_w(dest), MEM_OP(reg_x(base), offset)); 225ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu break; 226ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu case kLoadSignedHalfword: 227ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Ldrsh(reg_w(dest), MEM_OP(reg_x(base), offset)); 228ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu break; 229ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu case kLoadUnsignedByte: 230ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Ldrb(reg_w(dest), MEM_OP(reg_x(base), offset)); 231ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu break; 232ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu case kLoadUnsignedHalfword: 233ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Ldrh(reg_w(dest), MEM_OP(reg_x(base), offset)); 234ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu break; 235ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu case kLoadWord: 236ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Ldr(reg_w(dest), MEM_OP(reg_x(base), offset)); 237ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu break; 238ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu default: 239ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu LOG(FATAL) << "UNREACHABLE"; 240ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 241ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 242ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 243ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu// Note: We can extend this member by adding load type info - see 244ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu// sign extended A64 load variants. 24537c92df53979f9f6ab83155ab9521d554d717161Alexandre Ramesvoid Arm64Assembler::LoadFromOffset(XRegister dest, XRegister base, 246ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu int32_t offset) { 247ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK_NE(dest, SP); 248ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Ldr(reg_x(dest), MEM_OP(reg_x(base), offset)); 249ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 250ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 25137c92df53979f9f6ab83155ab9521d554d717161Alexandre Ramesvoid Arm64Assembler::LoadSFromOffset(SRegister dest, XRegister base, 252ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu int32_t offset) { 253ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Ldr(reg_s(dest), MEM_OP(reg_x(base), offset)); 254ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 255ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 25637c92df53979f9f6ab83155ab9521d554d717161Alexandre Ramesvoid Arm64Assembler::LoadDFromOffset(DRegister dest, XRegister base, 257ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu int32_t offset) { 258ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Ldr(reg_d(dest), MEM_OP(reg_x(base), offset)); 259ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 260ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 26137c92df53979f9f6ab83155ab9521d554d717161Alexandre Ramesvoid Arm64Assembler::Load(Arm64ManagedRegister dest, XRegister base, 262ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu int32_t offset, size_t size) { 263ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu if (dest.IsNoRegister()) { 264ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK_EQ(0u, size) << dest; 265ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else if (dest.IsWRegister()) { 266ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK_EQ(4u, size) << dest; 267ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Ldr(reg_w(dest.AsWRegister()), MEM_OP(reg_x(base), offset)); 26837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames } else if (dest.IsXRegister()) { 26937c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK_NE(dest.AsXRegister(), SP) << dest; 27075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu if (size == 4u) { 27137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames ___ Ldr(reg_w(dest.AsOverlappingWRegister()), MEM_OP(reg_x(base), offset)); 27275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else { 27375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu CHECK_EQ(8u, size) << dest; 27437c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames ___ Ldr(reg_x(dest.AsXRegister()), MEM_OP(reg_x(base), offset)); 27575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 276ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else if (dest.IsSRegister()) { 277ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Ldr(reg_s(dest.AsSRegister()), MEM_OP(reg_x(base), offset)); 278ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else { 279ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK(dest.IsDRegister()) << dest; 280ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Ldr(reg_d(dest.AsDRegister()), MEM_OP(reg_x(base), offset)); 281ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 282ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 283ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 284ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::Load(ManagedRegister m_dst, FrameOffset src, size_t size) { 285ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu return Load(m_dst.AsArm64(), SP, src.Int32Value(), size); 286ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 287ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 28875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescuvoid Arm64Assembler::LoadFromThread64(ManagedRegister m_dst, ThreadOffset<8> src, size_t size) { 2899bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu return Load(m_dst.AsArm64(), TR, src.Int32Value(), size); 290ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 291ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 292ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::LoadRef(ManagedRegister m_dst, FrameOffset offs) { 293ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister dst = m_dst.AsArm64(); 29437c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(dst.IsXRegister()) << dst; 29537c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadWFromOffset(kLoadWord, dst.AsOverlappingWRegister(), SP, offs.Int32Value()); 296ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 297ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 298e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid Arm64Assembler::LoadRef(ManagedRegister m_dst, ManagedRegister m_base, MemberOffset offs, 2994d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain bool unpoison_reference) { 300ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister dst = m_dst.AsArm64(); 301ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister base = m_base.AsArm64(); 30237c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(dst.IsXRegister() && base.IsXRegister()); 30337c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadWFromOffset(kLoadWord, dst.AsOverlappingWRegister(), base.AsXRegister(), 30475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu offs.Int32Value()); 3054d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain if (unpoison_reference) { 30637c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames WRegister ref_reg = dst.AsOverlappingWRegister(); 3074d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain MaybeUnpoisonHeapReference(reg_w(ref_reg)); 308b88f0b16dbaff09a140d2a62b66eca2736ff514bHiroshi Yamauchi } 309ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 310ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 311ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::LoadRawPtr(ManagedRegister m_dst, ManagedRegister m_base, Offset offs) { 312ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister dst = m_dst.AsArm64(); 313ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister base = m_base.AsArm64(); 31437c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(dst.IsXRegister() && base.IsXRegister()); 3150f89dac7336251f7921621a926319d461837840fSerban Constantinescu // Remove dst and base form the temp list - higher level API uses IP1, IP0. 3160f89dac7336251f7921621a926319d461837840fSerban Constantinescu vixl::UseScratchRegisterScope temps(vixl_masm_); 31737c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames temps.Exclude(reg_x(dst.AsXRegister()), reg_x(base.AsXRegister())); 31837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames ___ Ldr(reg_x(dst.AsXRegister()), MEM_OP(reg_x(base.AsXRegister()), offs.Int32Value())); 319ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 320ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 32175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescuvoid Arm64Assembler::LoadRawPtrFromThread64(ManagedRegister m_dst, ThreadOffset<8> offs) { 322ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister dst = m_dst.AsArm64(); 32337c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(dst.IsXRegister()) << dst; 3249bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu LoadFromOffset(dst.AsXRegister(), TR, offs.Int32Value()); 325ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 326ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 327ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu// Copying routines. 328ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::Move(ManagedRegister m_dst, ManagedRegister m_src, size_t size) { 329ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister dst = m_dst.AsArm64(); 330ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister src = m_src.AsArm64(); 331ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu if (!dst.Equals(src)) { 33237c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames if (dst.IsXRegister()) { 33375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu if (size == 4) { 33475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu CHECK(src.IsWRegister()); 33532f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu ___ Mov(reg_w(dst.AsOverlappingWRegister()), reg_w(src.AsWRegister())); 33675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else { 33737c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames if (src.IsXRegister()) { 33837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames ___ Mov(reg_x(dst.AsXRegister()), reg_x(src.AsXRegister())); 33975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else { 34032f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu ___ Mov(reg_x(dst.AsXRegister()), reg_x(src.AsOverlappingXRegister())); 34175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 34275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 343ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else if (dst.IsWRegister()) { 344ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK(src.IsWRegister()) << src; 345ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Mov(reg_w(dst.AsWRegister()), reg_w(src.AsWRegister())); 346ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else if (dst.IsSRegister()) { 347ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK(src.IsSRegister()) << src; 348ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Fmov(reg_s(dst.AsSRegister()), reg_s(src.AsSRegister())); 349ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else { 350ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK(dst.IsDRegister()) << dst; 351ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK(src.IsDRegister()) << src; 352ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Fmov(reg_d(dst.AsDRegister()), reg_d(src.AsDRegister())); 353ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 354ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 355ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 356ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 35775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescuvoid Arm64Assembler::CopyRawPtrFromThread64(FrameOffset fr_offs, 35875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu ThreadOffset<8> tr_offs, 359ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ManagedRegister m_scratch) { 360ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister scratch = m_scratch.AsArm64(); 36137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(scratch.IsXRegister()) << scratch; 3629bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu LoadFromOffset(scratch.AsXRegister(), TR, tr_offs.Int32Value()); 36337c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreToOffset(scratch.AsXRegister(), SP, fr_offs.Int32Value()); 364ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 365ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 36675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescuvoid Arm64Assembler::CopyRawPtrToThread64(ThreadOffset<8> tr_offs, 367ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu FrameOffset fr_offs, 368ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ManagedRegister m_scratch) { 369ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister scratch = m_scratch.AsArm64(); 37037c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(scratch.IsXRegister()) << scratch; 37137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadFromOffset(scratch.AsXRegister(), SP, fr_offs.Int32Value()); 3729bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu StoreToOffset(scratch.AsXRegister(), TR, tr_offs.Int32Value()); 373ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 374ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 375ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::CopyRef(FrameOffset dest, FrameOffset src, 376ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ManagedRegister m_scratch) { 377ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister scratch = m_scratch.AsArm64(); 37837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(scratch.IsXRegister()) << scratch; 37937c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadWFromOffset(kLoadWord, scratch.AsOverlappingWRegister(), 38075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu SP, src.Int32Value()); 38137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreWToOffset(kStoreWord, scratch.AsOverlappingWRegister(), 38275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu SP, dest.Int32Value()); 383ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 384ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 385ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::Copy(FrameOffset dest, FrameOffset src, 386ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ManagedRegister m_scratch, size_t size) { 387ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister scratch = m_scratch.AsArm64(); 38837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(scratch.IsXRegister()) << scratch; 389ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK(size == 4 || size == 8) << size; 390ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu if (size == 4) { 39137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadWFromOffset(kLoadWord, scratch.AsOverlappingWRegister(), SP, src.Int32Value()); 39237c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreWToOffset(kStoreWord, scratch.AsOverlappingWRegister(), SP, dest.Int32Value()); 393ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else if (size == 8) { 39437c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadFromOffset(scratch.AsXRegister(), SP, src.Int32Value()); 39537c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreToOffset(scratch.AsXRegister(), SP, dest.Int32Value()); 396ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else { 397ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 398ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 399ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 400ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 401ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, 402ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ManagedRegister m_scratch, size_t size) { 403ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister scratch = m_scratch.AsArm64(); 404ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister base = src_base.AsArm64(); 40537c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(base.IsXRegister()) << base; 40637c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(scratch.IsXRegister() || scratch.IsWRegister()) << scratch; 407ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK(size == 4 || size == 8) << size; 408ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu if (size == 4) { 40937c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadWFromOffset(kLoadWord, scratch.AsWRegister(), base.AsXRegister(), 410ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu src_offset.Int32Value()); 411ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu StoreWToOffset(kStoreWord, scratch.AsWRegister(), SP, dest.Int32Value()); 412ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else if (size == 8) { 41337c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadFromOffset(scratch.AsXRegister(), base.AsXRegister(), src_offset.Int32Value()); 41437c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreToOffset(scratch.AsXRegister(), SP, dest.Int32Value()); 415ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else { 416ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 417ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 418ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 419ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 420ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::Copy(ManagedRegister m_dest_base, Offset dest_offs, FrameOffset src, 421ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ManagedRegister m_scratch, size_t size) { 422ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister scratch = m_scratch.AsArm64(); 423ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister base = m_dest_base.AsArm64(); 42437c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(base.IsXRegister()) << base; 42537c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(scratch.IsXRegister() || scratch.IsWRegister()) << scratch; 426ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK(size == 4 || size == 8) << size; 427ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu if (size == 4) { 428ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu LoadWFromOffset(kLoadWord, scratch.AsWRegister(), SP, src.Int32Value()); 42937c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreWToOffset(kStoreWord, scratch.AsWRegister(), base.AsXRegister(), 430ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu dest_offs.Int32Value()); 431ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else if (size == 8) { 43237c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadFromOffset(scratch.AsXRegister(), SP, src.Int32Value()); 43337c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreToOffset(scratch.AsXRegister(), base.AsXRegister(), dest_offs.Int32Value()); 434ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else { 435ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 436ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 437ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 438ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 439ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::Copy(FrameOffset /*dst*/, FrameOffset /*src_base*/, Offset /*src_offset*/, 440ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ManagedRegister /*mscratch*/, size_t /*size*/) { 441ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu UNIMPLEMENTED(FATAL) << "Unimplemented Copy() variant"; 442ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 443ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 444ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::Copy(ManagedRegister m_dest, Offset dest_offset, 445ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ManagedRegister m_src, Offset src_offset, 446ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ManagedRegister m_scratch, size_t size) { 447ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister scratch = m_scratch.AsArm64(); 448ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister src = m_src.AsArm64(); 449ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister dest = m_dest.AsArm64(); 45037c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(dest.IsXRegister()) << dest; 45137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(src.IsXRegister()) << src; 45237c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(scratch.IsXRegister() || scratch.IsWRegister()) << scratch; 453ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK(size == 4 || size == 8) << size; 454ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu if (size == 4) { 45575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu if (scratch.IsWRegister()) { 45637c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadWFromOffset(kLoadWord, scratch.AsWRegister(), src.AsXRegister(), 457ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu src_offset.Int32Value()); 45837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreWToOffset(kStoreWord, scratch.AsWRegister(), dest.AsXRegister(), 459ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu dest_offset.Int32Value()); 46075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else { 46137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadWFromOffset(kLoadWord, scratch.AsOverlappingWRegister(), src.AsXRegister(), 46275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu src_offset.Int32Value()); 46337c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreWToOffset(kStoreWord, scratch.AsOverlappingWRegister(), dest.AsXRegister(), 46475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu dest_offset.Int32Value()); 46575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 466ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else if (size == 8) { 46737c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadFromOffset(scratch.AsXRegister(), src.AsXRegister(), src_offset.Int32Value()); 46837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreToOffset(scratch.AsXRegister(), dest.AsXRegister(), dest_offset.Int32Value()); 469ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else { 470ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu UNIMPLEMENTED(FATAL) << "We only support Copy() of size 4 and 8"; 471ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 472ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 473ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 474ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::Copy(FrameOffset /*dst*/, Offset /*dest_offset*/, 475ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu FrameOffset /*src*/, Offset /*src_offset*/, 476ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ManagedRegister /*scratch*/, size_t /*size*/) { 477ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu UNIMPLEMENTED(FATAL) << "Unimplemented Copy() variant"; 478ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 479ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 4806a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid Arm64Assembler::MemoryBarrier(ManagedRegister m_scratch ATTRIBUTE_UNUSED) { 481ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu // TODO: Should we check that m_scratch is IP? - see arm. 482ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Dmb(vixl::InnerShareable, vixl::BarrierAll); 483ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 484ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 485d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampevoid Arm64Assembler::SignExtend(ManagedRegister mreg, size_t size) { 486d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe Arm64ManagedRegister reg = mreg.AsArm64(); 487d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe CHECK(size == 1 || size == 2) << size; 488d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe CHECK(reg.IsWRegister()) << reg; 489d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe if (size == 1) { 49032f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu ___ Sxtb(reg_w(reg.AsWRegister()), reg_w(reg.AsWRegister())); 491d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe } else { 49232f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu ___ Sxth(reg_w(reg.AsWRegister()), reg_w(reg.AsWRegister())); 493d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe } 494ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 495ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 496d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampevoid Arm64Assembler::ZeroExtend(ManagedRegister mreg, size_t size) { 497d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe Arm64ManagedRegister reg = mreg.AsArm64(); 498d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe CHECK(size == 1 || size == 2) << size; 499d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe CHECK(reg.IsWRegister()) << reg; 500d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe if (size == 1) { 50132f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu ___ Uxtb(reg_w(reg.AsWRegister()), reg_w(reg.AsWRegister())); 502d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe } else { 50332f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu ___ Uxth(reg_w(reg.AsWRegister()), reg_w(reg.AsWRegister())); 504d1104322e5156669767e8b2c3b843ffaff173381Andreas Gampe } 505ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 506ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 507ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::VerifyObject(ManagedRegister /*src*/, bool /*could_be_null*/) { 508ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu // TODO: not validating references. 509ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 510ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 511ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::VerifyObject(FrameOffset /*src*/, bool /*could_be_null*/) { 512ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu // TODO: not validating references. 513ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 514ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 515ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::Call(ManagedRegister m_base, Offset offs, ManagedRegister m_scratch) { 516ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister base = m_base.AsArm64(); 517ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister scratch = m_scratch.AsArm64(); 51837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(base.IsXRegister()) << base; 51937c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(scratch.IsXRegister()) << scratch; 52037c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadFromOffset(scratch.AsXRegister(), base.AsXRegister(), offs.Int32Value()); 52137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames ___ Blr(reg_x(scratch.AsXRegister())); 522ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 523ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 524c6ee54e9a9fd67d24c63bd802ef2fe540a4f86a5Andreas Gampevoid Arm64Assembler::JumpTo(ManagedRegister m_base, Offset offs, ManagedRegister m_scratch) { 525c6ee54e9a9fd67d24c63bd802ef2fe540a4f86a5Andreas Gampe Arm64ManagedRegister base = m_base.AsArm64(); 526c6ee54e9a9fd67d24c63bd802ef2fe540a4f86a5Andreas Gampe Arm64ManagedRegister scratch = m_scratch.AsArm64(); 52737c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(base.IsXRegister()) << base; 52837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(scratch.IsXRegister()) << scratch; 5290f89dac7336251f7921621a926319d461837840fSerban Constantinescu // Remove base and scratch form the temp list - higher level API uses IP1, IP0. 5300f89dac7336251f7921621a926319d461837840fSerban Constantinescu vixl::UseScratchRegisterScope temps(vixl_masm_); 53137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames temps.Exclude(reg_x(base.AsXRegister()), reg_x(scratch.AsXRegister())); 53237c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames ___ Ldr(reg_x(scratch.AsXRegister()), MEM_OP(reg_x(base.AsXRegister()), offs.Int32Value())); 53337c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames ___ Br(reg_x(scratch.AsXRegister())); 534c6ee54e9a9fd67d24c63bd802ef2fe540a4f86a5Andreas Gampe} 535c6ee54e9a9fd67d24c63bd802ef2fe540a4f86a5Andreas Gampe 536ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::Call(FrameOffset base, Offset offs, ManagedRegister m_scratch) { 537ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister scratch = m_scratch.AsArm64(); 53837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(scratch.IsXRegister()) << scratch; 539ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu // Call *(*(SP + base) + offset) 540e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier LoadFromOffset(scratch.AsXRegister(), SP, base.Int32Value()); 54137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadFromOffset(scratch.AsXRegister(), scratch.AsXRegister(), offs.Int32Value()); 54237c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames ___ Blr(reg_x(scratch.AsXRegister())); 543ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 544ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 54575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescuvoid Arm64Assembler::CallFromThread64(ThreadOffset<8> /*offset*/, ManagedRegister /*scratch*/) { 546ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu UNIMPLEMENTED(FATAL) << "Unimplemented Call() variant"; 547ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 548ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 549e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid Arm64Assembler::CreateHandleScopeEntry( 550e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ManagedRegister m_out_reg, FrameOffset handle_scope_offs, ManagedRegister m_in_reg, 551e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier bool null_allowed) { 552ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister out_reg = m_out_reg.AsArm64(); 553ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister in_reg = m_in_reg.AsArm64(); 554eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // For now we only hold stale handle scope entries in x registers. 55537c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(in_reg.IsNoRegister() || in_reg.IsXRegister()) << in_reg; 55637c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(out_reg.IsXRegister()) << out_reg; 557ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu if (null_allowed) { 558eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is 559eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // the address in the handle scope holding the reference. 560ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset) 561ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu if (in_reg.IsNoRegister()) { 56237c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadWFromOffset(kLoadWord, out_reg.AsOverlappingWRegister(), SP, 563eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier handle_scope_offs.Int32Value()); 564ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu in_reg = out_reg; 565ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 56637c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames ___ Cmp(reg_w(in_reg.AsOverlappingWRegister()), 0); 567ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu if (!out_reg.Equals(in_reg)) { 56837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadImmediate(out_reg.AsXRegister(), 0, eq); 569ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 57037c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames AddConstant(out_reg.AsXRegister(), SP, handle_scope_offs.Int32Value(), ne); 571ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else { 57237c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames AddConstant(out_reg.AsXRegister(), SP, handle_scope_offs.Int32Value(), al); 573ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 574ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 575ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 576eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartiervoid Arm64Assembler::CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handle_scope_offset, 577e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ManagedRegister m_scratch, bool null_allowed) { 578ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister scratch = m_scratch.AsArm64(); 57937c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(scratch.IsXRegister()) << scratch; 580ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu if (null_allowed) { 58137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadWFromOffset(kLoadWord, scratch.AsOverlappingWRegister(), SP, 582eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier handle_scope_offset.Int32Value()); 583eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is 584eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // the address in the handle scope holding the reference. 585eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier // e.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset) 58637c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames ___ Cmp(reg_w(scratch.AsOverlappingWRegister()), 0); 587ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu // Move this logic in add constants with flags. 58837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames AddConstant(scratch.AsXRegister(), SP, handle_scope_offset.Int32Value(), ne); 589ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } else { 59037c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames AddConstant(scratch.AsXRegister(), SP, handle_scope_offset.Int32Value(), al); 591ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 59237c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreToOffset(scratch.AsXRegister(), SP, out_off.Int32Value()); 593ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 594ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 595eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartiervoid Arm64Assembler::LoadReferenceFromHandleScope(ManagedRegister m_out_reg, 596e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ManagedRegister m_in_reg) { 597ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister out_reg = m_out_reg.AsArm64(); 598ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister in_reg = m_in_reg.AsArm64(); 59937c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(out_reg.IsXRegister()) << out_reg; 60037c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames CHECK(in_reg.IsXRegister()) << in_reg; 601ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu vixl::Label exit; 602ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu if (!out_reg.Equals(in_reg)) { 603ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu // FIXME: Who sets the flags here? 60437c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadImmediate(out_reg.AsXRegister(), 0, eq); 605ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 60637c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames ___ Cbz(reg_x(in_reg.AsXRegister()), &exit); 60737c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames LoadFromOffset(out_reg.AsXRegister(), in_reg.AsXRegister(), 0); 608ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Bind(&exit); 609ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 610ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 611ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::ExceptionPoll(ManagedRegister m_scratch, size_t stack_adjust) { 612ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu CHECK_ALIGNED(stack_adjust, kStackAlignment); 613ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu Arm64ManagedRegister scratch = m_scratch.AsArm64(); 614c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames exception_blocks_.emplace_back(new Arm64Exception(scratch, stack_adjust)); 6159bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu LoadFromOffset(scratch.AsXRegister(), TR, Thread::ExceptionOffset<8>().Int32Value()); 616c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames ___ Cbnz(reg_x(scratch.AsXRegister()), exception_blocks_.back()->Entry()); 617ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 618ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 619ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::EmitExceptionPoll(Arm64Exception *exception) { 6200f89dac7336251f7921621a926319d461837840fSerban Constantinescu vixl::UseScratchRegisterScope temps(vixl_masm_); 62137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames temps.Exclude(reg_x(exception->scratch_.AsXRegister())); 6220f89dac7336251f7921621a926319d461837840fSerban Constantinescu vixl::Register temp = temps.AcquireX(); 6230f89dac7336251f7921621a926319d461837840fSerban Constantinescu 6240f89dac7336251f7921621a926319d461837840fSerban Constantinescu // Bind exception poll entry. 625ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Bind(exception->Entry()); 626ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu if (exception->stack_adjust_ != 0) { // Fix up the frame. 627ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu DecreaseFrameSize(exception->stack_adjust_); 628ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 629ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu // Pass exception object as argument. 630ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu // Don't care about preserving X0 as this won't return. 63137c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames ___ Mov(reg_x(X0), reg_x(exception->scratch_.AsXRegister())); 6329bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu ___ Ldr(temp, MEM_OP(reg_x(TR), QUICK_ENTRYPOINT_OFFSET(8, pDeliverException).Int32Value())); 63375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu 6340f89dac7336251f7921621a926319d461837840fSerban Constantinescu ___ Blr(temp); 635ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu // Call should never return. 636ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Brk(); 637ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 638ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 63969a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xustatic inline dwarf::Reg DWARFReg(CPURegister reg) { 64069a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu if (reg.IsFPRegister()) { 64169a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu return dwarf::Reg::Arm64Fp(reg.code()); 64269a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu } else { 64369a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu DCHECK_LT(reg.code(), 31u); // X0 - X30. 64469a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu return dwarf::Reg::Arm64Core(reg.code()); 64569a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu } 646dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky} 647dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky 64869a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xuvoid Arm64Assembler::SpillRegisters(vixl::CPURegList registers, int offset) { 64969a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu int size = registers.RegisterSizeInBytes(); 65069a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu const Register sp = vixl_masm_->StackPointer(); 65169a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu while (registers.Count() >= 2) { 65269a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu const CPURegister& dst0 = registers.PopLowestIndex(); 65369a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu const CPURegister& dst1 = registers.PopLowestIndex(); 65469a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu ___ Stp(dst0, dst1, MemOperand(sp, offset)); 65569a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu cfi_.RelOffset(DWARFReg(dst0), offset); 65669a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu cfi_.RelOffset(DWARFReg(dst1), offset + size); 65769a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu offset += 2 * size; 65869a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu } 65969a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu if (!registers.IsEmpty()) { 66069a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu const CPURegister& dst0 = registers.PopLowestIndex(); 66169a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu ___ Str(dst0, MemOperand(sp, offset)); 66269a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu cfi_.RelOffset(DWARFReg(dst0), offset); 66369a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu } 66469a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu DCHECK(registers.IsEmpty()); 66569a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu} 66669a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu 66769a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xuvoid Arm64Assembler::UnspillRegisters(vixl::CPURegList registers, int offset) { 66869a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu int size = registers.RegisterSizeInBytes(); 66969a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu const Register sp = vixl_masm_->StackPointer(); 67069a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu while (registers.Count() >= 2) { 67169a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu const CPURegister& dst0 = registers.PopLowestIndex(); 67269a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu const CPURegister& dst1 = registers.PopLowestIndex(); 67369a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu ___ Ldp(dst0, dst1, MemOperand(sp, offset)); 67469a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu cfi_.Restore(DWARFReg(dst0)); 67569a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu cfi_.Restore(DWARFReg(dst1)); 67669a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu offset += 2 * size; 67769a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu } 67869a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu if (!registers.IsEmpty()) { 67969a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu const CPURegister& dst0 = registers.PopLowestIndex(); 68069a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu ___ Ldr(dst0, MemOperand(sp, offset)); 68169a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu cfi_.Restore(DWARFReg(dst0)); 68269a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu } 68369a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu DCHECK(registers.IsEmpty()); 684dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky} 685dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky 686ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescuvoid Arm64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg, 68769a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu const std::vector<ManagedRegister>& callee_save_regs, 68869a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu const ManagedRegisterEntrySpills& entry_spills) { 68969a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu // Setup VIXL CPURegList for callee-saves. 69069a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu CPURegList core_reg_list(CPURegister::kRegister, kXRegSize, 0); 69169a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu CPURegList fp_reg_list(CPURegister::kFPRegister, kDRegSize, 0); 69269a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu for (auto r : callee_save_regs) { 69369a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu Arm64ManagedRegister reg = r.AsArm64(); 69469a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu if (reg.IsXRegister()) { 69569a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu core_reg_list.Combine(reg_x(reg.AsXRegister()).code()); 69669a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu } else { 69769a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu DCHECK(reg.IsDRegister()); 69869a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu fp_reg_list.Combine(reg_d(reg.AsDRegister()).code()); 69969a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu } 70069a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu } 70169a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu size_t core_reg_size = core_reg_list.TotalSizeInBytes(); 70269a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu size_t fp_reg_size = fp_reg_list.TotalSizeInBytes(); 70369a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu 70469a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu // Increase frame to required size. 70569a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu DCHECK_ALIGNED(frame_size, kStackAlignment); 706e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier DCHECK_GE(frame_size, core_reg_size + fp_reg_size + kArm64PointerSize); 707b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu IncreaseFrameSize(frame_size); 708b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu 70969a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu // Save callee-saves. 71069a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu SpillRegisters(core_reg_list, frame_size - core_reg_size); 71169a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu SpillRegisters(fp_reg_list, frame_size - core_reg_size - fp_reg_size); 7127cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz 7139bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu DCHECK(core_reg_list.IncludesAliasOf(reg_x(TR))); 714ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 715e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier // Write ArtMethod* 71669a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu DCHECK(X0 == method_reg.AsArm64().AsXRegister()); 717e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier StoreToOffset(X0, SP, 0); 718ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 71975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu // Write out entry spills 720e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier int32_t offset = frame_size + kArm64PointerSize; 721ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu for (size_t i = 0; i < entry_spills.size(); ++i) { 72275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu Arm64ManagedRegister reg = entry_spills.at(i).AsArm64(); 72375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu if (reg.IsNoRegister()) { 72475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu // only increment stack offset. 72575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu ManagedRegisterSpill spill = entry_spills.at(i); 72675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu offset += spill.getSize(); 72737c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames } else if (reg.IsXRegister()) { 72837c92df53979f9f6ab83155ab9521d554d717161Alexandre Rames StoreToOffset(reg.AsXRegister(), SP, offset); 72975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu offset += 8; 73075b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else if (reg.IsWRegister()) { 73175b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu StoreWToOffset(kStoreWord, reg.AsWRegister(), SP, offset); 73275b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu offset += 4; 73375b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else if (reg.IsDRegister()) { 73475b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu StoreDToOffset(reg.AsDRegister(), SP, offset); 73575b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu offset += 8; 73675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } else if (reg.IsSRegister()) { 73775b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu StoreSToOffset(reg.AsSRegister(), SP, offset); 73875b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu offset += 4; 73975b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu } 740ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu } 741ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 742ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 74369a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xuvoid Arm64Assembler::RemoveFrame(size_t frame_size, 74469a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu const std::vector<ManagedRegister>& callee_save_regs) { 74569a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu // Setup VIXL CPURegList for callee-saves. 74669a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu CPURegList core_reg_list(CPURegister::kRegister, kXRegSize, 0); 74769a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu CPURegList fp_reg_list(CPURegister::kFPRegister, kDRegSize, 0); 74869a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu for (auto r : callee_save_regs) { 74969a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu Arm64ManagedRegister reg = r.AsArm64(); 75069a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu if (reg.IsXRegister()) { 75169a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu core_reg_list.Combine(reg_x(reg.AsXRegister()).code()); 75269a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu } else { 75369a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu DCHECK(reg.IsDRegister()); 75469a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu fp_reg_list.Combine(reg_d(reg.AsDRegister()).code()); 75569a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu } 75669a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu } 75769a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu size_t core_reg_size = core_reg_list.TotalSizeInBytes(); 75869a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu size_t fp_reg_size = fp_reg_list.TotalSizeInBytes(); 75969a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu 76069a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu // For now we only check that the size of the frame is large enough to hold spills and method 76169a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu // reference. 762e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier DCHECK_GE(frame_size, core_reg_size + fp_reg_size + kArm64PointerSize); 76369a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu DCHECK_ALIGNED(frame_size, kStackAlignment); 76469a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu 7659bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu DCHECK(core_reg_list.IncludesAliasOf(reg_x(TR))); 76675b9113b2b0a5807043af2a669a93d1579af8e2cSerban Constantinescu 76769a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu cfi_.RememberState(); 76869a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu 76969a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu // Restore callee-saves. 77069a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu UnspillRegisters(core_reg_list, frame_size - core_reg_size); 77169a503050fb8a7b3a79b2cd2cdc2d8fbc594575dZheng Xu UnspillRegisters(fp_reg_list, frame_size - core_reg_size - fp_reg_size); 7727cde48c56df5b57aed524cce44c902bc720f2d6cSebastien Hertz 773b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu // Decrease frame size to start of callee saved regs. 774b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu DecreaseFrameSize(frame_size); 775b551fdcda9eb128c80de37c4fb978968bec6d4b3Zheng Xu 776ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu // Pop callee saved and return to LR. 777ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu ___ Ret(); 778dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky 779dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky // The CFI should be restored for any code that follows the exit block. 780dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky cfi_.RestoreState(); 781dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky cfi_.DefCFAOffset(frame_size); 782ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} 783ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu 7844d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillainvoid Arm64Assembler::PoisonHeapReference(vixl::Register reg) { 7854d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain DCHECK(reg.IsW()); 7864d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain // reg = -reg. 7874d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain ___ Neg(reg, vixl::Operand(reg)); 7884d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain} 7894d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain 7904d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillainvoid Arm64Assembler::UnpoisonHeapReference(vixl::Register reg) { 7914d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain DCHECK(reg.IsW()); 7924d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain // reg = -reg. 7934d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain ___ Neg(reg, vixl::Operand(reg)); 7944d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain} 7954d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain 7964d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillainvoid Arm64Assembler::MaybeUnpoisonHeapReference(vixl::Register reg) { 7974d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain if (kPoisonHeapReferences) { 7984d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain UnpoisonHeapReference(reg); 7994d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain } 8004d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain} 8014d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain 8024d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain#undef ___ 8034d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain 804ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} // namespace arm64 805ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu} // namespace art 806