1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_UTILS_ARM64_ASSEMBLER_ARM64_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_UTILS_ARM64_ASSEMBLER_ARM64_H_
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard Worker #include <stdint.h>
21*795d594fSAndroid Build Coastguard Worker #include <memory>
22*795d594fSAndroid Build Coastguard Worker #include <vector>
23*795d594fSAndroid Build Coastguard Worker
24*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
25*795d594fSAndroid Build Coastguard Worker
26*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils_iterator.h"
27*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
28*795d594fSAndroid Build Coastguard Worker #include "dwarf/register.h"
29*795d594fSAndroid Build Coastguard Worker #include "offsets.h"
30*795d594fSAndroid Build Coastguard Worker #include "utils/arm64/managed_register_arm64.h"
31*795d594fSAndroid Build Coastguard Worker #include "utils/assembler.h"
32*795d594fSAndroid Build Coastguard Worker
33*795d594fSAndroid Build Coastguard Worker // TODO(VIXL): Make VIXL compile cleanly with -Wshadow, -Wdeprecated-declarations.
34*795d594fSAndroid Build Coastguard Worker #pragma GCC diagnostic push
35*795d594fSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wshadow"
36*795d594fSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
37*795d594fSAndroid Build Coastguard Worker #include "aarch64/disasm-aarch64.h"
38*795d594fSAndroid Build Coastguard Worker #include "aarch64/macro-assembler-aarch64.h"
39*795d594fSAndroid Build Coastguard Worker #pragma GCC diagnostic pop
40*795d594fSAndroid Build Coastguard Worker
41*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
42*795d594fSAndroid Build Coastguard Worker
43*795d594fSAndroid Build Coastguard Worker class Arm64InstructionSetFeatures;
44*795d594fSAndroid Build Coastguard Worker
45*795d594fSAndroid Build Coastguard Worker namespace arm64 {
46*795d594fSAndroid Build Coastguard Worker
DWARFReg(vixl::aarch64::CPURegister reg)47*795d594fSAndroid Build Coastguard Worker static inline dwarf::Reg DWARFReg(vixl::aarch64::CPURegister reg) {
48*795d594fSAndroid Build Coastguard Worker if (reg.IsFPRegister()) {
49*795d594fSAndroid Build Coastguard Worker return dwarf::Reg::Arm64Fp(reg.GetCode());
50*795d594fSAndroid Build Coastguard Worker } else {
51*795d594fSAndroid Build Coastguard Worker DCHECK_LT(reg.GetCode(), 31u); // X0 - X30.
52*795d594fSAndroid Build Coastguard Worker return dwarf::Reg::Arm64Core(reg.GetCode());
53*795d594fSAndroid Build Coastguard Worker }
54*795d594fSAndroid Build Coastguard Worker }
55*795d594fSAndroid Build Coastguard Worker
56*795d594fSAndroid Build Coastguard Worker #define MEM_OP(...) vixl::aarch64::MemOperand(__VA_ARGS__)
57*795d594fSAndroid Build Coastguard Worker
58*795d594fSAndroid Build Coastguard Worker enum LoadOperandType {
59*795d594fSAndroid Build Coastguard Worker kLoadSignedByte,
60*795d594fSAndroid Build Coastguard Worker kLoadUnsignedByte,
61*795d594fSAndroid Build Coastguard Worker kLoadSignedHalfword,
62*795d594fSAndroid Build Coastguard Worker kLoadUnsignedHalfword,
63*795d594fSAndroid Build Coastguard Worker kLoadWord,
64*795d594fSAndroid Build Coastguard Worker kLoadCoreWord,
65*795d594fSAndroid Build Coastguard Worker kLoadSWord,
66*795d594fSAndroid Build Coastguard Worker kLoadDWord
67*795d594fSAndroid Build Coastguard Worker };
68*795d594fSAndroid Build Coastguard Worker
69*795d594fSAndroid Build Coastguard Worker enum StoreOperandType {
70*795d594fSAndroid Build Coastguard Worker kStoreByte,
71*795d594fSAndroid Build Coastguard Worker kStoreHalfword,
72*795d594fSAndroid Build Coastguard Worker kStoreWord,
73*795d594fSAndroid Build Coastguard Worker kStoreCoreWord,
74*795d594fSAndroid Build Coastguard Worker kStoreSWord,
75*795d594fSAndroid Build Coastguard Worker kStoreDWord
76*795d594fSAndroid Build Coastguard Worker };
77*795d594fSAndroid Build Coastguard Worker
78*795d594fSAndroid Build Coastguard Worker class Arm64Assembler final : public Assembler {
79*795d594fSAndroid Build Coastguard Worker public:
80*795d594fSAndroid Build Coastguard Worker explicit Arm64Assembler(
81*795d594fSAndroid Build Coastguard Worker ArenaAllocator* allocator, const Arm64InstructionSetFeatures* features = nullptr);
82*795d594fSAndroid Build Coastguard Worker
~Arm64Assembler()83*795d594fSAndroid Build Coastguard Worker virtual ~Arm64Assembler() {}
84*795d594fSAndroid Build Coastguard Worker
GetVIXLAssembler()85*795d594fSAndroid Build Coastguard Worker vixl::aarch64::MacroAssembler* GetVIXLAssembler() { return &vixl_masm_; }
86*795d594fSAndroid Build Coastguard Worker
87*795d594fSAndroid Build Coastguard Worker // Finalize the code.
88*795d594fSAndroid Build Coastguard Worker void FinalizeCode() override;
89*795d594fSAndroid Build Coastguard Worker
90*795d594fSAndroid Build Coastguard Worker // Size of generated code.
91*795d594fSAndroid Build Coastguard Worker size_t CodeSize() const override;
92*795d594fSAndroid Build Coastguard Worker const uint8_t* CodeBufferBaseAddress() const override;
93*795d594fSAndroid Build Coastguard Worker
94*795d594fSAndroid Build Coastguard Worker // Copy instructions out of assembly buffer into the given region of memory.
95*795d594fSAndroid Build Coastguard Worker void CopyInstructions(const MemoryRegion& region) override;
96*795d594fSAndroid Build Coastguard Worker
97*795d594fSAndroid Build Coastguard Worker void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs);
98*795d594fSAndroid Build Coastguard Worker
99*795d594fSAndroid Build Coastguard Worker void SpillRegisters(vixl::aarch64::CPURegList registers, int offset);
100*795d594fSAndroid Build Coastguard Worker void UnspillRegisters(vixl::aarch64::CPURegList registers, int offset);
101*795d594fSAndroid Build Coastguard Worker
102*795d594fSAndroid Build Coastguard Worker // A helper to save/restore a list of ZRegisters to a specified stack offset location.
103*795d594fSAndroid Build Coastguard Worker template <bool is_save>
SaveRestoreZRegisterList(uint32_t vreg_bit_vector,int64_t stack_offset)104*795d594fSAndroid Build Coastguard Worker void SaveRestoreZRegisterList(uint32_t vreg_bit_vector, int64_t stack_offset) {
105*795d594fSAndroid Build Coastguard Worker if (vreg_bit_vector == 0) {
106*795d594fSAndroid Build Coastguard Worker return;
107*795d594fSAndroid Build Coastguard Worker }
108*795d594fSAndroid Build Coastguard Worker vixl::aarch64::UseScratchRegisterScope temps(GetVIXLAssembler());
109*795d594fSAndroid Build Coastguard Worker vixl::aarch64::Register temp = temps.AcquireX();
110*795d594fSAndroid Build Coastguard Worker vixl_masm_.Add(temp, vixl::aarch64::sp, stack_offset);
111*795d594fSAndroid Build Coastguard Worker size_t slot_no = 0;
112*795d594fSAndroid Build Coastguard Worker for (uint32_t i : LowToHighBits(vreg_bit_vector)) {
113*795d594fSAndroid Build Coastguard Worker if (is_save) {
114*795d594fSAndroid Build Coastguard Worker vixl_masm_.Str(vixl::aarch64::ZRegister(i),
115*795d594fSAndroid Build Coastguard Worker vixl::aarch64::SVEMemOperand(temp, slot_no, vixl::aarch64::SVE_MUL_VL));
116*795d594fSAndroid Build Coastguard Worker } else {
117*795d594fSAndroid Build Coastguard Worker vixl_masm_.Ldr(vixl::aarch64::ZRegister(i),
118*795d594fSAndroid Build Coastguard Worker vixl::aarch64::SVEMemOperand(temp, slot_no, vixl::aarch64::SVE_MUL_VL));
119*795d594fSAndroid Build Coastguard Worker }
120*795d594fSAndroid Build Coastguard Worker slot_no++;
121*795d594fSAndroid Build Coastguard Worker }
122*795d594fSAndroid Build Coastguard Worker }
123*795d594fSAndroid Build Coastguard Worker
124*795d594fSAndroid Build Coastguard Worker // Jump to address (not setting link register)
125*795d594fSAndroid Build Coastguard Worker void JumpTo(ManagedRegister m_base, Offset offs, ManagedRegister m_scratch);
126*795d594fSAndroid Build Coastguard Worker
127*795d594fSAndroid Build Coastguard Worker //
128*795d594fSAndroid Build Coastguard Worker // Heap poisoning.
129*795d594fSAndroid Build Coastguard Worker //
130*795d594fSAndroid Build Coastguard Worker
131*795d594fSAndroid Build Coastguard Worker // Poison a heap reference contained in `reg`.
132*795d594fSAndroid Build Coastguard Worker void PoisonHeapReference(vixl::aarch64::Register reg);
133*795d594fSAndroid Build Coastguard Worker // Unpoison a heap reference contained in `reg`.
134*795d594fSAndroid Build Coastguard Worker void UnpoisonHeapReference(vixl::aarch64::Register reg);
135*795d594fSAndroid Build Coastguard Worker // Poison a heap reference contained in `reg` if heap poisoning is enabled.
136*795d594fSAndroid Build Coastguard Worker void MaybePoisonHeapReference(vixl::aarch64::Register reg);
137*795d594fSAndroid Build Coastguard Worker // Unpoison a heap reference contained in `reg` if heap poisoning is enabled.
138*795d594fSAndroid Build Coastguard Worker void MaybeUnpoisonHeapReference(vixl::aarch64::Register reg);
139*795d594fSAndroid Build Coastguard Worker
140*795d594fSAndroid Build Coastguard Worker // Emit code checking the status of the Marking Register, and aborting
141*795d594fSAndroid Build Coastguard Worker // the program if MR does not match the value stored in the art::Thread
142*795d594fSAndroid Build Coastguard Worker // object.
143*795d594fSAndroid Build Coastguard Worker //
144*795d594fSAndroid Build Coastguard Worker // Argument `temp` is used as a temporary register to generate code.
145*795d594fSAndroid Build Coastguard Worker // Argument `code` is used to identify the different occurrences of
146*795d594fSAndroid Build Coastguard Worker // MaybeGenerateMarkingRegisterCheck and is passed to the BRK instruction.
147*795d594fSAndroid Build Coastguard Worker void GenerateMarkingRegisterCheck(vixl::aarch64::Register temp, int code = 0);
148*795d594fSAndroid Build Coastguard Worker
Bind(Label * label)149*795d594fSAndroid Build Coastguard Worker void Bind([[maybe_unused]] Label* label) override {
150*795d594fSAndroid Build Coastguard Worker UNIMPLEMENTED(FATAL) << "Do not use Bind(Label*) for ARM64";
151*795d594fSAndroid Build Coastguard Worker }
Jump(Label * label)152*795d594fSAndroid Build Coastguard Worker void Jump([[maybe_unused]] Label* label) override {
153*795d594fSAndroid Build Coastguard Worker UNIMPLEMENTED(FATAL) << "Do not use Jump(Label*) for ARM64";
154*795d594fSAndroid Build Coastguard Worker }
155*795d594fSAndroid Build Coastguard Worker
Bind(vixl::aarch64::Label * label)156*795d594fSAndroid Build Coastguard Worker void Bind(vixl::aarch64::Label* label) {
157*795d594fSAndroid Build Coastguard Worker vixl_masm_.Bind(label);
158*795d594fSAndroid Build Coastguard Worker }
Jump(vixl::aarch64::Label * label)159*795d594fSAndroid Build Coastguard Worker void Jump(vixl::aarch64::Label* label) {
160*795d594fSAndroid Build Coastguard Worker vixl_masm_.B(label);
161*795d594fSAndroid Build Coastguard Worker }
162*795d594fSAndroid Build Coastguard Worker
reg_x(int code)163*795d594fSAndroid Build Coastguard Worker static vixl::aarch64::Register reg_x(int code) {
164*795d594fSAndroid Build Coastguard Worker CHECK(code < kNumberOfXRegisters) << code;
165*795d594fSAndroid Build Coastguard Worker if (code == SP) {
166*795d594fSAndroid Build Coastguard Worker return vixl::aarch64::sp;
167*795d594fSAndroid Build Coastguard Worker } else if (code == XZR) {
168*795d594fSAndroid Build Coastguard Worker return vixl::aarch64::xzr;
169*795d594fSAndroid Build Coastguard Worker }
170*795d594fSAndroid Build Coastguard Worker return vixl::aarch64::XRegister(code);
171*795d594fSAndroid Build Coastguard Worker }
172*795d594fSAndroid Build Coastguard Worker
reg_w(int code)173*795d594fSAndroid Build Coastguard Worker static vixl::aarch64::Register reg_w(int code) {
174*795d594fSAndroid Build Coastguard Worker CHECK(code < kNumberOfWRegisters) << code;
175*795d594fSAndroid Build Coastguard Worker if (code == WSP) {
176*795d594fSAndroid Build Coastguard Worker return vixl::aarch64::wsp;
177*795d594fSAndroid Build Coastguard Worker } else if (code == WZR) {
178*795d594fSAndroid Build Coastguard Worker return vixl::aarch64::wzr;
179*795d594fSAndroid Build Coastguard Worker }
180*795d594fSAndroid Build Coastguard Worker return vixl::aarch64::WRegister(code);
181*795d594fSAndroid Build Coastguard Worker }
182*795d594fSAndroid Build Coastguard Worker
reg_d(int code)183*795d594fSAndroid Build Coastguard Worker static vixl::aarch64::VRegister reg_d(int code) {
184*795d594fSAndroid Build Coastguard Worker return vixl::aarch64::DRegister(code);
185*795d594fSAndroid Build Coastguard Worker }
186*795d594fSAndroid Build Coastguard Worker
reg_s(int code)187*795d594fSAndroid Build Coastguard Worker static vixl::aarch64::VRegister reg_s(int code) {
188*795d594fSAndroid Build Coastguard Worker return vixl::aarch64::SRegister(code);
189*795d594fSAndroid Build Coastguard Worker }
190*795d594fSAndroid Build Coastguard Worker
191*795d594fSAndroid Build Coastguard Worker private:
192*795d594fSAndroid Build Coastguard Worker // VIXL assembler.
193*795d594fSAndroid Build Coastguard Worker vixl::aarch64::MacroAssembler vixl_masm_;
194*795d594fSAndroid Build Coastguard Worker
195*795d594fSAndroid Build Coastguard Worker // Used for testing.
196*795d594fSAndroid Build Coastguard Worker friend class Arm64ManagedRegister_VixlRegisters_Test;
197*795d594fSAndroid Build Coastguard Worker };
198*795d594fSAndroid Build Coastguard Worker
199*795d594fSAndroid Build Coastguard Worker } // namespace arm64
200*795d594fSAndroid Build Coastguard Worker } // namespace art
201*795d594fSAndroid Build Coastguard Worker
202*795d594fSAndroid Build Coastguard Worker #endif // ART_COMPILER_UTILS_ARM64_ASSEMBLER_ARM64_H_
203