1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2016 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_ARM_ASSEMBLER_ARM_VIXL_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_VIXL_H_
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
21*795d594fSAndroid Build Coastguard Worker
22*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
23*795d594fSAndroid Build Coastguard Worker #include "constants_arm.h"
24*795d594fSAndroid Build Coastguard Worker #include "dwarf/register.h"
25*795d594fSAndroid Build Coastguard Worker #include "offsets.h"
26*795d594fSAndroid Build Coastguard Worker #include "utils/arm/managed_register_arm.h"
27*795d594fSAndroid Build Coastguard Worker #include "utils/assembler.h"
28*795d594fSAndroid Build Coastguard Worker
29*795d594fSAndroid Build Coastguard Worker // TODO(VIXL): Make VIXL compile cleanly with -Wshadow, -Wdeprecated-declarations.
30*795d594fSAndroid Build Coastguard Worker #pragma GCC diagnostic push
31*795d594fSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wshadow"
32*795d594fSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
33*795d594fSAndroid Build Coastguard Worker #include "aarch32/macro-assembler-aarch32.h"
34*795d594fSAndroid Build Coastguard Worker #pragma GCC diagnostic pop
35*795d594fSAndroid Build Coastguard Worker
36*795d594fSAndroid Build Coastguard Worker namespace vixl32 = vixl::aarch32;
37*795d594fSAndroid Build Coastguard Worker
38*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
39*795d594fSAndroid Build Coastguard Worker namespace arm {
40*795d594fSAndroid Build Coastguard Worker
DWARFReg(vixl32::Register reg)41*795d594fSAndroid Build Coastguard Worker inline dwarf::Reg DWARFReg(vixl32::Register reg) {
42*795d594fSAndroid Build Coastguard Worker return dwarf::Reg::ArmCore(static_cast<int>(reg.GetCode()));
43*795d594fSAndroid Build Coastguard Worker }
44*795d594fSAndroid Build Coastguard Worker
DWARFReg(vixl32::SRegister reg)45*795d594fSAndroid Build Coastguard Worker inline dwarf::Reg DWARFReg(vixl32::SRegister reg) {
46*795d594fSAndroid Build Coastguard Worker return dwarf::Reg::ArmFp(static_cast<int>(reg.GetCode()));
47*795d594fSAndroid Build Coastguard Worker }
48*795d594fSAndroid Build Coastguard Worker
49*795d594fSAndroid Build Coastguard Worker enum LoadOperandType {
50*795d594fSAndroid Build Coastguard Worker kLoadSignedByte,
51*795d594fSAndroid Build Coastguard Worker kLoadUnsignedByte,
52*795d594fSAndroid Build Coastguard Worker kLoadSignedHalfword,
53*795d594fSAndroid Build Coastguard Worker kLoadUnsignedHalfword,
54*795d594fSAndroid Build Coastguard Worker kLoadWord,
55*795d594fSAndroid Build Coastguard Worker kLoadWordPair,
56*795d594fSAndroid Build Coastguard Worker kLoadSWord,
57*795d594fSAndroid Build Coastguard Worker kLoadDWord
58*795d594fSAndroid Build Coastguard Worker };
59*795d594fSAndroid Build Coastguard Worker
60*795d594fSAndroid Build Coastguard Worker enum StoreOperandType {
61*795d594fSAndroid Build Coastguard Worker kStoreByte,
62*795d594fSAndroid Build Coastguard Worker kStoreHalfword,
63*795d594fSAndroid Build Coastguard Worker kStoreWord,
64*795d594fSAndroid Build Coastguard Worker kStoreWordPair,
65*795d594fSAndroid Build Coastguard Worker kStoreSWord,
66*795d594fSAndroid Build Coastguard Worker kStoreDWord
67*795d594fSAndroid Build Coastguard Worker };
68*795d594fSAndroid Build Coastguard Worker
69*795d594fSAndroid Build Coastguard Worker class ArmVIXLMacroAssembler final : public vixl32::MacroAssembler {
70*795d594fSAndroid Build Coastguard Worker public:
71*795d594fSAndroid Build Coastguard Worker // Most methods fit in a 1KB code buffer, which results in more optimal alloc/realloc and
72*795d594fSAndroid Build Coastguard Worker // fewer system calls than a larger default capacity.
73*795d594fSAndroid Build Coastguard Worker static constexpr size_t kDefaultCodeBufferCapacity = 1 * KB;
74*795d594fSAndroid Build Coastguard Worker
ArmVIXLMacroAssembler()75*795d594fSAndroid Build Coastguard Worker ArmVIXLMacroAssembler()
76*795d594fSAndroid Build Coastguard Worker : vixl32::MacroAssembler(ArmVIXLMacroAssembler::kDefaultCodeBufferCapacity) {}
77*795d594fSAndroid Build Coastguard Worker
78*795d594fSAndroid Build Coastguard Worker // The following interfaces can generate CMP+Bcc or Cbz/Cbnz.
79*795d594fSAndroid Build Coastguard Worker // CMP+Bcc are generated by default.
80*795d594fSAndroid Build Coastguard Worker // If a hint is given (is_far_target = false) and rn and label can all fit into Cbz/Cbnz,
81*795d594fSAndroid Build Coastguard Worker // then Cbz/Cbnz is generated.
82*795d594fSAndroid Build Coastguard Worker // Prefer following interfaces to using vixl32::MacroAssembler::Cbz/Cbnz.
83*795d594fSAndroid Build Coastguard Worker // In T32, Cbz/Cbnz instructions have following limitations:
84*795d594fSAndroid Build Coastguard Worker // - Far targets, which are over 126 bytes away, are not supported.
85*795d594fSAndroid Build Coastguard Worker // - Only low registers can be encoded.
86*795d594fSAndroid Build Coastguard Worker // - Backward branches are not supported.
87*795d594fSAndroid Build Coastguard Worker void CompareAndBranchIfZero(vixl32::Register rn,
88*795d594fSAndroid Build Coastguard Worker vixl32::Label* label,
89*795d594fSAndroid Build Coastguard Worker bool is_far_target = true);
90*795d594fSAndroid Build Coastguard Worker void CompareAndBranchIfNonZero(vixl32::Register rn,
91*795d594fSAndroid Build Coastguard Worker vixl32::Label* label,
92*795d594fSAndroid Build Coastguard Worker bool is_far_target = true);
93*795d594fSAndroid Build Coastguard Worker
94*795d594fSAndroid Build Coastguard Worker // In T32 some of the instructions (add, mov, etc) outside an IT block
95*795d594fSAndroid Build Coastguard Worker // have only 32-bit encodings. But there are 16-bit flag setting
96*795d594fSAndroid Build Coastguard Worker // versions of these instructions (adds, movs, etc). In most of the
97*795d594fSAndroid Build Coastguard Worker // cases in ART we don't care if the instructions keep flags or not;
98*795d594fSAndroid Build Coastguard Worker // thus we can benefit from smaller code size.
99*795d594fSAndroid Build Coastguard Worker // VIXL will never generate flag setting versions (for example, adds
100*795d594fSAndroid Build Coastguard Worker // for Add macro instruction) unless vixl32::DontCare option is
101*795d594fSAndroid Build Coastguard Worker // explicitly specified. That's why we introduce wrappers to use
102*795d594fSAndroid Build Coastguard Worker // DontCare option by default.
103*795d594fSAndroid Build Coastguard Worker #define WITH_FLAGS_DONT_CARE_RD_RN_OP(func_name) \
104*795d594fSAndroid Build Coastguard Worker void (func_name)(vixl32::Register rd, vixl32::Register rn, const vixl32::Operand& operand) { \
105*795d594fSAndroid Build Coastguard Worker MacroAssembler::func_name(vixl32::DontCare, rd, rn, operand); \
106*795d594fSAndroid Build Coastguard Worker } \
107*795d594fSAndroid Build Coastguard Worker using MacroAssembler::func_name
108*795d594fSAndroid Build Coastguard Worker
109*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_RN_OP(Adc);
110*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_RN_OP(Sub);
111*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_RN_OP(Sbc);
112*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_RN_OP(Rsb);
113*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_RN_OP(Rsc);
114*795d594fSAndroid Build Coastguard Worker
115*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_RN_OP(Eor);
116*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_RN_OP(Orr);
117*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_RN_OP(Orn);
118*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_RN_OP(And);
119*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_RN_OP(Bic);
120*795d594fSAndroid Build Coastguard Worker
121*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_RN_OP(Asr);
122*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_RN_OP(Lsr);
123*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_RN_OP(Lsl);
124*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_RN_OP(Ror);
125*795d594fSAndroid Build Coastguard Worker
126*795d594fSAndroid Build Coastguard Worker #undef WITH_FLAGS_DONT_CARE_RD_RN_OP
127*795d594fSAndroid Build Coastguard Worker
128*795d594fSAndroid Build Coastguard Worker #define WITH_FLAGS_DONT_CARE_RD_OP(func_name) \
129*795d594fSAndroid Build Coastguard Worker void (func_name)(vixl32::Register rd, const vixl32::Operand& operand) { \
130*795d594fSAndroid Build Coastguard Worker MacroAssembler::func_name(vixl32::DontCare, rd, operand); \
131*795d594fSAndroid Build Coastguard Worker } \
132*795d594fSAndroid Build Coastguard Worker using MacroAssembler::func_name
133*795d594fSAndroid Build Coastguard Worker
134*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_OP(Mvn);
135*795d594fSAndroid Build Coastguard Worker WITH_FLAGS_DONT_CARE_RD_OP(Mov);
136*795d594fSAndroid Build Coastguard Worker
137*795d594fSAndroid Build Coastguard Worker #undef WITH_FLAGS_DONT_CARE_RD_OP
138*795d594fSAndroid Build Coastguard Worker
139*795d594fSAndroid Build Coastguard Worker // The following two functions don't fall into above categories. Overload them separately.
Rrx(vixl32::Register rd,vixl32::Register rn)140*795d594fSAndroid Build Coastguard Worker void Rrx(vixl32::Register rd, vixl32::Register rn) {
141*795d594fSAndroid Build Coastguard Worker MacroAssembler::Rrx(vixl32::DontCare, rd, rn);
142*795d594fSAndroid Build Coastguard Worker }
143*795d594fSAndroid Build Coastguard Worker using MacroAssembler::Rrx;
144*795d594fSAndroid Build Coastguard Worker
Mul(vixl32::Register rd,vixl32::Register rn,vixl32::Register rm)145*795d594fSAndroid Build Coastguard Worker void Mul(vixl32::Register rd, vixl32::Register rn, vixl32::Register rm) {
146*795d594fSAndroid Build Coastguard Worker MacroAssembler::Mul(vixl32::DontCare, rd, rn, rm);
147*795d594fSAndroid Build Coastguard Worker }
148*795d594fSAndroid Build Coastguard Worker using MacroAssembler::Mul;
149*795d594fSAndroid Build Coastguard Worker
150*795d594fSAndroid Build Coastguard Worker // TODO: Remove when MacroAssembler::Add(FlagsUpdate, Condition, Register, Register, Operand)
151*795d594fSAndroid Build Coastguard Worker // makes the right decision about 16-bit encodings.
Add(vixl32::Register rd,vixl32::Register rn,const vixl32::Operand & operand)152*795d594fSAndroid Build Coastguard Worker void Add(vixl32::Register rd, vixl32::Register rn, const vixl32::Operand& operand) {
153*795d594fSAndroid Build Coastguard Worker if (rd.Is(rn) && operand.IsPlainRegister()) {
154*795d594fSAndroid Build Coastguard Worker MacroAssembler::Add(rd, rn, operand);
155*795d594fSAndroid Build Coastguard Worker } else {
156*795d594fSAndroid Build Coastguard Worker MacroAssembler::Add(vixl32::DontCare, rd, rn, operand);
157*795d594fSAndroid Build Coastguard Worker }
158*795d594fSAndroid Build Coastguard Worker }
159*795d594fSAndroid Build Coastguard Worker using MacroAssembler::Add;
160*795d594fSAndroid Build Coastguard Worker
161*795d594fSAndroid Build Coastguard Worker // These interfaces try to use 16-bit T2 encoding of B instruction.
162*795d594fSAndroid Build Coastguard Worker void B(vixl32::Label* label);
163*795d594fSAndroid Build Coastguard Worker // For B(label), we always try to use Narrow encoding, because 16-bit T2 encoding supports
164*795d594fSAndroid Build Coastguard Worker // jumping within 2KB range. For B(cond, label), because the supported branch range is 256
165*795d594fSAndroid Build Coastguard Worker // bytes; we use the far_target hint to try to use 16-bit T1 encoding for short range jumps.
166*795d594fSAndroid Build Coastguard Worker void B(vixl32::Condition cond, vixl32::Label* label, bool is_far_target = true);
167*795d594fSAndroid Build Coastguard Worker
168*795d594fSAndroid Build Coastguard Worker // Use literal for generating double constant if it doesn't fit VMOV encoding.
Vmov(vixl32::DRegister rd,double imm)169*795d594fSAndroid Build Coastguard Worker void Vmov(vixl32::DRegister rd, double imm) {
170*795d594fSAndroid Build Coastguard Worker if (vixl::VFP::IsImmFP64(imm)) {
171*795d594fSAndroid Build Coastguard Worker MacroAssembler::Vmov(rd, imm);
172*795d594fSAndroid Build Coastguard Worker } else {
173*795d594fSAndroid Build Coastguard Worker MacroAssembler::Vldr(rd, imm);
174*795d594fSAndroid Build Coastguard Worker }
175*795d594fSAndroid Build Coastguard Worker }
176*795d594fSAndroid Build Coastguard Worker using MacroAssembler::Vmov;
177*795d594fSAndroid Build Coastguard Worker
178*795d594fSAndroid Build Coastguard Worker // TODO(b/281982421): Move the implementation of Mrrc to vixl and remove this implementation.
Mrrc(vixl32::Register r1,vixl32::Register r2,int coproc,int opc1,int crm)179*795d594fSAndroid Build Coastguard Worker void Mrrc(vixl32::Register r1, vixl32::Register r2, int coproc, int opc1, int crm) {
180*795d594fSAndroid Build Coastguard Worker // See ARM A-profile A32/T32 Instruction set architecture
181*795d594fSAndroid Build Coastguard Worker // https://developer.arm.com/documentation/ddi0597/2022-09/Base-Instructions/MRRC--Move-to-two-general-purpose-registers-from-System-register-
182*795d594fSAndroid Build Coastguard Worker CHECK(coproc == 15 || coproc == 14);
183*795d594fSAndroid Build Coastguard Worker if (IsUsingT32()) {
184*795d594fSAndroid Build Coastguard Worker uint32_t inst = (0b111011000101 << 20) |
185*795d594fSAndroid Build Coastguard Worker (r2.GetCode() << 16) |
186*795d594fSAndroid Build Coastguard Worker (r1.GetCode() << 12) |
187*795d594fSAndroid Build Coastguard Worker (coproc << 8) |
188*795d594fSAndroid Build Coastguard Worker (opc1 << 4) |
189*795d594fSAndroid Build Coastguard Worker crm;
190*795d594fSAndroid Build Coastguard Worker EmitT32_32(inst);
191*795d594fSAndroid Build Coastguard Worker } else {
192*795d594fSAndroid Build Coastguard Worker uint32_t inst = (0b000011000101 << 20) |
193*795d594fSAndroid Build Coastguard Worker (r2.GetCode() << 16) |
194*795d594fSAndroid Build Coastguard Worker (r1.GetCode() << 12) |
195*795d594fSAndroid Build Coastguard Worker (coproc << 8) |
196*795d594fSAndroid Build Coastguard Worker (opc1 << 4) |
197*795d594fSAndroid Build Coastguard Worker crm;
198*795d594fSAndroid Build Coastguard Worker EmitA32(inst);
199*795d594fSAndroid Build Coastguard Worker }
200*795d594fSAndroid Build Coastguard Worker }
201*795d594fSAndroid Build Coastguard Worker };
202*795d594fSAndroid Build Coastguard Worker
203*795d594fSAndroid Build Coastguard Worker class ArmVIXLAssembler final : public Assembler {
204*795d594fSAndroid Build Coastguard Worker private:
205*795d594fSAndroid Build Coastguard Worker class ArmException;
206*795d594fSAndroid Build Coastguard Worker public:
ArmVIXLAssembler(ArenaAllocator * allocator)207*795d594fSAndroid Build Coastguard Worker explicit ArmVIXLAssembler(ArenaAllocator* allocator)
208*795d594fSAndroid Build Coastguard Worker : Assembler(allocator) {
209*795d594fSAndroid Build Coastguard Worker // Use Thumb2 instruction set.
210*795d594fSAndroid Build Coastguard Worker vixl_masm_.UseT32();
211*795d594fSAndroid Build Coastguard Worker }
212*795d594fSAndroid Build Coastguard Worker
~ArmVIXLAssembler()213*795d594fSAndroid Build Coastguard Worker virtual ~ArmVIXLAssembler() {}
GetVIXLAssembler()214*795d594fSAndroid Build Coastguard Worker ArmVIXLMacroAssembler* GetVIXLAssembler() { return &vixl_masm_; }
215*795d594fSAndroid Build Coastguard Worker void FinalizeCode() override;
216*795d594fSAndroid Build Coastguard Worker
217*795d594fSAndroid Build Coastguard Worker // Size of generated code.
218*795d594fSAndroid Build Coastguard Worker size_t CodeSize() const override;
219*795d594fSAndroid Build Coastguard Worker const uint8_t* CodeBufferBaseAddress() const override;
220*795d594fSAndroid Build Coastguard Worker
221*795d594fSAndroid Build Coastguard Worker // Copy instructions out of assembly buffer into the given region of memory.
222*795d594fSAndroid Build Coastguard Worker void CopyInstructions(const MemoryRegion& region) override;
223*795d594fSAndroid Build Coastguard Worker
Bind(Label * label)224*795d594fSAndroid Build Coastguard Worker void Bind([[maybe_unused]] Label* label) override {
225*795d594fSAndroid Build Coastguard Worker UNIMPLEMENTED(FATAL) << "Do not use Bind(Label*) for ARM";
226*795d594fSAndroid Build Coastguard Worker }
Jump(Label * label)227*795d594fSAndroid Build Coastguard Worker void Jump([[maybe_unused]] Label* label) override {
228*795d594fSAndroid Build Coastguard Worker UNIMPLEMENTED(FATAL) << "Do not use Jump(Label*) for ARM";
229*795d594fSAndroid Build Coastguard Worker }
230*795d594fSAndroid Build Coastguard Worker
Bind(vixl::aarch32::Label * label)231*795d594fSAndroid Build Coastguard Worker void Bind(vixl::aarch32::Label* label) {
232*795d594fSAndroid Build Coastguard Worker vixl_masm_.Bind(label);
233*795d594fSAndroid Build Coastguard Worker }
Jump(vixl::aarch32::Label * label)234*795d594fSAndroid Build Coastguard Worker void Jump(vixl::aarch32::Label* label) {
235*795d594fSAndroid Build Coastguard Worker vixl_masm_.B(label);
236*795d594fSAndroid Build Coastguard Worker }
237*795d594fSAndroid Build Coastguard Worker
238*795d594fSAndroid Build Coastguard Worker //
239*795d594fSAndroid Build Coastguard Worker // Heap poisoning.
240*795d594fSAndroid Build Coastguard Worker //
241*795d594fSAndroid Build Coastguard Worker
242*795d594fSAndroid Build Coastguard Worker // Poison a heap reference contained in `reg`.
243*795d594fSAndroid Build Coastguard Worker void PoisonHeapReference(vixl32::Register reg);
244*795d594fSAndroid Build Coastguard Worker // Unpoison a heap reference contained in `reg`.
245*795d594fSAndroid Build Coastguard Worker void UnpoisonHeapReference(vixl32::Register reg);
246*795d594fSAndroid Build Coastguard Worker // Poison a heap reference contained in `reg` if heap poisoning is enabled.
247*795d594fSAndroid Build Coastguard Worker void MaybePoisonHeapReference(vixl32::Register reg);
248*795d594fSAndroid Build Coastguard Worker // Unpoison a heap reference contained in `reg` if heap poisoning is enabled.
249*795d594fSAndroid Build Coastguard Worker void MaybeUnpoisonHeapReference(vixl32::Register reg);
250*795d594fSAndroid Build Coastguard Worker
251*795d594fSAndroid Build Coastguard Worker // Emit code checking the status of the Marking Register, and aborting
252*795d594fSAndroid Build Coastguard Worker // the program if MR does not match the value stored in the art::Thread
253*795d594fSAndroid Build Coastguard Worker // object.
254*795d594fSAndroid Build Coastguard Worker //
255*795d594fSAndroid Build Coastguard Worker // Argument `temp` is used as a temporary register to generate code.
256*795d594fSAndroid Build Coastguard Worker // Argument `code` is used to identify the different occurrences of
257*795d594fSAndroid Build Coastguard Worker // MaybeGenerateMarkingRegisterCheck and is passed to the BKPT instruction.
258*795d594fSAndroid Build Coastguard Worker void GenerateMarkingRegisterCheck(vixl32::Register temp, int code = 0);
259*795d594fSAndroid Build Coastguard Worker
260*795d594fSAndroid Build Coastguard Worker void StoreToOffset(StoreOperandType type,
261*795d594fSAndroid Build Coastguard Worker vixl32::Register reg,
262*795d594fSAndroid Build Coastguard Worker vixl32::Register base,
263*795d594fSAndroid Build Coastguard Worker int32_t offset);
264*795d594fSAndroid Build Coastguard Worker void StoreSToOffset(vixl32::SRegister source, vixl32::Register base, int32_t offset);
265*795d594fSAndroid Build Coastguard Worker void StoreDToOffset(vixl32::DRegister source, vixl32::Register base, int32_t offset);
266*795d594fSAndroid Build Coastguard Worker
267*795d594fSAndroid Build Coastguard Worker void LoadImmediate(vixl32::Register dest, int32_t value);
268*795d594fSAndroid Build Coastguard Worker void LoadFromOffset(LoadOperandType type,
269*795d594fSAndroid Build Coastguard Worker vixl32::Register reg,
270*795d594fSAndroid Build Coastguard Worker vixl32::Register base,
271*795d594fSAndroid Build Coastguard Worker int32_t offset);
272*795d594fSAndroid Build Coastguard Worker void LoadSFromOffset(vixl32::SRegister reg, vixl32::Register base, int32_t offset);
273*795d594fSAndroid Build Coastguard Worker void LoadDFromOffset(vixl32::DRegister reg, vixl32::Register base, int32_t offset);
274*795d594fSAndroid Build Coastguard Worker
275*795d594fSAndroid Build Coastguard Worker void LoadRegisterList(RegList regs, size_t stack_offset);
276*795d594fSAndroid Build Coastguard Worker void StoreRegisterList(RegList regs, size_t stack_offset);
277*795d594fSAndroid Build Coastguard Worker
278*795d594fSAndroid Build Coastguard Worker bool ShifterOperandCanAlwaysHold(uint32_t immediate);
279*795d594fSAndroid Build Coastguard Worker bool ShifterOperandCanHold(Opcode opcode,
280*795d594fSAndroid Build Coastguard Worker uint32_t immediate,
281*795d594fSAndroid Build Coastguard Worker vixl::aarch32::FlagsUpdate update_flags = vixl::aarch32::DontCare);
282*795d594fSAndroid Build Coastguard Worker bool CanSplitLoadStoreOffset(int32_t allowed_offset_bits,
283*795d594fSAndroid Build Coastguard Worker int32_t offset,
284*795d594fSAndroid Build Coastguard Worker /*out*/ int32_t* add_to_base,
285*795d594fSAndroid Build Coastguard Worker /*out*/ int32_t* offset_for_load_store);
286*795d594fSAndroid Build Coastguard Worker int32_t AdjustLoadStoreOffset(int32_t allowed_offset_bits,
287*795d594fSAndroid Build Coastguard Worker vixl32::Register temp,
288*795d594fSAndroid Build Coastguard Worker vixl32::Register base,
289*795d594fSAndroid Build Coastguard Worker int32_t offset);
290*795d594fSAndroid Build Coastguard Worker int32_t GetAllowedLoadOffsetBits(LoadOperandType type);
291*795d594fSAndroid Build Coastguard Worker int32_t GetAllowedStoreOffsetBits(StoreOperandType type);
292*795d594fSAndroid Build Coastguard Worker
293*795d594fSAndroid Build Coastguard Worker void AddConstant(vixl32::Register rd, int32_t value);
294*795d594fSAndroid Build Coastguard Worker void AddConstant(vixl32::Register rd, vixl32::Register rn, int32_t value);
295*795d594fSAndroid Build Coastguard Worker void AddConstantInIt(vixl32::Register rd,
296*795d594fSAndroid Build Coastguard Worker vixl32::Register rn,
297*795d594fSAndroid Build Coastguard Worker int32_t value,
298*795d594fSAndroid Build Coastguard Worker vixl32::Condition cond = vixl32::al);
299*795d594fSAndroid Build Coastguard Worker
300*795d594fSAndroid Build Coastguard Worker template <typename T>
CreateLiteralDestroyedWithPool(T value)301*795d594fSAndroid Build Coastguard Worker vixl::aarch32::Literal<T>* CreateLiteralDestroyedWithPool(T value) {
302*795d594fSAndroid Build Coastguard Worker vixl::aarch32::Literal<T>* literal =
303*795d594fSAndroid Build Coastguard Worker new vixl::aarch32::Literal<T>(value,
304*795d594fSAndroid Build Coastguard Worker vixl32::RawLiteral::kPlacedWhenUsed,
305*795d594fSAndroid Build Coastguard Worker vixl32::RawLiteral::kDeletedOnPoolDestruction);
306*795d594fSAndroid Build Coastguard Worker return literal;
307*795d594fSAndroid Build Coastguard Worker }
308*795d594fSAndroid Build Coastguard Worker
309*795d594fSAndroid Build Coastguard Worker private:
310*795d594fSAndroid Build Coastguard Worker // VIXL assembler.
311*795d594fSAndroid Build Coastguard Worker ArmVIXLMacroAssembler vixl_masm_;
312*795d594fSAndroid Build Coastguard Worker };
313*795d594fSAndroid Build Coastguard Worker
314*795d594fSAndroid Build Coastguard Worker // Thread register declaration.
315*795d594fSAndroid Build Coastguard Worker extern const vixl32::Register tr;
316*795d594fSAndroid Build Coastguard Worker // Marking register declaration.
317*795d594fSAndroid Build Coastguard Worker extern const vixl32::Register mr;
318*795d594fSAndroid Build Coastguard Worker
319*795d594fSAndroid Build Coastguard Worker } // namespace arm
320*795d594fSAndroid Build Coastguard Worker } // namespace art
321*795d594fSAndroid Build Coastguard Worker
322*795d594fSAndroid Build Coastguard Worker #endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_VIXL_H_
323