1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2023 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 #include "code_generator_riscv64.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include "android-base/logging.h"
20*795d594fSAndroid Build Coastguard Worker #include "android-base/macros.h"
21*795d594fSAndroid Build Coastguard Worker #include "arch/riscv64/jni_frame_riscv64.h"
22*795d594fSAndroid Build Coastguard Worker #include "arch/riscv64/registers_riscv64.h"
23*795d594fSAndroid Build Coastguard Worker #include "base/arena_containers.h"
24*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
25*795d594fSAndroid Build Coastguard Worker #include "class_root-inl.h"
26*795d594fSAndroid Build Coastguard Worker #include "code_generator_utils.h"
27*795d594fSAndroid Build Coastguard Worker #include "dwarf/register.h"
28*795d594fSAndroid Build Coastguard Worker #include "gc/heap.h"
29*795d594fSAndroid Build Coastguard Worker #include "gc/space/image_space.h"
30*795d594fSAndroid Build Coastguard Worker #include "heap_poisoning.h"
31*795d594fSAndroid Build Coastguard Worker #include "intrinsics_list.h"
32*795d594fSAndroid Build Coastguard Worker #include "intrinsics_riscv64.h"
33*795d594fSAndroid Build Coastguard Worker #include "jit/profiling_info.h"
34*795d594fSAndroid Build Coastguard Worker #include "linker/linker_patch.h"
35*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
36*795d594fSAndroid Build Coastguard Worker #include "optimizing/nodes.h"
37*795d594fSAndroid Build Coastguard Worker #include "optimizing/profiling_info_builder.h"
38*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
39*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
40*795d594fSAndroid Build Coastguard Worker #include "stack_map_stream.h"
41*795d594fSAndroid Build Coastguard Worker #include "trace.h"
42*795d594fSAndroid Build Coastguard Worker #include "utils/label.h"
43*795d594fSAndroid Build Coastguard Worker #include "utils/riscv64/assembler_riscv64.h"
44*795d594fSAndroid Build Coastguard Worker #include "utils/stack_checks.h"
45*795d594fSAndroid Build Coastguard Worker
46*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
47*795d594fSAndroid Build Coastguard Worker namespace riscv64 {
48*795d594fSAndroid Build Coastguard Worker
49*795d594fSAndroid Build Coastguard Worker // Placeholder values embedded in instructions, patched at link time.
50*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kLinkTimeOffsetPlaceholderHigh = 0x12345;
51*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kLinkTimeOffsetPlaceholderLow = 0x678;
52*795d594fSAndroid Build Coastguard Worker
53*795d594fSAndroid Build Coastguard Worker // Compare-and-jump packed switch generates approx. 3 + 1.5 * N 32-bit
54*795d594fSAndroid Build Coastguard Worker // instructions for N cases.
55*795d594fSAndroid Build Coastguard Worker // Table-based packed switch generates approx. 10 32-bit instructions
56*795d594fSAndroid Build Coastguard Worker // and N 32-bit data words for N cases.
57*795d594fSAndroid Build Coastguard Worker // We switch to the table-based method starting with 6 entries.
58*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kPackedSwitchCompareJumpThreshold = 6;
59*795d594fSAndroid Build Coastguard Worker
60*795d594fSAndroid Build Coastguard Worker static constexpr XRegister kCoreCalleeSaves[] = {
61*795d594fSAndroid Build Coastguard Worker // S1(TR) is excluded as the ART thread register.
62*795d594fSAndroid Build Coastguard Worker S0, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, RA
63*795d594fSAndroid Build Coastguard Worker };
64*795d594fSAndroid Build Coastguard Worker
65*795d594fSAndroid Build Coastguard Worker static constexpr FRegister kFpuCalleeSaves[] = {
66*795d594fSAndroid Build Coastguard Worker FS0, FS1, FS2, FS3, FS4, FS5, FS6, FS7, FS8, FS9, FS10, FS11
67*795d594fSAndroid Build Coastguard Worker };
68*795d594fSAndroid Build Coastguard Worker
69*795d594fSAndroid Build Coastguard Worker #define QUICK_ENTRY_POINT(x) QUICK_ENTRYPOINT_OFFSET(kRiscv64PointerSize, x).Int32Value()
70*795d594fSAndroid Build Coastguard Worker
RegisterOrZeroBitPatternLocation(HInstruction * instruction)71*795d594fSAndroid Build Coastguard Worker Location RegisterOrZeroBitPatternLocation(HInstruction* instruction) {
72*795d594fSAndroid Build Coastguard Worker DCHECK(!DataType::IsFloatingPointType(instruction->GetType()));
73*795d594fSAndroid Build Coastguard Worker return IsZeroBitPattern(instruction)
74*795d594fSAndroid Build Coastguard Worker ? Location::ConstantLocation(instruction)
75*795d594fSAndroid Build Coastguard Worker : Location::RequiresRegister();
76*795d594fSAndroid Build Coastguard Worker }
77*795d594fSAndroid Build Coastguard Worker
FpuRegisterOrZeroBitPatternLocation(HInstruction * instruction)78*795d594fSAndroid Build Coastguard Worker Location FpuRegisterOrZeroBitPatternLocation(HInstruction* instruction) {
79*795d594fSAndroid Build Coastguard Worker DCHECK(DataType::IsFloatingPointType(instruction->GetType()));
80*795d594fSAndroid Build Coastguard Worker return IsZeroBitPattern(instruction)
81*795d594fSAndroid Build Coastguard Worker ? Location::ConstantLocation(instruction)
82*795d594fSAndroid Build Coastguard Worker : Location::RequiresFpuRegister();
83*795d594fSAndroid Build Coastguard Worker }
84*795d594fSAndroid Build Coastguard Worker
InputXRegisterOrZero(Location location)85*795d594fSAndroid Build Coastguard Worker XRegister InputXRegisterOrZero(Location location) {
86*795d594fSAndroid Build Coastguard Worker if (location.IsConstant()) {
87*795d594fSAndroid Build Coastguard Worker DCHECK(location.GetConstant()->IsZeroBitPattern());
88*795d594fSAndroid Build Coastguard Worker return Zero;
89*795d594fSAndroid Build Coastguard Worker } else {
90*795d594fSAndroid Build Coastguard Worker return location.AsRegister<XRegister>();
91*795d594fSAndroid Build Coastguard Worker }
92*795d594fSAndroid Build Coastguard Worker }
93*795d594fSAndroid Build Coastguard Worker
ValueLocationForStore(HInstruction * value)94*795d594fSAndroid Build Coastguard Worker Location ValueLocationForStore(HInstruction* value) {
95*795d594fSAndroid Build Coastguard Worker if (IsZeroBitPattern(value)) {
96*795d594fSAndroid Build Coastguard Worker return Location::ConstantLocation(value);
97*795d594fSAndroid Build Coastguard Worker } else if (DataType::IsFloatingPointType(value->GetType())) {
98*795d594fSAndroid Build Coastguard Worker return Location::RequiresFpuRegister();
99*795d594fSAndroid Build Coastguard Worker } else {
100*795d594fSAndroid Build Coastguard Worker return Location::RequiresRegister();
101*795d594fSAndroid Build Coastguard Worker }
102*795d594fSAndroid Build Coastguard Worker }
103*795d594fSAndroid Build Coastguard Worker
Riscv64ReturnLocation(DataType::Type return_type)104*795d594fSAndroid Build Coastguard Worker Location Riscv64ReturnLocation(DataType::Type return_type) {
105*795d594fSAndroid Build Coastguard Worker switch (return_type) {
106*795d594fSAndroid Build Coastguard Worker case DataType::Type::kBool:
107*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint8:
108*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt8:
109*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint16:
110*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt16:
111*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint32:
112*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
113*795d594fSAndroid Build Coastguard Worker case DataType::Type::kReference:
114*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint64:
115*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
116*795d594fSAndroid Build Coastguard Worker return Location::RegisterLocation(A0);
117*795d594fSAndroid Build Coastguard Worker
118*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
119*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
120*795d594fSAndroid Build Coastguard Worker return Location::FpuRegisterLocation(FA0);
121*795d594fSAndroid Build Coastguard Worker
122*795d594fSAndroid Build Coastguard Worker case DataType::Type::kVoid:
123*795d594fSAndroid Build Coastguard Worker return Location::NoLocation();
124*795d594fSAndroid Build Coastguard Worker }
125*795d594fSAndroid Build Coastguard Worker }
126*795d594fSAndroid Build Coastguard Worker
OneRegInReferenceOutSaveEverythingCallerSaves()127*795d594fSAndroid Build Coastguard Worker static RegisterSet OneRegInReferenceOutSaveEverythingCallerSaves() {
128*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
129*795d594fSAndroid Build Coastguard Worker RegisterSet caller_saves = RegisterSet::Empty();
130*795d594fSAndroid Build Coastguard Worker caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
131*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(
132*795d594fSAndroid Build Coastguard Worker calling_convention.GetRegisterAt(0),
133*795d594fSAndroid Build Coastguard Worker calling_convention.GetReturnLocation(DataType::Type::kReference).AsRegister<XRegister>());
134*795d594fSAndroid Build Coastguard Worker return caller_saves;
135*795d594fSAndroid Build Coastguard Worker }
136*795d594fSAndroid Build Coastguard Worker
137*795d594fSAndroid Build Coastguard Worker template <ClassStatus kStatus>
ShiftedSignExtendedClassStatusValue()138*795d594fSAndroid Build Coastguard Worker static constexpr int64_t ShiftedSignExtendedClassStatusValue() {
139*795d594fSAndroid Build Coastguard Worker // This is used only for status values that have the highest bit set.
140*795d594fSAndroid Build Coastguard Worker static_assert(CLZ(enum_cast<uint32_t>(kStatus)) == kClassStatusLsbPosition);
141*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kShiftedStatusValue = enum_cast<uint32_t>(kStatus) << kClassStatusLsbPosition;
142*795d594fSAndroid Build Coastguard Worker static_assert(kShiftedStatusValue >= 0x80000000u);
143*795d594fSAndroid Build Coastguard Worker return static_cast<int64_t>(kShiftedStatusValue) - (INT64_C(1) << 32);
144*795d594fSAndroid Build Coastguard Worker }
145*795d594fSAndroid Build Coastguard Worker
146*795d594fSAndroid Build Coastguard Worker // Split a 64-bit address used by JIT to the nearest 4KiB-aligned base address and a 12-bit
147*795d594fSAndroid Build Coastguard Worker // signed offset. It is usually cheaper to materialize the aligned address than the full address.
SplitJitAddress(uint64_t address)148*795d594fSAndroid Build Coastguard Worker std::pair<uint64_t, int32_t> SplitJitAddress(uint64_t address) {
149*795d594fSAndroid Build Coastguard Worker uint64_t bits0_11 = address & UINT64_C(0xfff);
150*795d594fSAndroid Build Coastguard Worker uint64_t bit11 = address & UINT64_C(0x800);
151*795d594fSAndroid Build Coastguard Worker // Round the address to nearest 4KiB address because the `imm12` has range [-0x800, 0x800).
152*795d594fSAndroid Build Coastguard Worker uint64_t base_address = (address & ~UINT64_C(0xfff)) + (bit11 << 1);
153*795d594fSAndroid Build Coastguard Worker int32_t imm12 = dchecked_integral_cast<int32_t>(bits0_11) -
154*795d594fSAndroid Build Coastguard Worker dchecked_integral_cast<int32_t>(bit11 << 1);
155*795d594fSAndroid Build Coastguard Worker return {base_address, imm12};
156*795d594fSAndroid Build Coastguard Worker }
157*795d594fSAndroid Build Coastguard Worker
ReadBarrierMarkEntrypointOffset(Location ref)158*795d594fSAndroid Build Coastguard Worker int32_t ReadBarrierMarkEntrypointOffset(Location ref) {
159*795d594fSAndroid Build Coastguard Worker DCHECK(ref.IsRegister());
160*795d594fSAndroid Build Coastguard Worker int reg = ref.reg();
161*795d594fSAndroid Build Coastguard Worker DCHECK(T0 <= reg && reg <= T6 && reg != TR) << reg;
162*795d594fSAndroid Build Coastguard Worker // Note: Entrypoints for registers X30 (T5) and X31 (T6) are stored in entries
163*795d594fSAndroid Build Coastguard Worker // for X0 (Zero) and X1 (RA) because these are not valid registers for marking
164*795d594fSAndroid Build Coastguard Worker // and we currently have slots only up to register 29.
165*795d594fSAndroid Build Coastguard Worker int entry_point_number = (reg >= 30) ? reg - 30 : reg;
166*795d594fSAndroid Build Coastguard Worker return Thread::ReadBarrierMarkEntryPointsOffset<kRiscv64PointerSize>(entry_point_number);
167*795d594fSAndroid Build Coastguard Worker }
168*795d594fSAndroid Build Coastguard Worker
GetReturnLocation(DataType::Type return_type)169*795d594fSAndroid Build Coastguard Worker Location InvokeRuntimeCallingConvention::GetReturnLocation(DataType::Type return_type) {
170*795d594fSAndroid Build Coastguard Worker return Riscv64ReturnLocation(return_type);
171*795d594fSAndroid Build Coastguard Worker }
172*795d594fSAndroid Build Coastguard Worker
GetReturnLocation(DataType::Type type) const173*795d594fSAndroid Build Coastguard Worker Location InvokeDexCallingConventionVisitorRISCV64::GetReturnLocation(DataType::Type type) const {
174*795d594fSAndroid Build Coastguard Worker return Riscv64ReturnLocation(type);
175*795d594fSAndroid Build Coastguard Worker }
176*795d594fSAndroid Build Coastguard Worker
GetMethodLocation() const177*795d594fSAndroid Build Coastguard Worker Location InvokeDexCallingConventionVisitorRISCV64::GetMethodLocation() const {
178*795d594fSAndroid Build Coastguard Worker return Location::RegisterLocation(kArtMethodRegister);
179*795d594fSAndroid Build Coastguard Worker }
180*795d594fSAndroid Build Coastguard Worker
GetNextLocation(DataType::Type type)181*795d594fSAndroid Build Coastguard Worker Location InvokeDexCallingConventionVisitorRISCV64::GetNextLocation(DataType::Type type) {
182*795d594fSAndroid Build Coastguard Worker Location next_location;
183*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kVoid) {
184*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected parameter type " << type;
185*795d594fSAndroid Build Coastguard Worker }
186*795d594fSAndroid Build Coastguard Worker
187*795d594fSAndroid Build Coastguard Worker // Note: Unlike the RISC-V C/C++ calling convention, managed ABI does not use
188*795d594fSAndroid Build Coastguard Worker // GPRs to pass FP args when we run out of FPRs.
189*795d594fSAndroid Build Coastguard Worker if (DataType::IsFloatingPointType(type) &&
190*795d594fSAndroid Build Coastguard Worker float_index_ < calling_convention.GetNumberOfFpuRegisters()) {
191*795d594fSAndroid Build Coastguard Worker next_location =
192*795d594fSAndroid Build Coastguard Worker Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(float_index_++));
193*795d594fSAndroid Build Coastguard Worker } else if (!DataType::IsFloatingPointType(type) &&
194*795d594fSAndroid Build Coastguard Worker (gp_index_ < calling_convention.GetNumberOfRegisters())) {
195*795d594fSAndroid Build Coastguard Worker next_location = Location::RegisterLocation(calling_convention.GetRegisterAt(gp_index_++));
196*795d594fSAndroid Build Coastguard Worker } else {
197*795d594fSAndroid Build Coastguard Worker size_t stack_offset = calling_convention.GetStackOffsetOf(stack_index_);
198*795d594fSAndroid Build Coastguard Worker next_location = DataType::Is64BitType(type) ? Location::DoubleStackSlot(stack_offset) :
199*795d594fSAndroid Build Coastguard Worker Location::StackSlot(stack_offset);
200*795d594fSAndroid Build Coastguard Worker }
201*795d594fSAndroid Build Coastguard Worker
202*795d594fSAndroid Build Coastguard Worker // Space on the stack is reserved for all arguments.
203*795d594fSAndroid Build Coastguard Worker stack_index_ += DataType::Is64BitType(type) ? 2 : 1;
204*795d594fSAndroid Build Coastguard Worker
205*795d594fSAndroid Build Coastguard Worker return next_location;
206*795d594fSAndroid Build Coastguard Worker }
207*795d594fSAndroid Build Coastguard Worker
GetNextLocation(DataType::Type type)208*795d594fSAndroid Build Coastguard Worker Location CriticalNativeCallingConventionVisitorRiscv64::GetNextLocation(DataType::Type type) {
209*795d594fSAndroid Build Coastguard Worker DCHECK_NE(type, DataType::Type::kReference);
210*795d594fSAndroid Build Coastguard Worker
211*795d594fSAndroid Build Coastguard Worker Location location = Location::NoLocation();
212*795d594fSAndroid Build Coastguard Worker if (DataType::IsFloatingPointType(type)) {
213*795d594fSAndroid Build Coastguard Worker if (fpr_index_ < kParameterFpuRegistersLength) {
214*795d594fSAndroid Build Coastguard Worker location = Location::FpuRegisterLocation(kParameterFpuRegisters[fpr_index_]);
215*795d594fSAndroid Build Coastguard Worker ++fpr_index_;
216*795d594fSAndroid Build Coastguard Worker } else {
217*795d594fSAndroid Build Coastguard Worker // Native ABI allows passing excessive FP args in GPRs. This is facilitated by
218*795d594fSAndroid Build Coastguard Worker // inserting fake conversion intrinsic calls (`Double.doubleToRawLongBits()`
219*795d594fSAndroid Build Coastguard Worker // or `Float.floatToRawIntBits()`) by `CriticalNativeAbiFixupRiscv64`.
220*795d594fSAndroid Build Coastguard Worker // Remaining FP args shall be passed on the stack.
221*795d594fSAndroid Build Coastguard Worker CHECK_EQ(gpr_index_, kRuntimeParameterCoreRegistersLength);
222*795d594fSAndroid Build Coastguard Worker }
223*795d594fSAndroid Build Coastguard Worker } else {
224*795d594fSAndroid Build Coastguard Worker // Native ABI uses the same core registers as a runtime call.
225*795d594fSAndroid Build Coastguard Worker if (gpr_index_ < kRuntimeParameterCoreRegistersLength) {
226*795d594fSAndroid Build Coastguard Worker location = Location::RegisterLocation(kRuntimeParameterCoreRegisters[gpr_index_]);
227*795d594fSAndroid Build Coastguard Worker ++gpr_index_;
228*795d594fSAndroid Build Coastguard Worker }
229*795d594fSAndroid Build Coastguard Worker }
230*795d594fSAndroid Build Coastguard Worker if (location.IsInvalid()) {
231*795d594fSAndroid Build Coastguard Worker // Only a `float` gets a single slot. Integral args need to be sign-extended to 64 bits.
232*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kFloat32) {
233*795d594fSAndroid Build Coastguard Worker location = Location::StackSlot(stack_offset_);
234*795d594fSAndroid Build Coastguard Worker } else {
235*795d594fSAndroid Build Coastguard Worker location = Location::DoubleStackSlot(stack_offset_);
236*795d594fSAndroid Build Coastguard Worker }
237*795d594fSAndroid Build Coastguard Worker stack_offset_ += kFramePointerSize;
238*795d594fSAndroid Build Coastguard Worker
239*795d594fSAndroid Build Coastguard Worker if (for_register_allocation_) {
240*795d594fSAndroid Build Coastguard Worker location = Location::Any();
241*795d594fSAndroid Build Coastguard Worker }
242*795d594fSAndroid Build Coastguard Worker }
243*795d594fSAndroid Build Coastguard Worker return location;
244*795d594fSAndroid Build Coastguard Worker }
245*795d594fSAndroid Build Coastguard Worker
GetReturnLocation(DataType::Type type) const246*795d594fSAndroid Build Coastguard Worker Location CriticalNativeCallingConventionVisitorRiscv64::GetReturnLocation(
247*795d594fSAndroid Build Coastguard Worker DataType::Type type) const {
248*795d594fSAndroid Build Coastguard Worker // The result is returned the same way in native ABI and managed ABI. No result conversion is
249*795d594fSAndroid Build Coastguard Worker // needed, see comments in `Riscv64JniCallingConvention::RequiresSmallResultTypeExtension()`.
250*795d594fSAndroid Build Coastguard Worker InvokeDexCallingConventionVisitorRISCV64 dex_calling_convention;
251*795d594fSAndroid Build Coastguard Worker return dex_calling_convention.GetReturnLocation(type);
252*795d594fSAndroid Build Coastguard Worker }
253*795d594fSAndroid Build Coastguard Worker
GetMethodLocation() const254*795d594fSAndroid Build Coastguard Worker Location CriticalNativeCallingConventionVisitorRiscv64::GetMethodLocation() const {
255*795d594fSAndroid Build Coastguard Worker // Pass the method in the hidden argument T0.
256*795d594fSAndroid Build Coastguard Worker return Location::RegisterLocation(T0);
257*795d594fSAndroid Build Coastguard Worker }
258*795d594fSAndroid Build Coastguard Worker
259*795d594fSAndroid Build Coastguard Worker #define __ down_cast<CodeGeneratorRISCV64*>(codegen)->GetAssembler()-> // NOLINT
260*795d594fSAndroid Build Coastguard Worker
HandleInvoke(HInvoke * instruction)261*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::HandleInvoke(HInvoke* instruction) {
262*795d594fSAndroid Build Coastguard Worker InvokeDexCallingConventionVisitorRISCV64 calling_convention_visitor;
263*795d594fSAndroid Build Coastguard Worker CodeGenerator::CreateCommonInvokeLocationSummary(instruction, &calling_convention_visitor);
264*795d594fSAndroid Build Coastguard Worker }
265*795d594fSAndroid Build Coastguard Worker
266*795d594fSAndroid Build Coastguard Worker class CompileOptimizedSlowPathRISCV64 : public SlowPathCodeRISCV64 {
267*795d594fSAndroid Build Coastguard Worker public:
CompileOptimizedSlowPathRISCV64(HSuspendCheck * suspend_check,XRegister base,int32_t imm12)268*795d594fSAndroid Build Coastguard Worker CompileOptimizedSlowPathRISCV64(HSuspendCheck* suspend_check, XRegister base, int32_t imm12)
269*795d594fSAndroid Build Coastguard Worker : SlowPathCodeRISCV64(suspend_check),
270*795d594fSAndroid Build Coastguard Worker base_(base),
271*795d594fSAndroid Build Coastguard Worker imm12_(imm12) {}
272*795d594fSAndroid Build Coastguard Worker
EmitNativeCode(CodeGenerator * codegen)273*795d594fSAndroid Build Coastguard Worker void EmitNativeCode(CodeGenerator* codegen) override {
274*795d594fSAndroid Build Coastguard Worker uint32_t entrypoint_offset =
275*795d594fSAndroid Build Coastguard Worker GetThreadOffset<kRiscv64PointerSize>(kQuickCompileOptimized).Int32Value();
276*795d594fSAndroid Build Coastguard Worker __ Bind(GetEntryLabel());
277*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64* riscv64_codegen = down_cast<CodeGeneratorRISCV64*>(codegen);
278*795d594fSAndroid Build Coastguard Worker riscv64::ScratchRegisterScope srs(riscv64_codegen->GetAssembler());
279*795d594fSAndroid Build Coastguard Worker XRegister counter = srs.AllocateXRegister();
280*795d594fSAndroid Build Coastguard Worker __ LoadConst32(counter, ProfilingInfo::GetOptimizeThreshold());
281*795d594fSAndroid Build Coastguard Worker __ Sh(counter, base_, imm12_);
282*795d594fSAndroid Build Coastguard Worker if (instruction_ != nullptr) {
283*795d594fSAndroid Build Coastguard Worker // Only saves live vector regs for SIMD.
284*795d594fSAndroid Build Coastguard Worker SaveLiveRegisters(codegen, instruction_->GetLocations());
285*795d594fSAndroid Build Coastguard Worker }
286*795d594fSAndroid Build Coastguard Worker __ Loadd(RA, TR, entrypoint_offset);
287*795d594fSAndroid Build Coastguard Worker // Note: we don't record the call here (and therefore don't generate a stack
288*795d594fSAndroid Build Coastguard Worker // map), as the entrypoint should never be suspended.
289*795d594fSAndroid Build Coastguard Worker __ Jalr(RA);
290*795d594fSAndroid Build Coastguard Worker if (instruction_ != nullptr) {
291*795d594fSAndroid Build Coastguard Worker // Only restores live vector regs for SIMD.
292*795d594fSAndroid Build Coastguard Worker RestoreLiveRegisters(codegen, instruction_->GetLocations());
293*795d594fSAndroid Build Coastguard Worker }
294*795d594fSAndroid Build Coastguard Worker __ J(GetExitLabel());
295*795d594fSAndroid Build Coastguard Worker }
296*795d594fSAndroid Build Coastguard Worker
GetDescription() const297*795d594fSAndroid Build Coastguard Worker const char* GetDescription() const override { return "CompileOptimizedSlowPath"; }
298*795d594fSAndroid Build Coastguard Worker
299*795d594fSAndroid Build Coastguard Worker private:
300*795d594fSAndroid Build Coastguard Worker XRegister base_;
301*795d594fSAndroid Build Coastguard Worker const int32_t imm12_;
302*795d594fSAndroid Build Coastguard Worker
303*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(CompileOptimizedSlowPathRISCV64);
304*795d594fSAndroid Build Coastguard Worker };
305*795d594fSAndroid Build Coastguard Worker
306*795d594fSAndroid Build Coastguard Worker class SuspendCheckSlowPathRISCV64 : public SlowPathCodeRISCV64 {
307*795d594fSAndroid Build Coastguard Worker public:
SuspendCheckSlowPathRISCV64(HSuspendCheck * instruction,HBasicBlock * successor)308*795d594fSAndroid Build Coastguard Worker SuspendCheckSlowPathRISCV64(HSuspendCheck* instruction, HBasicBlock* successor)
309*795d594fSAndroid Build Coastguard Worker : SlowPathCodeRISCV64(instruction), successor_(successor) {}
310*795d594fSAndroid Build Coastguard Worker
EmitNativeCode(CodeGenerator * codegen)311*795d594fSAndroid Build Coastguard Worker void EmitNativeCode(CodeGenerator* codegen) override {
312*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction_->GetLocations();
313*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64* riscv64_codegen = down_cast<CodeGeneratorRISCV64*>(codegen);
314*795d594fSAndroid Build Coastguard Worker __ Bind(GetEntryLabel());
315*795d594fSAndroid Build Coastguard Worker SaveLiveRegisters(codegen, locations); // Only saves live vector registers for SIMD.
316*795d594fSAndroid Build Coastguard Worker riscv64_codegen->InvokeRuntime(kQuickTestSuspend, instruction_, instruction_->GetDexPc(), this);
317*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickTestSuspend, void, void>();
318*795d594fSAndroid Build Coastguard Worker RestoreLiveRegisters(codegen, locations); // Only restores live vector registers for SIMD.
319*795d594fSAndroid Build Coastguard Worker if (successor_ == nullptr) {
320*795d594fSAndroid Build Coastguard Worker __ J(GetReturnLabel());
321*795d594fSAndroid Build Coastguard Worker } else {
322*795d594fSAndroid Build Coastguard Worker __ J(riscv64_codegen->GetLabelOf(successor_));
323*795d594fSAndroid Build Coastguard Worker }
324*795d594fSAndroid Build Coastguard Worker }
325*795d594fSAndroid Build Coastguard Worker
GetReturnLabel()326*795d594fSAndroid Build Coastguard Worker Riscv64Label* GetReturnLabel() {
327*795d594fSAndroid Build Coastguard Worker DCHECK(successor_ == nullptr);
328*795d594fSAndroid Build Coastguard Worker return &return_label_;
329*795d594fSAndroid Build Coastguard Worker }
330*795d594fSAndroid Build Coastguard Worker
GetDescription() const331*795d594fSAndroid Build Coastguard Worker const char* GetDescription() const override { return "SuspendCheckSlowPathRISCV64"; }
332*795d594fSAndroid Build Coastguard Worker
GetSuccessor() const333*795d594fSAndroid Build Coastguard Worker HBasicBlock* GetSuccessor() const { return successor_; }
334*795d594fSAndroid Build Coastguard Worker
335*795d594fSAndroid Build Coastguard Worker private:
336*795d594fSAndroid Build Coastguard Worker // If not null, the block to branch to after the suspend check.
337*795d594fSAndroid Build Coastguard Worker HBasicBlock* const successor_;
338*795d594fSAndroid Build Coastguard Worker
339*795d594fSAndroid Build Coastguard Worker // If `successor_` is null, the label to branch to after the suspend check.
340*795d594fSAndroid Build Coastguard Worker Riscv64Label return_label_;
341*795d594fSAndroid Build Coastguard Worker
342*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(SuspendCheckSlowPathRISCV64);
343*795d594fSAndroid Build Coastguard Worker };
344*795d594fSAndroid Build Coastguard Worker
345*795d594fSAndroid Build Coastguard Worker class NullCheckSlowPathRISCV64 : public SlowPathCodeRISCV64 {
346*795d594fSAndroid Build Coastguard Worker public:
NullCheckSlowPathRISCV64(HNullCheck * instr)347*795d594fSAndroid Build Coastguard Worker explicit NullCheckSlowPathRISCV64(HNullCheck* instr) : SlowPathCodeRISCV64(instr) {}
348*795d594fSAndroid Build Coastguard Worker
EmitNativeCode(CodeGenerator * codegen)349*795d594fSAndroid Build Coastguard Worker void EmitNativeCode(CodeGenerator* codegen) override {
350*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64* riscv64_codegen = down_cast<CodeGeneratorRISCV64*>(codegen);
351*795d594fSAndroid Build Coastguard Worker __ Bind(GetEntryLabel());
352*795d594fSAndroid Build Coastguard Worker if (instruction_->CanThrowIntoCatchBlock()) {
353*795d594fSAndroid Build Coastguard Worker // Live registers will be restored in the catch block if caught.
354*795d594fSAndroid Build Coastguard Worker SaveLiveRegisters(codegen, instruction_->GetLocations());
355*795d594fSAndroid Build Coastguard Worker }
356*795d594fSAndroid Build Coastguard Worker riscv64_codegen->InvokeRuntime(
357*795d594fSAndroid Build Coastguard Worker kQuickThrowNullPointer, instruction_, instruction_->GetDexPc(), this);
358*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickThrowNullPointer, void, void>();
359*795d594fSAndroid Build Coastguard Worker }
360*795d594fSAndroid Build Coastguard Worker
IsFatal() const361*795d594fSAndroid Build Coastguard Worker bool IsFatal() const override { return true; }
362*795d594fSAndroid Build Coastguard Worker
GetDescription() const363*795d594fSAndroid Build Coastguard Worker const char* GetDescription() const override { return "NullCheckSlowPathRISCV64"; }
364*795d594fSAndroid Build Coastguard Worker
365*795d594fSAndroid Build Coastguard Worker private:
366*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(NullCheckSlowPathRISCV64);
367*795d594fSAndroid Build Coastguard Worker };
368*795d594fSAndroid Build Coastguard Worker
369*795d594fSAndroid Build Coastguard Worker class BoundsCheckSlowPathRISCV64 : public SlowPathCodeRISCV64 {
370*795d594fSAndroid Build Coastguard Worker public:
BoundsCheckSlowPathRISCV64(HBoundsCheck * instruction)371*795d594fSAndroid Build Coastguard Worker explicit BoundsCheckSlowPathRISCV64(HBoundsCheck* instruction)
372*795d594fSAndroid Build Coastguard Worker : SlowPathCodeRISCV64(instruction) {}
373*795d594fSAndroid Build Coastguard Worker
EmitNativeCode(CodeGenerator * codegen)374*795d594fSAndroid Build Coastguard Worker void EmitNativeCode(CodeGenerator* codegen) override {
375*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction_->GetLocations();
376*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64* riscv64_codegen = down_cast<CodeGeneratorRISCV64*>(codegen);
377*795d594fSAndroid Build Coastguard Worker __ Bind(GetEntryLabel());
378*795d594fSAndroid Build Coastguard Worker if (instruction_->CanThrowIntoCatchBlock()) {
379*795d594fSAndroid Build Coastguard Worker // Live registers will be restored in the catch block if caught.
380*795d594fSAndroid Build Coastguard Worker SaveLiveRegisters(codegen, instruction_->GetLocations());
381*795d594fSAndroid Build Coastguard Worker }
382*795d594fSAndroid Build Coastguard Worker // We're moving two locations to locations that could overlap, so we need a parallel
383*795d594fSAndroid Build Coastguard Worker // move resolver.
384*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
385*795d594fSAndroid Build Coastguard Worker codegen->EmitParallelMoves(locations->InAt(0),
386*795d594fSAndroid Build Coastguard Worker Location::RegisterLocation(calling_convention.GetRegisterAt(0)),
387*795d594fSAndroid Build Coastguard Worker DataType::Type::kInt32,
388*795d594fSAndroid Build Coastguard Worker locations->InAt(1),
389*795d594fSAndroid Build Coastguard Worker Location::RegisterLocation(calling_convention.GetRegisterAt(1)),
390*795d594fSAndroid Build Coastguard Worker DataType::Type::kInt32);
391*795d594fSAndroid Build Coastguard Worker QuickEntrypointEnum entrypoint = instruction_->AsBoundsCheck()->IsStringCharAt() ?
392*795d594fSAndroid Build Coastguard Worker kQuickThrowStringBounds :
393*795d594fSAndroid Build Coastguard Worker kQuickThrowArrayBounds;
394*795d594fSAndroid Build Coastguard Worker riscv64_codegen->InvokeRuntime(entrypoint, instruction_, instruction_->GetDexPc(), this);
395*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickThrowStringBounds, void, int32_t, int32_t>();
396*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickThrowArrayBounds, void, int32_t, int32_t>();
397*795d594fSAndroid Build Coastguard Worker }
398*795d594fSAndroid Build Coastguard Worker
IsFatal() const399*795d594fSAndroid Build Coastguard Worker bool IsFatal() const override { return true; }
400*795d594fSAndroid Build Coastguard Worker
GetDescription() const401*795d594fSAndroid Build Coastguard Worker const char* GetDescription() const override { return "BoundsCheckSlowPathRISCV64"; }
402*795d594fSAndroid Build Coastguard Worker
403*795d594fSAndroid Build Coastguard Worker private:
404*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(BoundsCheckSlowPathRISCV64);
405*795d594fSAndroid Build Coastguard Worker };
406*795d594fSAndroid Build Coastguard Worker
407*795d594fSAndroid Build Coastguard Worker class LoadClassSlowPathRISCV64 : public SlowPathCodeRISCV64 {
408*795d594fSAndroid Build Coastguard Worker public:
LoadClassSlowPathRISCV64(HLoadClass * cls,HInstruction * at)409*795d594fSAndroid Build Coastguard Worker LoadClassSlowPathRISCV64(HLoadClass* cls, HInstruction* at) : SlowPathCodeRISCV64(at), cls_(cls) {
410*795d594fSAndroid Build Coastguard Worker DCHECK(at->IsLoadClass() || at->IsClinitCheck());
411*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(instruction_->IsLoadClass(), cls_ == instruction_);
412*795d594fSAndroid Build Coastguard Worker }
413*795d594fSAndroid Build Coastguard Worker
EmitNativeCode(CodeGenerator * codegen)414*795d594fSAndroid Build Coastguard Worker void EmitNativeCode(CodeGenerator* codegen) override {
415*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction_->GetLocations();
416*795d594fSAndroid Build Coastguard Worker Location out = locations->Out();
417*795d594fSAndroid Build Coastguard Worker const uint32_t dex_pc = instruction_->GetDexPc();
418*795d594fSAndroid Build Coastguard Worker bool must_resolve_type = instruction_->IsLoadClass() && cls_->MustResolveTypeOnSlowPath();
419*795d594fSAndroid Build Coastguard Worker bool must_do_clinit = instruction_->IsClinitCheck() || cls_->MustGenerateClinitCheck();
420*795d594fSAndroid Build Coastguard Worker
421*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64* riscv64_codegen = down_cast<CodeGeneratorRISCV64*>(codegen);
422*795d594fSAndroid Build Coastguard Worker __ Bind(GetEntryLabel());
423*795d594fSAndroid Build Coastguard Worker SaveLiveRegisters(codegen, locations);
424*795d594fSAndroid Build Coastguard Worker
425*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
426*795d594fSAndroid Build Coastguard Worker if (must_resolve_type) {
427*795d594fSAndroid Build Coastguard Worker DCHECK(IsSameDexFile(cls_->GetDexFile(), riscv64_codegen->GetGraph()->GetDexFile()) ||
428*795d594fSAndroid Build Coastguard Worker riscv64_codegen->GetCompilerOptions().WithinOatFile(&cls_->GetDexFile()) ||
429*795d594fSAndroid Build Coastguard Worker ContainsElement(Runtime::Current()->GetClassLinker()->GetBootClassPath(),
430*795d594fSAndroid Build Coastguard Worker &cls_->GetDexFile()));
431*795d594fSAndroid Build Coastguard Worker dex::TypeIndex type_index = cls_->GetTypeIndex();
432*795d594fSAndroid Build Coastguard Worker __ LoadConst32(calling_convention.GetRegisterAt(0), type_index.index_);
433*795d594fSAndroid Build Coastguard Worker if (cls_->NeedsAccessCheck()) {
434*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickResolveTypeAndVerifyAccess, void*, uint32_t>();
435*795d594fSAndroid Build Coastguard Worker riscv64_codegen->InvokeRuntime(
436*795d594fSAndroid Build Coastguard Worker kQuickResolveTypeAndVerifyAccess, instruction_, dex_pc, this);
437*795d594fSAndroid Build Coastguard Worker } else {
438*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>();
439*795d594fSAndroid Build Coastguard Worker riscv64_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this);
440*795d594fSAndroid Build Coastguard Worker }
441*795d594fSAndroid Build Coastguard Worker // If we also must_do_clinit, the resolved type is now in the correct register.
442*795d594fSAndroid Build Coastguard Worker } else {
443*795d594fSAndroid Build Coastguard Worker DCHECK(must_do_clinit);
444*795d594fSAndroid Build Coastguard Worker Location source = instruction_->IsLoadClass() ? out : locations->InAt(0);
445*795d594fSAndroid Build Coastguard Worker riscv64_codegen->MoveLocation(
446*795d594fSAndroid Build Coastguard Worker Location::RegisterLocation(calling_convention.GetRegisterAt(0)), source, cls_->GetType());
447*795d594fSAndroid Build Coastguard Worker }
448*795d594fSAndroid Build Coastguard Worker if (must_do_clinit) {
449*795d594fSAndroid Build Coastguard Worker riscv64_codegen->InvokeRuntime(kQuickInitializeStaticStorage, instruction_, dex_pc, this);
450*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickInitializeStaticStorage, void*, mirror::Class*>();
451*795d594fSAndroid Build Coastguard Worker }
452*795d594fSAndroid Build Coastguard Worker
453*795d594fSAndroid Build Coastguard Worker // Move the class to the desired location.
454*795d594fSAndroid Build Coastguard Worker if (out.IsValid()) {
455*795d594fSAndroid Build Coastguard Worker DCHECK(out.IsRegister() && !locations->GetLiveRegisters()->ContainsCoreRegister(out.reg()));
456*795d594fSAndroid Build Coastguard Worker DataType::Type type = DataType::Type::kReference;
457*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(type, instruction_->GetType());
458*795d594fSAndroid Build Coastguard Worker riscv64_codegen->MoveLocation(out, calling_convention.GetReturnLocation(type), type);
459*795d594fSAndroid Build Coastguard Worker }
460*795d594fSAndroid Build Coastguard Worker RestoreLiveRegisters(codegen, locations);
461*795d594fSAndroid Build Coastguard Worker
462*795d594fSAndroid Build Coastguard Worker __ J(GetExitLabel());
463*795d594fSAndroid Build Coastguard Worker }
464*795d594fSAndroid Build Coastguard Worker
GetDescription() const465*795d594fSAndroid Build Coastguard Worker const char* GetDescription() const override { return "LoadClassSlowPathRISCV64"; }
466*795d594fSAndroid Build Coastguard Worker
467*795d594fSAndroid Build Coastguard Worker private:
468*795d594fSAndroid Build Coastguard Worker // The class this slow path will load.
469*795d594fSAndroid Build Coastguard Worker HLoadClass* const cls_;
470*795d594fSAndroid Build Coastguard Worker
471*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(LoadClassSlowPathRISCV64);
472*795d594fSAndroid Build Coastguard Worker };
473*795d594fSAndroid Build Coastguard Worker
474*795d594fSAndroid Build Coastguard Worker class DeoptimizationSlowPathRISCV64 : public SlowPathCodeRISCV64 {
475*795d594fSAndroid Build Coastguard Worker public:
DeoptimizationSlowPathRISCV64(HDeoptimize * instruction)476*795d594fSAndroid Build Coastguard Worker explicit DeoptimizationSlowPathRISCV64(HDeoptimize* instruction)
477*795d594fSAndroid Build Coastguard Worker : SlowPathCodeRISCV64(instruction) {}
478*795d594fSAndroid Build Coastguard Worker
EmitNativeCode(CodeGenerator * codegen)479*795d594fSAndroid Build Coastguard Worker void EmitNativeCode(CodeGenerator* codegen) override {
480*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64* riscv64_codegen = down_cast<CodeGeneratorRISCV64*>(codegen);
481*795d594fSAndroid Build Coastguard Worker __ Bind(GetEntryLabel());
482*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction_->GetLocations();
483*795d594fSAndroid Build Coastguard Worker SaveLiveRegisters(codegen, locations);
484*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
485*795d594fSAndroid Build Coastguard Worker __ LoadConst32(calling_convention.GetRegisterAt(0),
486*795d594fSAndroid Build Coastguard Worker static_cast<uint32_t>(instruction_->AsDeoptimize()->GetDeoptimizationKind()));
487*795d594fSAndroid Build Coastguard Worker riscv64_codegen->InvokeRuntime(kQuickDeoptimize, instruction_, instruction_->GetDexPc(), this);
488*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickDeoptimize, void, DeoptimizationKind>();
489*795d594fSAndroid Build Coastguard Worker }
490*795d594fSAndroid Build Coastguard Worker
GetDescription() const491*795d594fSAndroid Build Coastguard Worker const char* GetDescription() const override { return "DeoptimizationSlowPathRISCV64"; }
492*795d594fSAndroid Build Coastguard Worker
493*795d594fSAndroid Build Coastguard Worker private:
494*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(DeoptimizationSlowPathRISCV64);
495*795d594fSAndroid Build Coastguard Worker };
496*795d594fSAndroid Build Coastguard Worker
497*795d594fSAndroid Build Coastguard Worker // Slow path generating a read barrier for a GC root.
498*795d594fSAndroid Build Coastguard Worker class ReadBarrierForRootSlowPathRISCV64 : public SlowPathCodeRISCV64 {
499*795d594fSAndroid Build Coastguard Worker public:
ReadBarrierForRootSlowPathRISCV64(HInstruction * instruction,Location out,Location root)500*795d594fSAndroid Build Coastguard Worker ReadBarrierForRootSlowPathRISCV64(HInstruction* instruction, Location out, Location root)
501*795d594fSAndroid Build Coastguard Worker : SlowPathCodeRISCV64(instruction), out_(out), root_(root) {
502*795d594fSAndroid Build Coastguard Worker }
503*795d594fSAndroid Build Coastguard Worker
EmitNativeCode(CodeGenerator * codegen)504*795d594fSAndroid Build Coastguard Worker void EmitNativeCode(CodeGenerator* codegen) override {
505*795d594fSAndroid Build Coastguard Worker DCHECK(codegen->EmitReadBarrier());
506*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction_->GetLocations();
507*795d594fSAndroid Build Coastguard Worker DataType::Type type = DataType::Type::kReference;
508*795d594fSAndroid Build Coastguard Worker XRegister reg_out = out_.AsRegister<XRegister>();
509*795d594fSAndroid Build Coastguard Worker DCHECK(locations->CanCall());
510*795d594fSAndroid Build Coastguard Worker DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(reg_out));
511*795d594fSAndroid Build Coastguard Worker DCHECK(instruction_->IsLoadClass() ||
512*795d594fSAndroid Build Coastguard Worker instruction_->IsLoadString() ||
513*795d594fSAndroid Build Coastguard Worker (instruction_->IsInvoke() && instruction_->GetLocations()->Intrinsified()))
514*795d594fSAndroid Build Coastguard Worker << "Unexpected instruction in read barrier for GC root slow path: "
515*795d594fSAndroid Build Coastguard Worker << instruction_->DebugName();
516*795d594fSAndroid Build Coastguard Worker
517*795d594fSAndroid Build Coastguard Worker __ Bind(GetEntryLabel());
518*795d594fSAndroid Build Coastguard Worker SaveLiveRegisters(codegen, locations);
519*795d594fSAndroid Build Coastguard Worker
520*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
521*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64* riscv64_codegen = down_cast<CodeGeneratorRISCV64*>(codegen);
522*795d594fSAndroid Build Coastguard Worker riscv64_codegen->MoveLocation(Location::RegisterLocation(calling_convention.GetRegisterAt(0)),
523*795d594fSAndroid Build Coastguard Worker root_,
524*795d594fSAndroid Build Coastguard Worker DataType::Type::kReference);
525*795d594fSAndroid Build Coastguard Worker riscv64_codegen->InvokeRuntime(kQuickReadBarrierForRootSlow,
526*795d594fSAndroid Build Coastguard Worker instruction_,
527*795d594fSAndroid Build Coastguard Worker instruction_->GetDexPc(),
528*795d594fSAndroid Build Coastguard Worker this);
529*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickReadBarrierForRootSlow, mirror::Object*, GcRoot<mirror::Object>*>();
530*795d594fSAndroid Build Coastguard Worker riscv64_codegen->MoveLocation(out_, calling_convention.GetReturnLocation(type), type);
531*795d594fSAndroid Build Coastguard Worker
532*795d594fSAndroid Build Coastguard Worker RestoreLiveRegisters(codegen, locations);
533*795d594fSAndroid Build Coastguard Worker __ J(GetExitLabel());
534*795d594fSAndroid Build Coastguard Worker }
535*795d594fSAndroid Build Coastguard Worker
GetDescription() const536*795d594fSAndroid Build Coastguard Worker const char* GetDescription() const override { return "ReadBarrierForRootSlowPathRISCV64"; }
537*795d594fSAndroid Build Coastguard Worker
538*795d594fSAndroid Build Coastguard Worker private:
539*795d594fSAndroid Build Coastguard Worker const Location out_;
540*795d594fSAndroid Build Coastguard Worker const Location root_;
541*795d594fSAndroid Build Coastguard Worker
542*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ReadBarrierForRootSlowPathRISCV64);
543*795d594fSAndroid Build Coastguard Worker };
544*795d594fSAndroid Build Coastguard Worker
545*795d594fSAndroid Build Coastguard Worker class MethodEntryExitHooksSlowPathRISCV64 : public SlowPathCodeRISCV64 {
546*795d594fSAndroid Build Coastguard Worker public:
MethodEntryExitHooksSlowPathRISCV64(HInstruction * instruction)547*795d594fSAndroid Build Coastguard Worker explicit MethodEntryExitHooksSlowPathRISCV64(HInstruction* instruction)
548*795d594fSAndroid Build Coastguard Worker : SlowPathCodeRISCV64(instruction) {}
549*795d594fSAndroid Build Coastguard Worker
EmitNativeCode(CodeGenerator * codegen)550*795d594fSAndroid Build Coastguard Worker void EmitNativeCode(CodeGenerator* codegen) override {
551*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction_->GetLocations();
552*795d594fSAndroid Build Coastguard Worker QuickEntrypointEnum entry_point =
553*795d594fSAndroid Build Coastguard Worker (instruction_->IsMethodEntryHook()) ? kQuickMethodEntryHook : kQuickMethodExitHook;
554*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64* riscv64_codegen = down_cast<CodeGeneratorRISCV64*>(codegen);
555*795d594fSAndroid Build Coastguard Worker __ Bind(GetEntryLabel());
556*795d594fSAndroid Build Coastguard Worker SaveLiveRegisters(codegen, locations);
557*795d594fSAndroid Build Coastguard Worker if (instruction_->IsMethodExitHook()) {
558*795d594fSAndroid Build Coastguard Worker __ Li(A4, riscv64_codegen->GetFrameSize());
559*795d594fSAndroid Build Coastguard Worker }
560*795d594fSAndroid Build Coastguard Worker riscv64_codegen->InvokeRuntime(entry_point, instruction_, instruction_->GetDexPc(), this);
561*795d594fSAndroid Build Coastguard Worker RestoreLiveRegisters(codegen, locations);
562*795d594fSAndroid Build Coastguard Worker __ J(GetExitLabel());
563*795d594fSAndroid Build Coastguard Worker }
564*795d594fSAndroid Build Coastguard Worker
GetDescription() const565*795d594fSAndroid Build Coastguard Worker const char* GetDescription() const override {
566*795d594fSAndroid Build Coastguard Worker return "MethodEntryExitHooksSlowPathRISCV";
567*795d594fSAndroid Build Coastguard Worker }
568*795d594fSAndroid Build Coastguard Worker
569*795d594fSAndroid Build Coastguard Worker private:
570*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(MethodEntryExitHooksSlowPathRISCV64);
571*795d594fSAndroid Build Coastguard Worker };
572*795d594fSAndroid Build Coastguard Worker
573*795d594fSAndroid Build Coastguard Worker class ArraySetSlowPathRISCV64 : public SlowPathCodeRISCV64 {
574*795d594fSAndroid Build Coastguard Worker public:
ArraySetSlowPathRISCV64(HInstruction * instruction)575*795d594fSAndroid Build Coastguard Worker explicit ArraySetSlowPathRISCV64(HInstruction* instruction) : SlowPathCodeRISCV64(instruction) {}
576*795d594fSAndroid Build Coastguard Worker
EmitNativeCode(CodeGenerator * codegen)577*795d594fSAndroid Build Coastguard Worker void EmitNativeCode(CodeGenerator* codegen) override {
578*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction_->GetLocations();
579*795d594fSAndroid Build Coastguard Worker __ Bind(GetEntryLabel());
580*795d594fSAndroid Build Coastguard Worker SaveLiveRegisters(codegen, locations);
581*795d594fSAndroid Build Coastguard Worker
582*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
583*795d594fSAndroid Build Coastguard Worker HParallelMove parallel_move(codegen->GetGraph()->GetAllocator());
584*795d594fSAndroid Build Coastguard Worker parallel_move.AddMove(
585*795d594fSAndroid Build Coastguard Worker locations->InAt(0),
586*795d594fSAndroid Build Coastguard Worker Location::RegisterLocation(calling_convention.GetRegisterAt(0)),
587*795d594fSAndroid Build Coastguard Worker DataType::Type::kReference,
588*795d594fSAndroid Build Coastguard Worker nullptr);
589*795d594fSAndroid Build Coastguard Worker parallel_move.AddMove(
590*795d594fSAndroid Build Coastguard Worker locations->InAt(1),
591*795d594fSAndroid Build Coastguard Worker Location::RegisterLocation(calling_convention.GetRegisterAt(1)),
592*795d594fSAndroid Build Coastguard Worker DataType::Type::kInt32,
593*795d594fSAndroid Build Coastguard Worker nullptr);
594*795d594fSAndroid Build Coastguard Worker parallel_move.AddMove(
595*795d594fSAndroid Build Coastguard Worker locations->InAt(2),
596*795d594fSAndroid Build Coastguard Worker Location::RegisterLocation(calling_convention.GetRegisterAt(2)),
597*795d594fSAndroid Build Coastguard Worker DataType::Type::kReference,
598*795d594fSAndroid Build Coastguard Worker nullptr);
599*795d594fSAndroid Build Coastguard Worker codegen->GetMoveResolver()->EmitNativeCode(¶llel_move);
600*795d594fSAndroid Build Coastguard Worker
601*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64* riscv64_codegen = down_cast<CodeGeneratorRISCV64*>(codegen);
602*795d594fSAndroid Build Coastguard Worker riscv64_codegen->InvokeRuntime(kQuickAputObject, instruction_, instruction_->GetDexPc(), this);
603*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickAputObject, void, mirror::Array*, int32_t, mirror::Object*>();
604*795d594fSAndroid Build Coastguard Worker RestoreLiveRegisters(codegen, locations);
605*795d594fSAndroid Build Coastguard Worker __ J(GetExitLabel());
606*795d594fSAndroid Build Coastguard Worker }
607*795d594fSAndroid Build Coastguard Worker
GetDescription() const608*795d594fSAndroid Build Coastguard Worker const char* GetDescription() const override { return "ArraySetSlowPathRISCV64"; }
609*795d594fSAndroid Build Coastguard Worker
610*795d594fSAndroid Build Coastguard Worker private:
611*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ArraySetSlowPathRISCV64);
612*795d594fSAndroid Build Coastguard Worker };
613*795d594fSAndroid Build Coastguard Worker
614*795d594fSAndroid Build Coastguard Worker class TypeCheckSlowPathRISCV64 : public SlowPathCodeRISCV64 {
615*795d594fSAndroid Build Coastguard Worker public:
TypeCheckSlowPathRISCV64(HInstruction * instruction,bool is_fatal)616*795d594fSAndroid Build Coastguard Worker explicit TypeCheckSlowPathRISCV64(HInstruction* instruction, bool is_fatal)
617*795d594fSAndroid Build Coastguard Worker : SlowPathCodeRISCV64(instruction), is_fatal_(is_fatal) {}
618*795d594fSAndroid Build Coastguard Worker
EmitNativeCode(CodeGenerator * codegen)619*795d594fSAndroid Build Coastguard Worker void EmitNativeCode(CodeGenerator* codegen) override {
620*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction_->GetLocations();
621*795d594fSAndroid Build Coastguard Worker
622*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc = instruction_->GetDexPc();
623*795d594fSAndroid Build Coastguard Worker DCHECK(instruction_->IsCheckCast()
624*795d594fSAndroid Build Coastguard Worker || !locations->GetLiveRegisters()->ContainsCoreRegister(locations->Out().reg()));
625*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64* riscv64_codegen = down_cast<CodeGeneratorRISCV64*>(codegen);
626*795d594fSAndroid Build Coastguard Worker
627*795d594fSAndroid Build Coastguard Worker __ Bind(GetEntryLabel());
628*795d594fSAndroid Build Coastguard Worker if (!is_fatal_ || instruction_->CanThrowIntoCatchBlock()) {
629*795d594fSAndroid Build Coastguard Worker SaveLiveRegisters(codegen, locations);
630*795d594fSAndroid Build Coastguard Worker }
631*795d594fSAndroid Build Coastguard Worker
632*795d594fSAndroid Build Coastguard Worker // We're moving two locations to locations that could overlap, so we need a parallel
633*795d594fSAndroid Build Coastguard Worker // move resolver.
634*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
635*795d594fSAndroid Build Coastguard Worker codegen->EmitParallelMoves(locations->InAt(0),
636*795d594fSAndroid Build Coastguard Worker Location::RegisterLocation(calling_convention.GetRegisterAt(0)),
637*795d594fSAndroid Build Coastguard Worker DataType::Type::kReference,
638*795d594fSAndroid Build Coastguard Worker locations->InAt(1),
639*795d594fSAndroid Build Coastguard Worker Location::RegisterLocation(calling_convention.GetRegisterAt(1)),
640*795d594fSAndroid Build Coastguard Worker DataType::Type::kReference);
641*795d594fSAndroid Build Coastguard Worker if (instruction_->IsInstanceOf()) {
642*795d594fSAndroid Build Coastguard Worker riscv64_codegen->InvokeRuntime(kQuickInstanceofNonTrivial, instruction_, dex_pc, this);
643*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickInstanceofNonTrivial, size_t, mirror::Object*, mirror::Class*>();
644*795d594fSAndroid Build Coastguard Worker DataType::Type ret_type = instruction_->GetType();
645*795d594fSAndroid Build Coastguard Worker Location ret_loc = calling_convention.GetReturnLocation(ret_type);
646*795d594fSAndroid Build Coastguard Worker riscv64_codegen->MoveLocation(locations->Out(), ret_loc, ret_type);
647*795d594fSAndroid Build Coastguard Worker } else {
648*795d594fSAndroid Build Coastguard Worker DCHECK(instruction_->IsCheckCast());
649*795d594fSAndroid Build Coastguard Worker riscv64_codegen->InvokeRuntime(kQuickCheckInstanceOf, instruction_, dex_pc, this);
650*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickCheckInstanceOf, void, mirror::Object*, mirror::Class*>();
651*795d594fSAndroid Build Coastguard Worker }
652*795d594fSAndroid Build Coastguard Worker
653*795d594fSAndroid Build Coastguard Worker if (!is_fatal_) {
654*795d594fSAndroid Build Coastguard Worker RestoreLiveRegisters(codegen, locations);
655*795d594fSAndroid Build Coastguard Worker __ J(GetExitLabel());
656*795d594fSAndroid Build Coastguard Worker }
657*795d594fSAndroid Build Coastguard Worker }
658*795d594fSAndroid Build Coastguard Worker
GetDescription() const659*795d594fSAndroid Build Coastguard Worker const char* GetDescription() const override { return "TypeCheckSlowPathRISCV64"; }
660*795d594fSAndroid Build Coastguard Worker
IsFatal() const661*795d594fSAndroid Build Coastguard Worker bool IsFatal() const override { return is_fatal_; }
662*795d594fSAndroid Build Coastguard Worker
663*795d594fSAndroid Build Coastguard Worker private:
664*795d594fSAndroid Build Coastguard Worker const bool is_fatal_;
665*795d594fSAndroid Build Coastguard Worker
666*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(TypeCheckSlowPathRISCV64);
667*795d594fSAndroid Build Coastguard Worker };
668*795d594fSAndroid Build Coastguard Worker
669*795d594fSAndroid Build Coastguard Worker class DivZeroCheckSlowPathRISCV64 : public SlowPathCodeRISCV64 {
670*795d594fSAndroid Build Coastguard Worker public:
DivZeroCheckSlowPathRISCV64(HDivZeroCheck * instruction)671*795d594fSAndroid Build Coastguard Worker explicit DivZeroCheckSlowPathRISCV64(HDivZeroCheck* instruction)
672*795d594fSAndroid Build Coastguard Worker : SlowPathCodeRISCV64(instruction) {}
673*795d594fSAndroid Build Coastguard Worker
EmitNativeCode(CodeGenerator * codegen)674*795d594fSAndroid Build Coastguard Worker void EmitNativeCode(CodeGenerator* codegen) override {
675*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64* riscv64_codegen = down_cast<CodeGeneratorRISCV64*>(codegen);
676*795d594fSAndroid Build Coastguard Worker __ Bind(GetEntryLabel());
677*795d594fSAndroid Build Coastguard Worker riscv64_codegen->InvokeRuntime(
678*795d594fSAndroid Build Coastguard Worker kQuickThrowDivZero, instruction_, instruction_->GetDexPc(), this);
679*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickThrowDivZero, void, void>();
680*795d594fSAndroid Build Coastguard Worker }
681*795d594fSAndroid Build Coastguard Worker
IsFatal() const682*795d594fSAndroid Build Coastguard Worker bool IsFatal() const override { return true; }
683*795d594fSAndroid Build Coastguard Worker
GetDescription() const684*795d594fSAndroid Build Coastguard Worker const char* GetDescription() const override { return "DivZeroCheckSlowPathRISCV64"; }
685*795d594fSAndroid Build Coastguard Worker
686*795d594fSAndroid Build Coastguard Worker private:
687*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(DivZeroCheckSlowPathRISCV64);
688*795d594fSAndroid Build Coastguard Worker };
689*795d594fSAndroid Build Coastguard Worker
690*795d594fSAndroid Build Coastguard Worker class ReadBarrierMarkSlowPathRISCV64 : public SlowPathCodeRISCV64 {
691*795d594fSAndroid Build Coastguard Worker public:
ReadBarrierMarkSlowPathRISCV64(HInstruction * instruction,Location ref,Location entrypoint)692*795d594fSAndroid Build Coastguard Worker ReadBarrierMarkSlowPathRISCV64(HInstruction* instruction, Location ref, Location entrypoint)
693*795d594fSAndroid Build Coastguard Worker : SlowPathCodeRISCV64(instruction), ref_(ref), entrypoint_(entrypoint) {
694*795d594fSAndroid Build Coastguard Worker DCHECK(entrypoint.IsRegister());
695*795d594fSAndroid Build Coastguard Worker }
696*795d594fSAndroid Build Coastguard Worker
GetDescription() const697*795d594fSAndroid Build Coastguard Worker const char* GetDescription() const override { return "ReadBarrierMarkSlowPathRISCV64"; }
698*795d594fSAndroid Build Coastguard Worker
EmitNativeCode(CodeGenerator * codegen)699*795d594fSAndroid Build Coastguard Worker void EmitNativeCode(CodeGenerator* codegen) override {
700*795d594fSAndroid Build Coastguard Worker DCHECK(codegen->EmitReadBarrier());
701*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction_->GetLocations();
702*795d594fSAndroid Build Coastguard Worker XRegister ref_reg = ref_.AsRegister<XRegister>();
703*795d594fSAndroid Build Coastguard Worker DCHECK(locations->CanCall());
704*795d594fSAndroid Build Coastguard Worker DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(ref_reg)) << ref_reg;
705*795d594fSAndroid Build Coastguard Worker DCHECK(instruction_->IsInstanceFieldGet() ||
706*795d594fSAndroid Build Coastguard Worker instruction_->IsStaticFieldGet() ||
707*795d594fSAndroid Build Coastguard Worker instruction_->IsArrayGet() ||
708*795d594fSAndroid Build Coastguard Worker instruction_->IsArraySet() ||
709*795d594fSAndroid Build Coastguard Worker instruction_->IsLoadClass() ||
710*795d594fSAndroid Build Coastguard Worker instruction_->IsLoadString() ||
711*795d594fSAndroid Build Coastguard Worker instruction_->IsInstanceOf() ||
712*795d594fSAndroid Build Coastguard Worker instruction_->IsCheckCast() ||
713*795d594fSAndroid Build Coastguard Worker (instruction_->IsInvoke() && instruction_->GetLocations()->Intrinsified()))
714*795d594fSAndroid Build Coastguard Worker << "Unexpected instruction in read barrier marking slow path: "
715*795d594fSAndroid Build Coastguard Worker << instruction_->DebugName();
716*795d594fSAndroid Build Coastguard Worker
717*795d594fSAndroid Build Coastguard Worker __ Bind(GetEntryLabel());
718*795d594fSAndroid Build Coastguard Worker // No need to save live registers; it's taken care of by the
719*795d594fSAndroid Build Coastguard Worker // entrypoint. Also, there is no need to update the stack mask,
720*795d594fSAndroid Build Coastguard Worker // as this runtime call will not trigger a garbage collection.
721*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64* riscv64_codegen = down_cast<CodeGeneratorRISCV64*>(codegen);
722*795d594fSAndroid Build Coastguard Worker DCHECK(ref_reg >= T0 && ref_reg != TR);
723*795d594fSAndroid Build Coastguard Worker
724*795d594fSAndroid Build Coastguard Worker // "Compact" slow path, saving two moves.
725*795d594fSAndroid Build Coastguard Worker //
726*795d594fSAndroid Build Coastguard Worker // Instead of using the standard runtime calling convention (input
727*795d594fSAndroid Build Coastguard Worker // and output in A0 and V0 respectively):
728*795d594fSAndroid Build Coastguard Worker //
729*795d594fSAndroid Build Coastguard Worker // A0 <- ref
730*795d594fSAndroid Build Coastguard Worker // V0 <- ReadBarrierMark(A0)
731*795d594fSAndroid Build Coastguard Worker // ref <- V0
732*795d594fSAndroid Build Coastguard Worker //
733*795d594fSAndroid Build Coastguard Worker // we just use rX (the register containing `ref`) as input and output
734*795d594fSAndroid Build Coastguard Worker // of a dedicated entrypoint:
735*795d594fSAndroid Build Coastguard Worker //
736*795d594fSAndroid Build Coastguard Worker // rX <- ReadBarrierMarkRegX(rX)
737*795d594fSAndroid Build Coastguard Worker //
738*795d594fSAndroid Build Coastguard Worker riscv64_codegen->ValidateInvokeRuntimeWithoutRecordingPcInfo(instruction_, this);
739*795d594fSAndroid Build Coastguard Worker DCHECK_NE(entrypoint_.AsRegister<XRegister>(), TMP); // A taken branch can clobber `TMP`.
740*795d594fSAndroid Build Coastguard Worker __ Jalr(entrypoint_.AsRegister<XRegister>()); // Clobbers `RA` (used as the `entrypoint_`).
741*795d594fSAndroid Build Coastguard Worker __ J(GetExitLabel());
742*795d594fSAndroid Build Coastguard Worker }
743*795d594fSAndroid Build Coastguard Worker
744*795d594fSAndroid Build Coastguard Worker private:
745*795d594fSAndroid Build Coastguard Worker // The location (register) of the marked object reference.
746*795d594fSAndroid Build Coastguard Worker const Location ref_;
747*795d594fSAndroid Build Coastguard Worker
748*795d594fSAndroid Build Coastguard Worker // The location of the already loaded entrypoint.
749*795d594fSAndroid Build Coastguard Worker const Location entrypoint_;
750*795d594fSAndroid Build Coastguard Worker
751*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ReadBarrierMarkSlowPathRISCV64);
752*795d594fSAndroid Build Coastguard Worker };
753*795d594fSAndroid Build Coastguard Worker
754*795d594fSAndroid Build Coastguard Worker class LoadStringSlowPathRISCV64 : public SlowPathCodeRISCV64 {
755*795d594fSAndroid Build Coastguard Worker public:
LoadStringSlowPathRISCV64(HLoadString * instruction)756*795d594fSAndroid Build Coastguard Worker explicit LoadStringSlowPathRISCV64(HLoadString* instruction)
757*795d594fSAndroid Build Coastguard Worker : SlowPathCodeRISCV64(instruction) {}
758*795d594fSAndroid Build Coastguard Worker
EmitNativeCode(CodeGenerator * codegen)759*795d594fSAndroid Build Coastguard Worker void EmitNativeCode(CodeGenerator* codegen) override {
760*795d594fSAndroid Build Coastguard Worker DCHECK(instruction_->IsLoadString());
761*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(instruction_->AsLoadString()->GetLoadKind(), HLoadString::LoadKind::kBssEntry);
762*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction_->GetLocations();
763*795d594fSAndroid Build Coastguard Worker DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(locations->Out().reg()));
764*795d594fSAndroid Build Coastguard Worker const dex::StringIndex string_index = instruction_->AsLoadString()->GetStringIndex();
765*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64* riscv64_codegen = down_cast<CodeGeneratorRISCV64*>(codegen);
766*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
767*795d594fSAndroid Build Coastguard Worker __ Bind(GetEntryLabel());
768*795d594fSAndroid Build Coastguard Worker SaveLiveRegisters(codegen, locations);
769*795d594fSAndroid Build Coastguard Worker
770*795d594fSAndroid Build Coastguard Worker __ LoadConst32(calling_convention.GetRegisterAt(0), string_index.index_);
771*795d594fSAndroid Build Coastguard Worker riscv64_codegen->InvokeRuntime(
772*795d594fSAndroid Build Coastguard Worker kQuickResolveString, instruction_, instruction_->GetDexPc(), this);
773*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
774*795d594fSAndroid Build Coastguard Worker
775*795d594fSAndroid Build Coastguard Worker DataType::Type type = DataType::Type::kReference;
776*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(type, instruction_->GetType());
777*795d594fSAndroid Build Coastguard Worker riscv64_codegen->MoveLocation(
778*795d594fSAndroid Build Coastguard Worker locations->Out(), calling_convention.GetReturnLocation(type), type);
779*795d594fSAndroid Build Coastguard Worker RestoreLiveRegisters(codegen, locations);
780*795d594fSAndroid Build Coastguard Worker
781*795d594fSAndroid Build Coastguard Worker __ J(GetExitLabel());
782*795d594fSAndroid Build Coastguard Worker }
783*795d594fSAndroid Build Coastguard Worker
GetDescription() const784*795d594fSAndroid Build Coastguard Worker const char* GetDescription() const override { return "LoadStringSlowPathRISCV64"; }
785*795d594fSAndroid Build Coastguard Worker
786*795d594fSAndroid Build Coastguard Worker private:
787*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(LoadStringSlowPathRISCV64);
788*795d594fSAndroid Build Coastguard Worker };
789*795d594fSAndroid Build Coastguard Worker
790*795d594fSAndroid Build Coastguard Worker #undef __
791*795d594fSAndroid Build Coastguard Worker #define __ down_cast<Riscv64Assembler*>(GetAssembler())-> // NOLINT
792*795d594fSAndroid Build Coastguard Worker
793*795d594fSAndroid Build Coastguard Worker template <typename Reg,
794*795d594fSAndroid Build Coastguard Worker void (Riscv64Assembler::*opS)(Reg, FRegister, FRegister),
795*795d594fSAndroid Build Coastguard Worker void (Riscv64Assembler::*opD)(Reg, FRegister, FRegister)>
FpBinOp(Reg rd,FRegister rs1,FRegister rs2,DataType::Type type)796*795d594fSAndroid Build Coastguard Worker inline void InstructionCodeGeneratorRISCV64::FpBinOp(
797*795d594fSAndroid Build Coastguard Worker Reg rd, FRegister rs1, FRegister rs2, DataType::Type type) {
798*795d594fSAndroid Build Coastguard Worker Riscv64Assembler* assembler = down_cast<CodeGeneratorRISCV64*>(codegen_)->GetAssembler();
799*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kFloat32) {
800*795d594fSAndroid Build Coastguard Worker (assembler->*opS)(rd, rs1, rs2);
801*795d594fSAndroid Build Coastguard Worker } else {
802*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(type, DataType::Type::kFloat64);
803*795d594fSAndroid Build Coastguard Worker (assembler->*opD)(rd, rs1, rs2);
804*795d594fSAndroid Build Coastguard Worker }
805*795d594fSAndroid Build Coastguard Worker }
806*795d594fSAndroid Build Coastguard Worker
FAdd(FRegister rd,FRegister rs1,FRegister rs2,DataType::Type type)807*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::FAdd(
808*795d594fSAndroid Build Coastguard Worker FRegister rd, FRegister rs1, FRegister rs2, DataType::Type type) {
809*795d594fSAndroid Build Coastguard Worker FpBinOp<FRegister, &Riscv64Assembler::FAddS, &Riscv64Assembler::FAddD>(rd, rs1, rs2, type);
810*795d594fSAndroid Build Coastguard Worker }
811*795d594fSAndroid Build Coastguard Worker
FSub(FRegister rd,FRegister rs1,FRegister rs2,DataType::Type type)812*795d594fSAndroid Build Coastguard Worker inline void InstructionCodeGeneratorRISCV64::FSub(
813*795d594fSAndroid Build Coastguard Worker FRegister rd, FRegister rs1, FRegister rs2, DataType::Type type) {
814*795d594fSAndroid Build Coastguard Worker FpBinOp<FRegister, &Riscv64Assembler::FSubS, &Riscv64Assembler::FSubD>(rd, rs1, rs2, type);
815*795d594fSAndroid Build Coastguard Worker }
816*795d594fSAndroid Build Coastguard Worker
FDiv(FRegister rd,FRegister rs1,FRegister rs2,DataType::Type type)817*795d594fSAndroid Build Coastguard Worker inline void InstructionCodeGeneratorRISCV64::FDiv(
818*795d594fSAndroid Build Coastguard Worker FRegister rd, FRegister rs1, FRegister rs2, DataType::Type type) {
819*795d594fSAndroid Build Coastguard Worker FpBinOp<FRegister, &Riscv64Assembler::FDivS, &Riscv64Assembler::FDivD>(rd, rs1, rs2, type);
820*795d594fSAndroid Build Coastguard Worker }
821*795d594fSAndroid Build Coastguard Worker
FMul(FRegister rd,FRegister rs1,FRegister rs2,DataType::Type type)822*795d594fSAndroid Build Coastguard Worker inline void InstructionCodeGeneratorRISCV64::FMul(
823*795d594fSAndroid Build Coastguard Worker FRegister rd, FRegister rs1, FRegister rs2, DataType::Type type) {
824*795d594fSAndroid Build Coastguard Worker FpBinOp<FRegister, &Riscv64Assembler::FMulS, &Riscv64Assembler::FMulD>(rd, rs1, rs2, type);
825*795d594fSAndroid Build Coastguard Worker }
826*795d594fSAndroid Build Coastguard Worker
FMin(FRegister rd,FRegister rs1,FRegister rs2,DataType::Type type)827*795d594fSAndroid Build Coastguard Worker inline void InstructionCodeGeneratorRISCV64::FMin(
828*795d594fSAndroid Build Coastguard Worker FRegister rd, FRegister rs1, FRegister rs2, DataType::Type type) {
829*795d594fSAndroid Build Coastguard Worker FpBinOp<FRegister, &Riscv64Assembler::FMinS, &Riscv64Assembler::FMinD>(rd, rs1, rs2, type);
830*795d594fSAndroid Build Coastguard Worker }
831*795d594fSAndroid Build Coastguard Worker
FMax(FRegister rd,FRegister rs1,FRegister rs2,DataType::Type type)832*795d594fSAndroid Build Coastguard Worker inline void InstructionCodeGeneratorRISCV64::FMax(
833*795d594fSAndroid Build Coastguard Worker FRegister rd, FRegister rs1, FRegister rs2, DataType::Type type) {
834*795d594fSAndroid Build Coastguard Worker FpBinOp<FRegister, &Riscv64Assembler::FMaxS, &Riscv64Assembler::FMaxD>(rd, rs1, rs2, type);
835*795d594fSAndroid Build Coastguard Worker }
836*795d594fSAndroid Build Coastguard Worker
FEq(XRegister rd,FRegister rs1,FRegister rs2,DataType::Type type)837*795d594fSAndroid Build Coastguard Worker inline void InstructionCodeGeneratorRISCV64::FEq(
838*795d594fSAndroid Build Coastguard Worker XRegister rd, FRegister rs1, FRegister rs2, DataType::Type type) {
839*795d594fSAndroid Build Coastguard Worker FpBinOp<XRegister, &Riscv64Assembler::FEqS, &Riscv64Assembler::FEqD>(rd, rs1, rs2, type);
840*795d594fSAndroid Build Coastguard Worker }
841*795d594fSAndroid Build Coastguard Worker
FLt(XRegister rd,FRegister rs1,FRegister rs2,DataType::Type type)842*795d594fSAndroid Build Coastguard Worker inline void InstructionCodeGeneratorRISCV64::FLt(
843*795d594fSAndroid Build Coastguard Worker XRegister rd, FRegister rs1, FRegister rs2, DataType::Type type) {
844*795d594fSAndroid Build Coastguard Worker FpBinOp<XRegister, &Riscv64Assembler::FLtS, &Riscv64Assembler::FLtD>(rd, rs1, rs2, type);
845*795d594fSAndroid Build Coastguard Worker }
846*795d594fSAndroid Build Coastguard Worker
FLe(XRegister rd,FRegister rs1,FRegister rs2,DataType::Type type)847*795d594fSAndroid Build Coastguard Worker inline void InstructionCodeGeneratorRISCV64::FLe(
848*795d594fSAndroid Build Coastguard Worker XRegister rd, FRegister rs1, FRegister rs2, DataType::Type type) {
849*795d594fSAndroid Build Coastguard Worker FpBinOp<XRegister, &Riscv64Assembler::FLeS, &Riscv64Assembler::FLeD>(rd, rs1, rs2, type);
850*795d594fSAndroid Build Coastguard Worker }
851*795d594fSAndroid Build Coastguard Worker
852*795d594fSAndroid Build Coastguard Worker template <typename Reg,
853*795d594fSAndroid Build Coastguard Worker void (Riscv64Assembler::*opS)(Reg, FRegister),
854*795d594fSAndroid Build Coastguard Worker void (Riscv64Assembler::*opD)(Reg, FRegister)>
FpUnOp(Reg rd,FRegister rs1,DataType::Type type)855*795d594fSAndroid Build Coastguard Worker inline void InstructionCodeGeneratorRISCV64::FpUnOp(
856*795d594fSAndroid Build Coastguard Worker Reg rd, FRegister rs1, DataType::Type type) {
857*795d594fSAndroid Build Coastguard Worker Riscv64Assembler* assembler = down_cast<CodeGeneratorRISCV64*>(codegen_)->GetAssembler();
858*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kFloat32) {
859*795d594fSAndroid Build Coastguard Worker (assembler->*opS)(rd, rs1);
860*795d594fSAndroid Build Coastguard Worker } else {
861*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(type, DataType::Type::kFloat64);
862*795d594fSAndroid Build Coastguard Worker (assembler->*opD)(rd, rs1);
863*795d594fSAndroid Build Coastguard Worker }
864*795d594fSAndroid Build Coastguard Worker }
865*795d594fSAndroid Build Coastguard Worker
FAbs(FRegister rd,FRegister rs1,DataType::Type type)866*795d594fSAndroid Build Coastguard Worker inline void InstructionCodeGeneratorRISCV64::FAbs(
867*795d594fSAndroid Build Coastguard Worker FRegister rd, FRegister rs1, DataType::Type type) {
868*795d594fSAndroid Build Coastguard Worker FpUnOp<FRegister, &Riscv64Assembler::FAbsS, &Riscv64Assembler::FAbsD>(rd, rs1, type);
869*795d594fSAndroid Build Coastguard Worker }
870*795d594fSAndroid Build Coastguard Worker
FNeg(FRegister rd,FRegister rs1,DataType::Type type)871*795d594fSAndroid Build Coastguard Worker inline void InstructionCodeGeneratorRISCV64::FNeg(
872*795d594fSAndroid Build Coastguard Worker FRegister rd, FRegister rs1, DataType::Type type) {
873*795d594fSAndroid Build Coastguard Worker FpUnOp<FRegister, &Riscv64Assembler::FNegS, &Riscv64Assembler::FNegD>(rd, rs1, type);
874*795d594fSAndroid Build Coastguard Worker }
875*795d594fSAndroid Build Coastguard Worker
FMv(FRegister rd,FRegister rs1,DataType::Type type)876*795d594fSAndroid Build Coastguard Worker inline void InstructionCodeGeneratorRISCV64::FMv(
877*795d594fSAndroid Build Coastguard Worker FRegister rd, FRegister rs1, DataType::Type type) {
878*795d594fSAndroid Build Coastguard Worker FpUnOp<FRegister, &Riscv64Assembler::FMvS, &Riscv64Assembler::FMvD>(rd, rs1, type);
879*795d594fSAndroid Build Coastguard Worker }
880*795d594fSAndroid Build Coastguard Worker
FMvX(XRegister rd,FRegister rs1,DataType::Type type)881*795d594fSAndroid Build Coastguard Worker inline void InstructionCodeGeneratorRISCV64::FMvX(
882*795d594fSAndroid Build Coastguard Worker XRegister rd, FRegister rs1, DataType::Type type) {
883*795d594fSAndroid Build Coastguard Worker FpUnOp<XRegister, &Riscv64Assembler::FMvXW, &Riscv64Assembler::FMvXD>(rd, rs1, type);
884*795d594fSAndroid Build Coastguard Worker }
885*795d594fSAndroid Build Coastguard Worker
FClass(XRegister rd,FRegister rs1,DataType::Type type)886*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::FClass(
887*795d594fSAndroid Build Coastguard Worker XRegister rd, FRegister rs1, DataType::Type type) {
888*795d594fSAndroid Build Coastguard Worker FpUnOp<XRegister, &Riscv64Assembler::FClassS, &Riscv64Assembler::FClassD>(rd, rs1, type);
889*795d594fSAndroid Build Coastguard Worker }
890*795d594fSAndroid Build Coastguard Worker
Load(Location out,XRegister rs1,int32_t offset,DataType::Type type)891*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::Load(
892*795d594fSAndroid Build Coastguard Worker Location out, XRegister rs1, int32_t offset, DataType::Type type) {
893*795d594fSAndroid Build Coastguard Worker switch (type) {
894*795d594fSAndroid Build Coastguard Worker case DataType::Type::kBool:
895*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint8:
896*795d594fSAndroid Build Coastguard Worker __ Loadbu(out.AsRegister<XRegister>(), rs1, offset);
897*795d594fSAndroid Build Coastguard Worker break;
898*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt8:
899*795d594fSAndroid Build Coastguard Worker __ Loadb(out.AsRegister<XRegister>(), rs1, offset);
900*795d594fSAndroid Build Coastguard Worker break;
901*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint16:
902*795d594fSAndroid Build Coastguard Worker __ Loadhu(out.AsRegister<XRegister>(), rs1, offset);
903*795d594fSAndroid Build Coastguard Worker break;
904*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt16:
905*795d594fSAndroid Build Coastguard Worker __ Loadh(out.AsRegister<XRegister>(), rs1, offset);
906*795d594fSAndroid Build Coastguard Worker break;
907*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
908*795d594fSAndroid Build Coastguard Worker __ Loadw(out.AsRegister<XRegister>(), rs1, offset);
909*795d594fSAndroid Build Coastguard Worker break;
910*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
911*795d594fSAndroid Build Coastguard Worker __ Loadd(out.AsRegister<XRegister>(), rs1, offset);
912*795d594fSAndroid Build Coastguard Worker break;
913*795d594fSAndroid Build Coastguard Worker case DataType::Type::kReference:
914*795d594fSAndroid Build Coastguard Worker __ Loadwu(out.AsRegister<XRegister>(), rs1, offset);
915*795d594fSAndroid Build Coastguard Worker break;
916*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
917*795d594fSAndroid Build Coastguard Worker __ FLoadw(out.AsFpuRegister<FRegister>(), rs1, offset);
918*795d594fSAndroid Build Coastguard Worker break;
919*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
920*795d594fSAndroid Build Coastguard Worker __ FLoadd(out.AsFpuRegister<FRegister>(), rs1, offset);
921*795d594fSAndroid Build Coastguard Worker break;
922*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint32:
923*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint64:
924*795d594fSAndroid Build Coastguard Worker case DataType::Type::kVoid:
925*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unreachable type " << type;
926*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
927*795d594fSAndroid Build Coastguard Worker }
928*795d594fSAndroid Build Coastguard Worker }
929*795d594fSAndroid Build Coastguard Worker
Store(Location value,XRegister rs1,int32_t offset,DataType::Type type)930*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::Store(
931*795d594fSAndroid Build Coastguard Worker Location value, XRegister rs1, int32_t offset, DataType::Type type) {
932*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(value.IsConstant(), IsZeroBitPattern(value.GetConstant()));
933*795d594fSAndroid Build Coastguard Worker if (kPoisonHeapReferences && type == DataType::Type::kReference && !value.IsConstant()) {
934*795d594fSAndroid Build Coastguard Worker riscv64::ScratchRegisterScope srs(GetAssembler());
935*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
936*795d594fSAndroid Build Coastguard Worker __ Mv(tmp, value.AsRegister<XRegister>());
937*795d594fSAndroid Build Coastguard Worker codegen_->PoisonHeapReference(tmp);
938*795d594fSAndroid Build Coastguard Worker __ Storew(tmp, rs1, offset);
939*795d594fSAndroid Build Coastguard Worker return;
940*795d594fSAndroid Build Coastguard Worker }
941*795d594fSAndroid Build Coastguard Worker switch (type) {
942*795d594fSAndroid Build Coastguard Worker case DataType::Type::kBool:
943*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint8:
944*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt8:
945*795d594fSAndroid Build Coastguard Worker __ Storeb(InputXRegisterOrZero(value), rs1, offset);
946*795d594fSAndroid Build Coastguard Worker break;
947*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint16:
948*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt16:
949*795d594fSAndroid Build Coastguard Worker __ Storeh(InputXRegisterOrZero(value), rs1, offset);
950*795d594fSAndroid Build Coastguard Worker break;
951*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
952*795d594fSAndroid Build Coastguard Worker if (!value.IsConstant()) {
953*795d594fSAndroid Build Coastguard Worker __ FStorew(value.AsFpuRegister<FRegister>(), rs1, offset);
954*795d594fSAndroid Build Coastguard Worker break;
955*795d594fSAndroid Build Coastguard Worker }
956*795d594fSAndroid Build Coastguard Worker FALLTHROUGH_INTENDED;
957*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
958*795d594fSAndroid Build Coastguard Worker case DataType::Type::kReference:
959*795d594fSAndroid Build Coastguard Worker __ Storew(InputXRegisterOrZero(value), rs1, offset);
960*795d594fSAndroid Build Coastguard Worker break;
961*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
962*795d594fSAndroid Build Coastguard Worker if (!value.IsConstant()) {
963*795d594fSAndroid Build Coastguard Worker __ FStored(value.AsFpuRegister<FRegister>(), rs1, offset);
964*795d594fSAndroid Build Coastguard Worker break;
965*795d594fSAndroid Build Coastguard Worker }
966*795d594fSAndroid Build Coastguard Worker FALLTHROUGH_INTENDED;
967*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
968*795d594fSAndroid Build Coastguard Worker __ Stored(InputXRegisterOrZero(value), rs1, offset);
969*795d594fSAndroid Build Coastguard Worker break;
970*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint32:
971*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint64:
972*795d594fSAndroid Build Coastguard Worker case DataType::Type::kVoid:
973*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unreachable type " << type;
974*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
975*795d594fSAndroid Build Coastguard Worker }
976*795d594fSAndroid Build Coastguard Worker }
977*795d594fSAndroid Build Coastguard Worker
StoreSeqCst(Location value,XRegister rs1,int32_t offset,DataType::Type type,HInstruction * instruction)978*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::StoreSeqCst(Location value,
979*795d594fSAndroid Build Coastguard Worker XRegister rs1,
980*795d594fSAndroid Build Coastguard Worker int32_t offset,
981*795d594fSAndroid Build Coastguard Worker DataType::Type type,
982*795d594fSAndroid Build Coastguard Worker HInstruction* instruction) {
983*795d594fSAndroid Build Coastguard Worker if (DataType::Size(type) >= 4u) {
984*795d594fSAndroid Build Coastguard Worker // Use AMOSWAP for 32-bit and 64-bit data types.
985*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
986*795d594fSAndroid Build Coastguard Worker XRegister swap_src = kNoXRegister;
987*795d594fSAndroid Build Coastguard Worker if (kPoisonHeapReferences && type == DataType::Type::kReference && !value.IsConstant()) {
988*795d594fSAndroid Build Coastguard Worker swap_src = srs.AllocateXRegister();
989*795d594fSAndroid Build Coastguard Worker __ Mv(swap_src, value.AsRegister<XRegister>());
990*795d594fSAndroid Build Coastguard Worker codegen_->PoisonHeapReference(swap_src);
991*795d594fSAndroid Build Coastguard Worker } else if (DataType::IsFloatingPointType(type) && !value.IsConstant()) {
992*795d594fSAndroid Build Coastguard Worker swap_src = srs.AllocateXRegister();
993*795d594fSAndroid Build Coastguard Worker FMvX(swap_src, value.AsFpuRegister<FRegister>(), type);
994*795d594fSAndroid Build Coastguard Worker } else {
995*795d594fSAndroid Build Coastguard Worker swap_src = InputXRegisterOrZero(value);
996*795d594fSAndroid Build Coastguard Worker }
997*795d594fSAndroid Build Coastguard Worker XRegister addr = rs1;
998*795d594fSAndroid Build Coastguard Worker if (offset != 0) {
999*795d594fSAndroid Build Coastguard Worker addr = srs.AllocateXRegister();
1000*795d594fSAndroid Build Coastguard Worker __ AddConst64(addr, rs1, offset);
1001*795d594fSAndroid Build Coastguard Worker }
1002*795d594fSAndroid Build Coastguard Worker if (DataType::Is64BitType(type)) {
1003*795d594fSAndroid Build Coastguard Worker __ AmoSwapD(Zero, swap_src, addr, AqRl::kRelease);
1004*795d594fSAndroid Build Coastguard Worker } else {
1005*795d594fSAndroid Build Coastguard Worker __ AmoSwapW(Zero, swap_src, addr, AqRl::kRelease);
1006*795d594fSAndroid Build Coastguard Worker }
1007*795d594fSAndroid Build Coastguard Worker if (instruction != nullptr) {
1008*795d594fSAndroid Build Coastguard Worker codegen_->MaybeRecordImplicitNullCheck(instruction);
1009*795d594fSAndroid Build Coastguard Worker }
1010*795d594fSAndroid Build Coastguard Worker } else {
1011*795d594fSAndroid Build Coastguard Worker // Use fences for smaller data types.
1012*795d594fSAndroid Build Coastguard Worker codegen_->GenerateMemoryBarrier(MemBarrierKind::kAnyStore);
1013*795d594fSAndroid Build Coastguard Worker Store(value, rs1, offset, type);
1014*795d594fSAndroid Build Coastguard Worker if (instruction != nullptr) {
1015*795d594fSAndroid Build Coastguard Worker codegen_->MaybeRecordImplicitNullCheck(instruction);
1016*795d594fSAndroid Build Coastguard Worker }
1017*795d594fSAndroid Build Coastguard Worker codegen_->GenerateMemoryBarrier(MemBarrierKind::kAnyAny);
1018*795d594fSAndroid Build Coastguard Worker }
1019*795d594fSAndroid Build Coastguard Worker }
1020*795d594fSAndroid Build Coastguard Worker
ShNAdd(XRegister rd,XRegister rs1,XRegister rs2,DataType::Type type)1021*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::ShNAdd(
1022*795d594fSAndroid Build Coastguard Worker XRegister rd, XRegister rs1, XRegister rs2, DataType::Type type) {
1023*795d594fSAndroid Build Coastguard Worker switch (type) {
1024*795d594fSAndroid Build Coastguard Worker case DataType::Type::kBool:
1025*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint8:
1026*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt8:
1027*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(DataType::SizeShift(type), 0u);
1028*795d594fSAndroid Build Coastguard Worker __ Add(rd, rs1, rs2);
1029*795d594fSAndroid Build Coastguard Worker break;
1030*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint16:
1031*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt16:
1032*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(DataType::SizeShift(type), 1u);
1033*795d594fSAndroid Build Coastguard Worker __ Sh1Add(rd, rs1, rs2);
1034*795d594fSAndroid Build Coastguard Worker break;
1035*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
1036*795d594fSAndroid Build Coastguard Worker case DataType::Type::kReference:
1037*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
1038*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(DataType::SizeShift(type), 2u);
1039*795d594fSAndroid Build Coastguard Worker __ Sh2Add(rd, rs1, rs2);
1040*795d594fSAndroid Build Coastguard Worker break;
1041*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
1042*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
1043*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(DataType::SizeShift(type), 3u);
1044*795d594fSAndroid Build Coastguard Worker __ Sh3Add(rd, rs1, rs2);
1045*795d594fSAndroid Build Coastguard Worker break;
1046*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint32:
1047*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint64:
1048*795d594fSAndroid Build Coastguard Worker case DataType::Type::kVoid:
1049*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unreachable type " << type;
1050*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
1051*795d594fSAndroid Build Coastguard Worker }
1052*795d594fSAndroid Build Coastguard Worker }
1053*795d594fSAndroid Build Coastguard Worker
GetAssembler() const1054*795d594fSAndroid Build Coastguard Worker Riscv64Assembler* ParallelMoveResolverRISCV64::GetAssembler() const {
1055*795d594fSAndroid Build Coastguard Worker return codegen_->GetAssembler();
1056*795d594fSAndroid Build Coastguard Worker }
1057*795d594fSAndroid Build Coastguard Worker
EmitMove(size_t index)1058*795d594fSAndroid Build Coastguard Worker void ParallelMoveResolverRISCV64::EmitMove(size_t index) {
1059*795d594fSAndroid Build Coastguard Worker MoveOperands* move = moves_[index];
1060*795d594fSAndroid Build Coastguard Worker codegen_->MoveLocation(move->GetDestination(), move->GetSource(), move->GetType());
1061*795d594fSAndroid Build Coastguard Worker }
1062*795d594fSAndroid Build Coastguard Worker
EmitSwap(size_t index)1063*795d594fSAndroid Build Coastguard Worker void ParallelMoveResolverRISCV64::EmitSwap(size_t index) {
1064*795d594fSAndroid Build Coastguard Worker MoveOperands* move = moves_[index];
1065*795d594fSAndroid Build Coastguard Worker codegen_->SwapLocations(move->GetDestination(), move->GetSource(), move->GetType());
1066*795d594fSAndroid Build Coastguard Worker }
1067*795d594fSAndroid Build Coastguard Worker
SpillScratch(int reg)1068*795d594fSAndroid Build Coastguard Worker void ParallelMoveResolverRISCV64::SpillScratch([[maybe_unused]] int reg) {
1069*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
1070*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
1071*795d594fSAndroid Build Coastguard Worker }
1072*795d594fSAndroid Build Coastguard Worker
RestoreScratch(int reg)1073*795d594fSAndroid Build Coastguard Worker void ParallelMoveResolverRISCV64::RestoreScratch([[maybe_unused]] int reg) {
1074*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
1075*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
1076*795d594fSAndroid Build Coastguard Worker }
1077*795d594fSAndroid Build Coastguard Worker
Exchange(int index1,int index2,bool double_slot)1078*795d594fSAndroid Build Coastguard Worker void ParallelMoveResolverRISCV64::Exchange(int index1, int index2, bool double_slot) {
1079*795d594fSAndroid Build Coastguard Worker // We have 2 scratch X registers and 1 scratch F register that we can use. We prefer
1080*795d594fSAndroid Build Coastguard Worker // to use X registers for the swap but if both offsets are too big, we need to reserve
1081*795d594fSAndroid Build Coastguard Worker // one of the X registers for address adjustment and use an F register.
1082*795d594fSAndroid Build Coastguard Worker bool use_fp_tmp2 = false;
1083*795d594fSAndroid Build Coastguard Worker if (!IsInt<12>(index2)) {
1084*795d594fSAndroid Build Coastguard Worker if (!IsInt<12>(index1)) {
1085*795d594fSAndroid Build Coastguard Worker use_fp_tmp2 = true;
1086*795d594fSAndroid Build Coastguard Worker } else {
1087*795d594fSAndroid Build Coastguard Worker std::swap(index1, index2);
1088*795d594fSAndroid Build Coastguard Worker }
1089*795d594fSAndroid Build Coastguard Worker }
1090*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(!IsInt<12>(index2), use_fp_tmp2);
1091*795d594fSAndroid Build Coastguard Worker
1092*795d594fSAndroid Build Coastguard Worker Location loc1(double_slot ? Location::DoubleStackSlot(index1) : Location::StackSlot(index1));
1093*795d594fSAndroid Build Coastguard Worker Location loc2(double_slot ? Location::DoubleStackSlot(index2) : Location::StackSlot(index2));
1094*795d594fSAndroid Build Coastguard Worker riscv64::ScratchRegisterScope srs(GetAssembler());
1095*795d594fSAndroid Build Coastguard Worker Location tmp = Location::RegisterLocation(srs.AllocateXRegister());
1096*795d594fSAndroid Build Coastguard Worker DataType::Type tmp_type = double_slot ? DataType::Type::kInt64 : DataType::Type::kInt32;
1097*795d594fSAndroid Build Coastguard Worker Location tmp2 = use_fp_tmp2
1098*795d594fSAndroid Build Coastguard Worker ? Location::FpuRegisterLocation(srs.AllocateFRegister())
1099*795d594fSAndroid Build Coastguard Worker : Location::RegisterLocation(srs.AllocateXRegister());
1100*795d594fSAndroid Build Coastguard Worker DataType::Type tmp2_type = use_fp_tmp2
1101*795d594fSAndroid Build Coastguard Worker ? (double_slot ? DataType::Type::kFloat64 : DataType::Type::kFloat32)
1102*795d594fSAndroid Build Coastguard Worker : tmp_type;
1103*795d594fSAndroid Build Coastguard Worker
1104*795d594fSAndroid Build Coastguard Worker codegen_->MoveLocation(tmp, loc1, tmp_type);
1105*795d594fSAndroid Build Coastguard Worker codegen_->MoveLocation(tmp2, loc2, tmp2_type);
1106*795d594fSAndroid Build Coastguard Worker if (use_fp_tmp2) {
1107*795d594fSAndroid Build Coastguard Worker codegen_->MoveLocation(loc2, tmp, tmp_type);
1108*795d594fSAndroid Build Coastguard Worker } else {
1109*795d594fSAndroid Build Coastguard Worker // We cannot use `Stored()` or `Storew()` via `MoveLocation()` because we have
1110*795d594fSAndroid Build Coastguard Worker // no more scratch registers available. Use `Sd()` or `Sw()` explicitly.
1111*795d594fSAndroid Build Coastguard Worker DCHECK(IsInt<12>(index2));
1112*795d594fSAndroid Build Coastguard Worker if (double_slot) {
1113*795d594fSAndroid Build Coastguard Worker __ Sd(tmp.AsRegister<XRegister>(), SP, index2);
1114*795d594fSAndroid Build Coastguard Worker } else {
1115*795d594fSAndroid Build Coastguard Worker __ Sw(tmp.AsRegister<XRegister>(), SP, index2);
1116*795d594fSAndroid Build Coastguard Worker }
1117*795d594fSAndroid Build Coastguard Worker srs.FreeXRegister(tmp.AsRegister<XRegister>()); // Free a temporary for `MoveLocation()`.
1118*795d594fSAndroid Build Coastguard Worker }
1119*795d594fSAndroid Build Coastguard Worker codegen_->MoveLocation(loc1, tmp2, tmp2_type);
1120*795d594fSAndroid Build Coastguard Worker }
1121*795d594fSAndroid Build Coastguard Worker
InstructionCodeGeneratorRISCV64(HGraph * graph,CodeGeneratorRISCV64 * codegen)1122*795d594fSAndroid Build Coastguard Worker InstructionCodeGeneratorRISCV64::InstructionCodeGeneratorRISCV64(HGraph* graph,
1123*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64* codegen)
1124*795d594fSAndroid Build Coastguard Worker : InstructionCodeGenerator(graph, codegen),
1125*795d594fSAndroid Build Coastguard Worker assembler_(codegen->GetAssembler()),
1126*795d594fSAndroid Build Coastguard Worker codegen_(codegen) {}
1127*795d594fSAndroid Build Coastguard Worker
GenerateClassInitializationCheck(SlowPathCodeRISCV64 * slow_path,XRegister class_reg)1128*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenerateClassInitializationCheck(
1129*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path, XRegister class_reg) {
1130*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
1131*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
1132*795d594fSAndroid Build Coastguard Worker XRegister tmp2 = srs.AllocateXRegister();
1133*795d594fSAndroid Build Coastguard Worker
1134*795d594fSAndroid Build Coastguard Worker // We shall load the full 32-bit status word with sign-extension and compare as unsigned
1135*795d594fSAndroid Build Coastguard Worker // to a sign-extended shifted status value. This yields the same comparison as loading and
1136*795d594fSAndroid Build Coastguard Worker // materializing unsigned but the constant is materialized with a single LUI instruction.
1137*795d594fSAndroid Build Coastguard Worker __ Loadw(tmp, class_reg, mirror::Class::StatusOffset().SizeValue()); // Sign-extended.
1138*795d594fSAndroid Build Coastguard Worker __ Li(tmp2, ShiftedSignExtendedClassStatusValue<ClassStatus::kVisiblyInitialized>());
1139*795d594fSAndroid Build Coastguard Worker __ Bltu(tmp, tmp2, slow_path->GetEntryLabel());
1140*795d594fSAndroid Build Coastguard Worker __ Bind(slow_path->GetExitLabel());
1141*795d594fSAndroid Build Coastguard Worker }
1142*795d594fSAndroid Build Coastguard Worker
GenerateBitstringTypeCheckCompare(HTypeCheckInstruction * instruction,XRegister temp)1143*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenerateBitstringTypeCheckCompare(
1144*795d594fSAndroid Build Coastguard Worker HTypeCheckInstruction* instruction, XRegister temp) {
1145*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
1146*795d594fSAndroid Build Coastguard Worker UNUSED(temp);
1147*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
1148*795d594fSAndroid Build Coastguard Worker }
1149*795d594fSAndroid Build Coastguard Worker
GenerateSuspendCheck(HSuspendCheck * instruction,HBasicBlock * successor)1150*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenerateSuspendCheck(HSuspendCheck* instruction,
1151*795d594fSAndroid Build Coastguard Worker HBasicBlock* successor) {
1152*795d594fSAndroid Build Coastguard Worker if (instruction->IsNoOp()) {
1153*795d594fSAndroid Build Coastguard Worker if (successor != nullptr) {
1154*795d594fSAndroid Build Coastguard Worker __ J(codegen_->GetLabelOf(successor));
1155*795d594fSAndroid Build Coastguard Worker }
1156*795d594fSAndroid Build Coastguard Worker return;
1157*795d594fSAndroid Build Coastguard Worker }
1158*795d594fSAndroid Build Coastguard Worker
1159*795d594fSAndroid Build Coastguard Worker if (codegen_->CanUseImplicitSuspendCheck()) {
1160*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented ImplicitSuspendCheck";
1161*795d594fSAndroid Build Coastguard Worker return;
1162*795d594fSAndroid Build Coastguard Worker }
1163*795d594fSAndroid Build Coastguard Worker
1164*795d594fSAndroid Build Coastguard Worker SuspendCheckSlowPathRISCV64* slow_path =
1165*795d594fSAndroid Build Coastguard Worker down_cast<SuspendCheckSlowPathRISCV64*>(instruction->GetSlowPath());
1166*795d594fSAndroid Build Coastguard Worker
1167*795d594fSAndroid Build Coastguard Worker if (slow_path == nullptr) {
1168*795d594fSAndroid Build Coastguard Worker slow_path =
1169*795d594fSAndroid Build Coastguard Worker new (codegen_->GetScopedAllocator()) SuspendCheckSlowPathRISCV64(instruction, successor);
1170*795d594fSAndroid Build Coastguard Worker instruction->SetSlowPath(slow_path);
1171*795d594fSAndroid Build Coastguard Worker codegen_->AddSlowPath(slow_path);
1172*795d594fSAndroid Build Coastguard Worker if (successor != nullptr) {
1173*795d594fSAndroid Build Coastguard Worker DCHECK(successor->IsLoopHeader());
1174*795d594fSAndroid Build Coastguard Worker }
1175*795d594fSAndroid Build Coastguard Worker } else {
1176*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(slow_path->GetSuccessor(), successor);
1177*795d594fSAndroid Build Coastguard Worker }
1178*795d594fSAndroid Build Coastguard Worker
1179*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
1180*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
1181*795d594fSAndroid Build Coastguard Worker __ Loadw(tmp, TR, Thread::ThreadFlagsOffset<kRiscv64PointerSize>().Int32Value());
1182*795d594fSAndroid Build Coastguard Worker static_assert(Thread::SuspendOrCheckpointRequestFlags() != std::numeric_limits<uint32_t>::max());
1183*795d594fSAndroid Build Coastguard Worker static_assert(IsPowerOfTwo(Thread::SuspendOrCheckpointRequestFlags() + 1u));
1184*795d594fSAndroid Build Coastguard Worker // Shift out other bits. Use an instruction that can be 16-bit with the "C" Standard Extension.
1185*795d594fSAndroid Build Coastguard Worker __ Slli(tmp, tmp, CLZ(static_cast<uint64_t>(Thread::SuspendOrCheckpointRequestFlags())));
1186*795d594fSAndroid Build Coastguard Worker if (successor == nullptr) {
1187*795d594fSAndroid Build Coastguard Worker __ Bnez(tmp, slow_path->GetEntryLabel());
1188*795d594fSAndroid Build Coastguard Worker __ Bind(slow_path->GetReturnLabel());
1189*795d594fSAndroid Build Coastguard Worker } else {
1190*795d594fSAndroid Build Coastguard Worker __ Beqz(tmp, codegen_->GetLabelOf(successor));
1191*795d594fSAndroid Build Coastguard Worker __ J(slow_path->GetEntryLabel());
1192*795d594fSAndroid Build Coastguard Worker // slow_path will return to GetLabelOf(successor).
1193*795d594fSAndroid Build Coastguard Worker }
1194*795d594fSAndroid Build Coastguard Worker }
1195*795d594fSAndroid Build Coastguard Worker
GenerateReferenceLoadOneRegister(HInstruction * instruction,Location out,uint32_t offset,Location maybe_temp,ReadBarrierOption read_barrier_option)1196*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenerateReferenceLoadOneRegister(
1197*795d594fSAndroid Build Coastguard Worker HInstruction* instruction,
1198*795d594fSAndroid Build Coastguard Worker Location out,
1199*795d594fSAndroid Build Coastguard Worker uint32_t offset,
1200*795d594fSAndroid Build Coastguard Worker Location maybe_temp,
1201*795d594fSAndroid Build Coastguard Worker ReadBarrierOption read_barrier_option) {
1202*795d594fSAndroid Build Coastguard Worker XRegister out_reg = out.AsRegister<XRegister>();
1203*795d594fSAndroid Build Coastguard Worker if (read_barrier_option == kWithReadBarrier) {
1204*795d594fSAndroid Build Coastguard Worker DCHECK(codegen_->EmitReadBarrier());
1205*795d594fSAndroid Build Coastguard Worker if (kUseBakerReadBarrier) {
1206*795d594fSAndroid Build Coastguard Worker // Load with fast path based Baker's read barrier.
1207*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Object> */ out = *(out + offset)
1208*795d594fSAndroid Build Coastguard Worker codegen_->GenerateFieldLoadWithBakerReadBarrier(instruction,
1209*795d594fSAndroid Build Coastguard Worker out,
1210*795d594fSAndroid Build Coastguard Worker out_reg,
1211*795d594fSAndroid Build Coastguard Worker offset,
1212*795d594fSAndroid Build Coastguard Worker maybe_temp,
1213*795d594fSAndroid Build Coastguard Worker /* needs_null_check= */ false);
1214*795d594fSAndroid Build Coastguard Worker } else {
1215*795d594fSAndroid Build Coastguard Worker // Load with slow path based read barrier.
1216*795d594fSAndroid Build Coastguard Worker // Save the value of `out` into `maybe_temp` before overwriting it
1217*795d594fSAndroid Build Coastguard Worker // in the following move operation, as we will need it for the
1218*795d594fSAndroid Build Coastguard Worker // read barrier below.
1219*795d594fSAndroid Build Coastguard Worker __ Mv(maybe_temp.AsRegister<XRegister>(), out_reg);
1220*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Object> */ out = *(out + offset)
1221*795d594fSAndroid Build Coastguard Worker __ Loadwu(out_reg, out_reg, offset);
1222*795d594fSAndroid Build Coastguard Worker codegen_->GenerateReadBarrierSlow(instruction, out, out, maybe_temp, offset);
1223*795d594fSAndroid Build Coastguard Worker }
1224*795d594fSAndroid Build Coastguard Worker } else {
1225*795d594fSAndroid Build Coastguard Worker // Plain load with no read barrier.
1226*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Object> */ out = *(out + offset)
1227*795d594fSAndroid Build Coastguard Worker __ Loadwu(out_reg, out_reg, offset);
1228*795d594fSAndroid Build Coastguard Worker codegen_->MaybeUnpoisonHeapReference(out_reg);
1229*795d594fSAndroid Build Coastguard Worker }
1230*795d594fSAndroid Build Coastguard Worker }
1231*795d594fSAndroid Build Coastguard Worker
GenerateReferenceLoadTwoRegisters(HInstruction * instruction,Location out,Location obj,uint32_t offset,Location maybe_temp,ReadBarrierOption read_barrier_option)1232*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenerateReferenceLoadTwoRegisters(
1233*795d594fSAndroid Build Coastguard Worker HInstruction* instruction,
1234*795d594fSAndroid Build Coastguard Worker Location out,
1235*795d594fSAndroid Build Coastguard Worker Location obj,
1236*795d594fSAndroid Build Coastguard Worker uint32_t offset,
1237*795d594fSAndroid Build Coastguard Worker Location maybe_temp,
1238*795d594fSAndroid Build Coastguard Worker ReadBarrierOption read_barrier_option) {
1239*795d594fSAndroid Build Coastguard Worker XRegister out_reg = out.AsRegister<XRegister>();
1240*795d594fSAndroid Build Coastguard Worker XRegister obj_reg = obj.AsRegister<XRegister>();
1241*795d594fSAndroid Build Coastguard Worker if (read_barrier_option == kWithReadBarrier) {
1242*795d594fSAndroid Build Coastguard Worker DCHECK(codegen_->EmitReadBarrier());
1243*795d594fSAndroid Build Coastguard Worker if (kUseBakerReadBarrier) {
1244*795d594fSAndroid Build Coastguard Worker // Load with fast path based Baker's read barrier.
1245*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Object> */ out = *(obj + offset)
1246*795d594fSAndroid Build Coastguard Worker codegen_->GenerateFieldLoadWithBakerReadBarrier(instruction,
1247*795d594fSAndroid Build Coastguard Worker out,
1248*795d594fSAndroid Build Coastguard Worker obj_reg,
1249*795d594fSAndroid Build Coastguard Worker offset,
1250*795d594fSAndroid Build Coastguard Worker maybe_temp,
1251*795d594fSAndroid Build Coastguard Worker /* needs_null_check= */ false);
1252*795d594fSAndroid Build Coastguard Worker } else {
1253*795d594fSAndroid Build Coastguard Worker // Load with slow path based read barrier.
1254*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Object> */ out = *(obj + offset)
1255*795d594fSAndroid Build Coastguard Worker __ Loadwu(out_reg, obj_reg, offset);
1256*795d594fSAndroid Build Coastguard Worker codegen_->GenerateReadBarrierSlow(instruction, out, out, obj, offset);
1257*795d594fSAndroid Build Coastguard Worker }
1258*795d594fSAndroid Build Coastguard Worker } else {
1259*795d594fSAndroid Build Coastguard Worker // Plain load with no read barrier.
1260*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Object> */ out = *(obj + offset)
1261*795d594fSAndroid Build Coastguard Worker __ Loadwu(out_reg, obj_reg, offset);
1262*795d594fSAndroid Build Coastguard Worker codegen_->MaybeUnpoisonHeapReference(out_reg);
1263*795d594fSAndroid Build Coastguard Worker }
1264*795d594fSAndroid Build Coastguard Worker }
1265*795d594fSAndroid Build Coastguard Worker
AddGcRootBakerBarrierBarrierSlowPath(HInstruction * instruction,Location root,Location temp)1266*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* CodeGeneratorRISCV64::AddGcRootBakerBarrierBarrierSlowPath(
1267*795d594fSAndroid Build Coastguard Worker HInstruction* instruction, Location root, Location temp) {
1268*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path =
1269*795d594fSAndroid Build Coastguard Worker new (GetScopedAllocator()) ReadBarrierMarkSlowPathRISCV64(instruction, root, temp);
1270*795d594fSAndroid Build Coastguard Worker AddSlowPath(slow_path);
1271*795d594fSAndroid Build Coastguard Worker return slow_path;
1272*795d594fSAndroid Build Coastguard Worker }
1273*795d594fSAndroid Build Coastguard Worker
EmitBakerReadBarierMarkingCheck(SlowPathCodeRISCV64 * slow_path,Location root,Location temp)1274*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::EmitBakerReadBarierMarkingCheck(
1275*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path, Location root, Location temp) {
1276*795d594fSAndroid Build Coastguard Worker const int32_t entry_point_offset = ReadBarrierMarkEntrypointOffset(root);
1277*795d594fSAndroid Build Coastguard Worker // Loading the entrypoint does not require a load acquire since it is only changed when
1278*795d594fSAndroid Build Coastguard Worker // threads are suspended or running a checkpoint.
1279*795d594fSAndroid Build Coastguard Worker __ Loadd(temp.AsRegister<XRegister>(), TR, entry_point_offset);
1280*795d594fSAndroid Build Coastguard Worker __ Bnez(temp.AsRegister<XRegister>(), slow_path->GetEntryLabel());
1281*795d594fSAndroid Build Coastguard Worker __ Bind(slow_path->GetExitLabel());
1282*795d594fSAndroid Build Coastguard Worker }
1283*795d594fSAndroid Build Coastguard Worker
GenerateGcRootFieldLoad(HInstruction * instruction,Location root,XRegister obj,uint32_t offset,ReadBarrierOption read_barrier_option,Riscv64Label * label_low)1284*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::GenerateGcRootFieldLoad(HInstruction* instruction,
1285*795d594fSAndroid Build Coastguard Worker Location root,
1286*795d594fSAndroid Build Coastguard Worker XRegister obj,
1287*795d594fSAndroid Build Coastguard Worker uint32_t offset,
1288*795d594fSAndroid Build Coastguard Worker ReadBarrierOption read_barrier_option,
1289*795d594fSAndroid Build Coastguard Worker Riscv64Label* label_low) {
1290*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(label_low != nullptr, offset == kLinkTimeOffsetPlaceholderLow) << offset;
1291*795d594fSAndroid Build Coastguard Worker XRegister root_reg = root.AsRegister<XRegister>();
1292*795d594fSAndroid Build Coastguard Worker if (read_barrier_option == kWithReadBarrier) {
1293*795d594fSAndroid Build Coastguard Worker DCHECK(EmitReadBarrier());
1294*795d594fSAndroid Build Coastguard Worker if (kUseBakerReadBarrier) {
1295*795d594fSAndroid Build Coastguard Worker // Note that we do not actually check the value of `GetIsGcMarking()`
1296*795d594fSAndroid Build Coastguard Worker // to decide whether to mark the loaded GC root or not. Instead, we
1297*795d594fSAndroid Build Coastguard Worker // load into `temp` (T6) the read barrier mark entry point corresponding
1298*795d594fSAndroid Build Coastguard Worker // to register `root`. If `temp` is null, it means that `GetIsGcMarking()`
1299*795d594fSAndroid Build Coastguard Worker // is false, and vice versa.
1300*795d594fSAndroid Build Coastguard Worker //
1301*795d594fSAndroid Build Coastguard Worker // GcRoot<mirror::Object> root = *(obj+offset); // Original reference load.
1302*795d594fSAndroid Build Coastguard Worker // temp = Thread::Current()->pReadBarrierMarkReg ## root.reg()
1303*795d594fSAndroid Build Coastguard Worker // if (temp != null) {
1304*795d594fSAndroid Build Coastguard Worker // root = temp(root)
1305*795d594fSAndroid Build Coastguard Worker // }
1306*795d594fSAndroid Build Coastguard Worker //
1307*795d594fSAndroid Build Coastguard Worker // TODO(riscv64): Introduce a "marking register" that holds the pointer to one of the
1308*795d594fSAndroid Build Coastguard Worker // register marking entrypoints if marking (null if not marking) and make sure that
1309*795d594fSAndroid Build Coastguard Worker // marking entrypoints for other registers are at known offsets, so that we can call
1310*795d594fSAndroid Build Coastguard Worker // them using the "marking register" plus the offset embedded in the JALR instruction.
1311*795d594fSAndroid Build Coastguard Worker
1312*795d594fSAndroid Build Coastguard Worker if (label_low != nullptr) {
1313*795d594fSAndroid Build Coastguard Worker __ Bind(label_low);
1314*795d594fSAndroid Build Coastguard Worker }
1315*795d594fSAndroid Build Coastguard Worker // /* GcRoot<mirror::Object> */ root = *(obj + offset)
1316*795d594fSAndroid Build Coastguard Worker __ Loadwu(root_reg, obj, offset);
1317*795d594fSAndroid Build Coastguard Worker static_assert(
1318*795d594fSAndroid Build Coastguard Worker sizeof(mirror::CompressedReference<mirror::Object>) == sizeof(GcRoot<mirror::Object>),
1319*795d594fSAndroid Build Coastguard Worker "art::mirror::CompressedReference<mirror::Object> and art::GcRoot<mirror::Object> "
1320*795d594fSAndroid Build Coastguard Worker "have different sizes.");
1321*795d594fSAndroid Build Coastguard Worker static_assert(sizeof(mirror::CompressedReference<mirror::Object>) == sizeof(int32_t),
1322*795d594fSAndroid Build Coastguard Worker "art::mirror::CompressedReference<mirror::Object> and int32_t "
1323*795d594fSAndroid Build Coastguard Worker "have different sizes.");
1324*795d594fSAndroid Build Coastguard Worker
1325*795d594fSAndroid Build Coastguard Worker // Use RA as temp. It is clobbered in the slow path anyway.
1326*795d594fSAndroid Build Coastguard Worker Location temp = Location::RegisterLocation(RA);
1327*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path =
1328*795d594fSAndroid Build Coastguard Worker AddGcRootBakerBarrierBarrierSlowPath(instruction, root, temp);
1329*795d594fSAndroid Build Coastguard Worker EmitBakerReadBarierMarkingCheck(slow_path, root, temp);
1330*795d594fSAndroid Build Coastguard Worker } else {
1331*795d594fSAndroid Build Coastguard Worker // GC root loaded through a slow path for read barriers other
1332*795d594fSAndroid Build Coastguard Worker // than Baker's.
1333*795d594fSAndroid Build Coastguard Worker // /* GcRoot<mirror::Object>* */ root = obj + offset
1334*795d594fSAndroid Build Coastguard Worker if (label_low != nullptr) {
1335*795d594fSAndroid Build Coastguard Worker __ Bind(label_low);
1336*795d594fSAndroid Build Coastguard Worker }
1337*795d594fSAndroid Build Coastguard Worker __ AddConst32(root_reg, obj, offset);
1338*795d594fSAndroid Build Coastguard Worker // /* mirror::Object* */ root = root->Read()
1339*795d594fSAndroid Build Coastguard Worker GenerateReadBarrierForRootSlow(instruction, root, root);
1340*795d594fSAndroid Build Coastguard Worker }
1341*795d594fSAndroid Build Coastguard Worker } else {
1342*795d594fSAndroid Build Coastguard Worker // Plain GC root load with no read barrier.
1343*795d594fSAndroid Build Coastguard Worker // /* GcRoot<mirror::Object> */ root = *(obj + offset)
1344*795d594fSAndroid Build Coastguard Worker if (label_low != nullptr) {
1345*795d594fSAndroid Build Coastguard Worker __ Bind(label_low);
1346*795d594fSAndroid Build Coastguard Worker }
1347*795d594fSAndroid Build Coastguard Worker __ Loadwu(root_reg, obj, offset);
1348*795d594fSAndroid Build Coastguard Worker // Note that GC roots are not affected by heap poisoning, thus we
1349*795d594fSAndroid Build Coastguard Worker // do not have to unpoison `root_reg` here.
1350*795d594fSAndroid Build Coastguard Worker }
1351*795d594fSAndroid Build Coastguard Worker }
1352*795d594fSAndroid Build Coastguard Worker
GenerateTestAndBranch(HInstruction * instruction,size_t condition_input_index,Riscv64Label * true_target,Riscv64Label * false_target)1353*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenerateTestAndBranch(HInstruction* instruction,
1354*795d594fSAndroid Build Coastguard Worker size_t condition_input_index,
1355*795d594fSAndroid Build Coastguard Worker Riscv64Label* true_target,
1356*795d594fSAndroid Build Coastguard Worker Riscv64Label* false_target) {
1357*795d594fSAndroid Build Coastguard Worker HInstruction* cond = instruction->InputAt(condition_input_index);
1358*795d594fSAndroid Build Coastguard Worker
1359*795d594fSAndroid Build Coastguard Worker if (true_target == nullptr && false_target == nullptr) {
1360*795d594fSAndroid Build Coastguard Worker // Nothing to do. The code always falls through.
1361*795d594fSAndroid Build Coastguard Worker return;
1362*795d594fSAndroid Build Coastguard Worker } else if (cond->IsIntConstant()) {
1363*795d594fSAndroid Build Coastguard Worker // Constant condition, statically compared against "true" (integer value 1).
1364*795d594fSAndroid Build Coastguard Worker if (cond->AsIntConstant()->IsTrue()) {
1365*795d594fSAndroid Build Coastguard Worker if (true_target != nullptr) {
1366*795d594fSAndroid Build Coastguard Worker __ J(true_target);
1367*795d594fSAndroid Build Coastguard Worker }
1368*795d594fSAndroid Build Coastguard Worker } else {
1369*795d594fSAndroid Build Coastguard Worker DCHECK(cond->AsIntConstant()->IsFalse()) << cond->AsIntConstant()->GetValue();
1370*795d594fSAndroid Build Coastguard Worker if (false_target != nullptr) {
1371*795d594fSAndroid Build Coastguard Worker __ J(false_target);
1372*795d594fSAndroid Build Coastguard Worker }
1373*795d594fSAndroid Build Coastguard Worker }
1374*795d594fSAndroid Build Coastguard Worker return;
1375*795d594fSAndroid Build Coastguard Worker }
1376*795d594fSAndroid Build Coastguard Worker
1377*795d594fSAndroid Build Coastguard Worker // The following code generates these patterns:
1378*795d594fSAndroid Build Coastguard Worker // (1) true_target == nullptr && false_target != nullptr
1379*795d594fSAndroid Build Coastguard Worker // - opposite condition true => branch to false_target
1380*795d594fSAndroid Build Coastguard Worker // (2) true_target != nullptr && false_target == nullptr
1381*795d594fSAndroid Build Coastguard Worker // - condition true => branch to true_target
1382*795d594fSAndroid Build Coastguard Worker // (3) true_target != nullptr && false_target != nullptr
1383*795d594fSAndroid Build Coastguard Worker // - condition true => branch to true_target
1384*795d594fSAndroid Build Coastguard Worker // - branch to false_target
1385*795d594fSAndroid Build Coastguard Worker if (IsBooleanValueOrMaterializedCondition(cond)) {
1386*795d594fSAndroid Build Coastguard Worker // The condition instruction has been materialized, compare the output to 0.
1387*795d594fSAndroid Build Coastguard Worker Location cond_val = instruction->GetLocations()->InAt(condition_input_index);
1388*795d594fSAndroid Build Coastguard Worker DCHECK(cond_val.IsRegister());
1389*795d594fSAndroid Build Coastguard Worker if (true_target == nullptr) {
1390*795d594fSAndroid Build Coastguard Worker __ Beqz(cond_val.AsRegister<XRegister>(), false_target);
1391*795d594fSAndroid Build Coastguard Worker } else {
1392*795d594fSAndroid Build Coastguard Worker __ Bnez(cond_val.AsRegister<XRegister>(), true_target);
1393*795d594fSAndroid Build Coastguard Worker }
1394*795d594fSAndroid Build Coastguard Worker } else {
1395*795d594fSAndroid Build Coastguard Worker // The condition instruction has not been materialized, use its inputs as
1396*795d594fSAndroid Build Coastguard Worker // the comparison and its condition as the branch condition.
1397*795d594fSAndroid Build Coastguard Worker HCondition* condition = cond->AsCondition();
1398*795d594fSAndroid Build Coastguard Worker DataType::Type type = condition->InputAt(0)->GetType();
1399*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = condition->GetLocations();
1400*795d594fSAndroid Build Coastguard Worker IfCondition if_cond = condition->GetCondition();
1401*795d594fSAndroid Build Coastguard Worker Riscv64Label* branch_target = true_target;
1402*795d594fSAndroid Build Coastguard Worker
1403*795d594fSAndroid Build Coastguard Worker if (true_target == nullptr) {
1404*795d594fSAndroid Build Coastguard Worker if_cond = condition->GetOppositeCondition();
1405*795d594fSAndroid Build Coastguard Worker branch_target = false_target;
1406*795d594fSAndroid Build Coastguard Worker }
1407*795d594fSAndroid Build Coastguard Worker
1408*795d594fSAndroid Build Coastguard Worker switch (type) {
1409*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
1410*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
1411*795d594fSAndroid Build Coastguard Worker GenerateFpCondition(if_cond, condition->IsGtBias(), type, locations, branch_target);
1412*795d594fSAndroid Build Coastguard Worker break;
1413*795d594fSAndroid Build Coastguard Worker default:
1414*795d594fSAndroid Build Coastguard Worker // Integral types and reference equality.
1415*795d594fSAndroid Build Coastguard Worker GenerateIntLongCompareAndBranch(if_cond, locations, branch_target);
1416*795d594fSAndroid Build Coastguard Worker break;
1417*795d594fSAndroid Build Coastguard Worker }
1418*795d594fSAndroid Build Coastguard Worker }
1419*795d594fSAndroid Build Coastguard Worker
1420*795d594fSAndroid Build Coastguard Worker // If neither branch falls through (case 3), the conditional branch to `true_target`
1421*795d594fSAndroid Build Coastguard Worker // was already emitted (case 2) and we need to emit a jump to `false_target`.
1422*795d594fSAndroid Build Coastguard Worker if (true_target != nullptr && false_target != nullptr) {
1423*795d594fSAndroid Build Coastguard Worker __ J(false_target);
1424*795d594fSAndroid Build Coastguard Worker }
1425*795d594fSAndroid Build Coastguard Worker }
1426*795d594fSAndroid Build Coastguard Worker
DivRemOneOrMinusOne(HBinaryOperation * instruction)1427*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::DivRemOneOrMinusOne(HBinaryOperation* instruction) {
1428*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsDiv() || instruction->IsRem());
1429*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetResultType();
1430*795d594fSAndroid Build Coastguard Worker
1431*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
1432*795d594fSAndroid Build Coastguard Worker Location second = locations->InAt(1);
1433*795d594fSAndroid Build Coastguard Worker DCHECK(second.IsConstant());
1434*795d594fSAndroid Build Coastguard Worker
1435*795d594fSAndroid Build Coastguard Worker XRegister out = locations->Out().AsRegister<XRegister>();
1436*795d594fSAndroid Build Coastguard Worker XRegister dividend = locations->InAt(0).AsRegister<XRegister>();
1437*795d594fSAndroid Build Coastguard Worker int64_t imm = Int64FromConstant(second.GetConstant());
1438*795d594fSAndroid Build Coastguard Worker DCHECK(imm == 1 || imm == -1);
1439*795d594fSAndroid Build Coastguard Worker
1440*795d594fSAndroid Build Coastguard Worker if (instruction->IsRem()) {
1441*795d594fSAndroid Build Coastguard Worker __ Mv(out, Zero);
1442*795d594fSAndroid Build Coastguard Worker } else {
1443*795d594fSAndroid Build Coastguard Worker if (imm == -1) {
1444*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kInt32) {
1445*795d594fSAndroid Build Coastguard Worker __ Subw(out, Zero, dividend);
1446*795d594fSAndroid Build Coastguard Worker } else {
1447*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(type, DataType::Type::kInt64);
1448*795d594fSAndroid Build Coastguard Worker __ Sub(out, Zero, dividend);
1449*795d594fSAndroid Build Coastguard Worker }
1450*795d594fSAndroid Build Coastguard Worker } else if (out != dividend) {
1451*795d594fSAndroid Build Coastguard Worker __ Mv(out, dividend);
1452*795d594fSAndroid Build Coastguard Worker }
1453*795d594fSAndroid Build Coastguard Worker }
1454*795d594fSAndroid Build Coastguard Worker }
1455*795d594fSAndroid Build Coastguard Worker
DivRemByPowerOfTwo(HBinaryOperation * instruction)1456*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::DivRemByPowerOfTwo(HBinaryOperation* instruction) {
1457*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsDiv() || instruction->IsRem());
1458*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetResultType();
1459*795d594fSAndroid Build Coastguard Worker DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64) << type;
1460*795d594fSAndroid Build Coastguard Worker
1461*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
1462*795d594fSAndroid Build Coastguard Worker Location second = locations->InAt(1);
1463*795d594fSAndroid Build Coastguard Worker DCHECK(second.IsConstant());
1464*795d594fSAndroid Build Coastguard Worker
1465*795d594fSAndroid Build Coastguard Worker XRegister out = locations->Out().AsRegister<XRegister>();
1466*795d594fSAndroid Build Coastguard Worker XRegister dividend = locations->InAt(0).AsRegister<XRegister>();
1467*795d594fSAndroid Build Coastguard Worker int64_t imm = Int64FromConstant(second.GetConstant());
1468*795d594fSAndroid Build Coastguard Worker int64_t abs_imm = static_cast<uint64_t>(AbsOrMin(imm));
1469*795d594fSAndroid Build Coastguard Worker int ctz_imm = CTZ(abs_imm);
1470*795d594fSAndroid Build Coastguard Worker DCHECK_GE(ctz_imm, 1); // Division by +/-1 is handled by `DivRemOneOrMinusOne()`.
1471*795d594fSAndroid Build Coastguard Worker
1472*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
1473*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
1474*795d594fSAndroid Build Coastguard Worker // Calculate the negative dividend adjustment `tmp = dividend < 0 ? abs_imm - 1 : 0`.
1475*795d594fSAndroid Build Coastguard Worker // This adjustment is needed for rounding the division result towards zero.
1476*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kInt32 || ctz_imm == 1) {
1477*795d594fSAndroid Build Coastguard Worker // A 32-bit dividend is sign-extended to 64-bit, so we can use the upper bits.
1478*795d594fSAndroid Build Coastguard Worker // And for a 64-bit division by +/-2, we need just the sign bit.
1479*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(type == DataType::Type::kInt32, ctz_imm < 32);
1480*795d594fSAndroid Build Coastguard Worker __ Srli(tmp, dividend, 64 - ctz_imm);
1481*795d594fSAndroid Build Coastguard Worker } else {
1482*795d594fSAndroid Build Coastguard Worker // For other 64-bit divisions, we need to replicate the sign bit.
1483*795d594fSAndroid Build Coastguard Worker __ Srai(tmp, dividend, 63);
1484*795d594fSAndroid Build Coastguard Worker __ Srli(tmp, tmp, 64 - ctz_imm);
1485*795d594fSAndroid Build Coastguard Worker }
1486*795d594fSAndroid Build Coastguard Worker // The rest of the calculation can use 64-bit operations even for 32-bit div/rem.
1487*795d594fSAndroid Build Coastguard Worker __ Add(tmp, tmp, dividend);
1488*795d594fSAndroid Build Coastguard Worker if (instruction->IsDiv()) {
1489*795d594fSAndroid Build Coastguard Worker __ Srai(out, tmp, ctz_imm);
1490*795d594fSAndroid Build Coastguard Worker if (imm < 0) {
1491*795d594fSAndroid Build Coastguard Worker __ Neg(out, out);
1492*795d594fSAndroid Build Coastguard Worker }
1493*795d594fSAndroid Build Coastguard Worker } else {
1494*795d594fSAndroid Build Coastguard Worker if (ctz_imm <= 11) {
1495*795d594fSAndroid Build Coastguard Worker __ Andi(tmp, tmp, -abs_imm);
1496*795d594fSAndroid Build Coastguard Worker } else {
1497*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs2(GetAssembler());
1498*795d594fSAndroid Build Coastguard Worker XRegister tmp2 = srs2.AllocateXRegister();
1499*795d594fSAndroid Build Coastguard Worker __ Li(tmp2, -abs_imm);
1500*795d594fSAndroid Build Coastguard Worker __ And(tmp, tmp, tmp2);
1501*795d594fSAndroid Build Coastguard Worker }
1502*795d594fSAndroid Build Coastguard Worker __ Sub(out, dividend, tmp);
1503*795d594fSAndroid Build Coastguard Worker }
1504*795d594fSAndroid Build Coastguard Worker }
1505*795d594fSAndroid Build Coastguard Worker
GenerateDivRemWithAnyConstant(HBinaryOperation * instruction)1506*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenerateDivRemWithAnyConstant(HBinaryOperation* instruction) {
1507*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsDiv() || instruction->IsRem());
1508*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
1509*795d594fSAndroid Build Coastguard Worker XRegister dividend = locations->InAt(0).AsRegister<XRegister>();
1510*795d594fSAndroid Build Coastguard Worker XRegister out = locations->Out().AsRegister<XRegister>();
1511*795d594fSAndroid Build Coastguard Worker Location second = locations->InAt(1);
1512*795d594fSAndroid Build Coastguard Worker int64_t imm = Int64FromConstant(second.GetConstant());
1513*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetResultType();
1514*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
1515*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
1516*795d594fSAndroid Build Coastguard Worker
1517*795d594fSAndroid Build Coastguard Worker // TODO: optimize with constant.
1518*795d594fSAndroid Build Coastguard Worker __ LoadConst64(tmp, imm);
1519*795d594fSAndroid Build Coastguard Worker if (instruction->IsDiv()) {
1520*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kInt32) {
1521*795d594fSAndroid Build Coastguard Worker __ Divw(out, dividend, tmp);
1522*795d594fSAndroid Build Coastguard Worker } else {
1523*795d594fSAndroid Build Coastguard Worker __ Div(out, dividend, tmp);
1524*795d594fSAndroid Build Coastguard Worker }
1525*795d594fSAndroid Build Coastguard Worker } else {
1526*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kInt32) {
1527*795d594fSAndroid Build Coastguard Worker __ Remw(out, dividend, tmp);
1528*795d594fSAndroid Build Coastguard Worker } else {
1529*795d594fSAndroid Build Coastguard Worker __ Rem(out, dividend, tmp);
1530*795d594fSAndroid Build Coastguard Worker }
1531*795d594fSAndroid Build Coastguard Worker }
1532*795d594fSAndroid Build Coastguard Worker }
1533*795d594fSAndroid Build Coastguard Worker
GenerateDivRemIntegral(HBinaryOperation * instruction)1534*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenerateDivRemIntegral(HBinaryOperation* instruction) {
1535*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsDiv() || instruction->IsRem());
1536*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetResultType();
1537*795d594fSAndroid Build Coastguard Worker DCHECK(type == DataType::Type::kInt32 || type == DataType::Type::kInt64) << type;
1538*795d594fSAndroid Build Coastguard Worker
1539*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
1540*795d594fSAndroid Build Coastguard Worker XRegister out = locations->Out().AsRegister<XRegister>();
1541*795d594fSAndroid Build Coastguard Worker Location second = locations->InAt(1);
1542*795d594fSAndroid Build Coastguard Worker
1543*795d594fSAndroid Build Coastguard Worker if (second.IsConstant()) {
1544*795d594fSAndroid Build Coastguard Worker int64_t imm = Int64FromConstant(second.GetConstant());
1545*795d594fSAndroid Build Coastguard Worker if (imm == 0) {
1546*795d594fSAndroid Build Coastguard Worker // Do not generate anything. DivZeroCheck would prevent any code to be executed.
1547*795d594fSAndroid Build Coastguard Worker } else if (imm == 1 || imm == -1) {
1548*795d594fSAndroid Build Coastguard Worker DivRemOneOrMinusOne(instruction);
1549*795d594fSAndroid Build Coastguard Worker } else if (IsPowerOfTwo(AbsOrMin(imm))) {
1550*795d594fSAndroid Build Coastguard Worker DivRemByPowerOfTwo(instruction);
1551*795d594fSAndroid Build Coastguard Worker } else {
1552*795d594fSAndroid Build Coastguard Worker DCHECK(imm <= -2 || imm >= 2);
1553*795d594fSAndroid Build Coastguard Worker GenerateDivRemWithAnyConstant(instruction);
1554*795d594fSAndroid Build Coastguard Worker }
1555*795d594fSAndroid Build Coastguard Worker } else {
1556*795d594fSAndroid Build Coastguard Worker XRegister dividend = locations->InAt(0).AsRegister<XRegister>();
1557*795d594fSAndroid Build Coastguard Worker XRegister divisor = second.AsRegister<XRegister>();
1558*795d594fSAndroid Build Coastguard Worker if (instruction->IsDiv()) {
1559*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kInt32) {
1560*795d594fSAndroid Build Coastguard Worker __ Divw(out, dividend, divisor);
1561*795d594fSAndroid Build Coastguard Worker } else {
1562*795d594fSAndroid Build Coastguard Worker __ Div(out, dividend, divisor);
1563*795d594fSAndroid Build Coastguard Worker }
1564*795d594fSAndroid Build Coastguard Worker } else {
1565*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kInt32) {
1566*795d594fSAndroid Build Coastguard Worker __ Remw(out, dividend, divisor);
1567*795d594fSAndroid Build Coastguard Worker } else {
1568*795d594fSAndroid Build Coastguard Worker __ Rem(out, dividend, divisor);
1569*795d594fSAndroid Build Coastguard Worker }
1570*795d594fSAndroid Build Coastguard Worker }
1571*795d594fSAndroid Build Coastguard Worker }
1572*795d594fSAndroid Build Coastguard Worker }
1573*795d594fSAndroid Build Coastguard Worker
GenerateIntLongCondition(IfCondition cond,LocationSummary * locations)1574*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenerateIntLongCondition(IfCondition cond,
1575*795d594fSAndroid Build Coastguard Worker LocationSummary* locations) {
1576*795d594fSAndroid Build Coastguard Worker XRegister rd = locations->Out().AsRegister<XRegister>();
1577*795d594fSAndroid Build Coastguard Worker GenerateIntLongCondition(cond, locations, rd, /*to_all_bits=*/ false);
1578*795d594fSAndroid Build Coastguard Worker }
1579*795d594fSAndroid Build Coastguard Worker
GenerateIntLongCondition(IfCondition cond,LocationSummary * locations,XRegister rd,bool to_all_bits)1580*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenerateIntLongCondition(IfCondition cond,
1581*795d594fSAndroid Build Coastguard Worker LocationSummary* locations,
1582*795d594fSAndroid Build Coastguard Worker XRegister rd,
1583*795d594fSAndroid Build Coastguard Worker bool to_all_bits) {
1584*795d594fSAndroid Build Coastguard Worker XRegister rs1 = locations->InAt(0).AsRegister<XRegister>();
1585*795d594fSAndroid Build Coastguard Worker Location rs2_location = locations->InAt(1);
1586*795d594fSAndroid Build Coastguard Worker bool use_imm = rs2_location.IsConstant();
1587*795d594fSAndroid Build Coastguard Worker int64_t imm = use_imm ? CodeGenerator::GetInt64ValueOf(rs2_location.GetConstant()) : 0;
1588*795d594fSAndroid Build Coastguard Worker XRegister rs2 = use_imm ? kNoXRegister : rs2_location.AsRegister<XRegister>();
1589*795d594fSAndroid Build Coastguard Worker bool reverse_condition = false;
1590*795d594fSAndroid Build Coastguard Worker switch (cond) {
1591*795d594fSAndroid Build Coastguard Worker case kCondEQ:
1592*795d594fSAndroid Build Coastguard Worker case kCondNE:
1593*795d594fSAndroid Build Coastguard Worker if (!use_imm) {
1594*795d594fSAndroid Build Coastguard Worker __ Sub(rd, rs1, rs2); // SUB is OK here even for 32-bit comparison.
1595*795d594fSAndroid Build Coastguard Worker } else if (imm != 0) {
1596*795d594fSAndroid Build Coastguard Worker DCHECK(IsInt<12>(-imm));
1597*795d594fSAndroid Build Coastguard Worker __ Addi(rd, rs1, -imm); // ADDI is OK here even for 32-bit comparison.
1598*795d594fSAndroid Build Coastguard Worker } // else test `rs1` directly without subtraction for `use_imm && imm == 0`.
1599*795d594fSAndroid Build Coastguard Worker if (cond == kCondEQ) {
1600*795d594fSAndroid Build Coastguard Worker __ Seqz(rd, (use_imm && imm == 0) ? rs1 : rd);
1601*795d594fSAndroid Build Coastguard Worker } else {
1602*795d594fSAndroid Build Coastguard Worker __ Snez(rd, (use_imm && imm == 0) ? rs1 : rd);
1603*795d594fSAndroid Build Coastguard Worker }
1604*795d594fSAndroid Build Coastguard Worker break;
1605*795d594fSAndroid Build Coastguard Worker
1606*795d594fSAndroid Build Coastguard Worker case kCondLT:
1607*795d594fSAndroid Build Coastguard Worker case kCondGE:
1608*795d594fSAndroid Build Coastguard Worker if (use_imm) {
1609*795d594fSAndroid Build Coastguard Worker DCHECK(IsInt<12>(imm));
1610*795d594fSAndroid Build Coastguard Worker __ Slti(rd, rs1, imm);
1611*795d594fSAndroid Build Coastguard Worker } else {
1612*795d594fSAndroid Build Coastguard Worker __ Slt(rd, rs1, rs2);
1613*795d594fSAndroid Build Coastguard Worker }
1614*795d594fSAndroid Build Coastguard Worker // Calculate `rs1 >= rhs` as `!(rs1 < rhs)` since there's only the SLT but no SGE.
1615*795d594fSAndroid Build Coastguard Worker reverse_condition = (cond == kCondGE);
1616*795d594fSAndroid Build Coastguard Worker break;
1617*795d594fSAndroid Build Coastguard Worker
1618*795d594fSAndroid Build Coastguard Worker case kCondLE:
1619*795d594fSAndroid Build Coastguard Worker case kCondGT:
1620*795d594fSAndroid Build Coastguard Worker if (use_imm) {
1621*795d594fSAndroid Build Coastguard Worker // Calculate `rs1 <= imm` as `rs1 < imm + 1`.
1622*795d594fSAndroid Build Coastguard Worker DCHECK(IsInt<12>(imm + 1)); // The value that overflows would fail this check.
1623*795d594fSAndroid Build Coastguard Worker __ Slti(rd, rs1, imm + 1);
1624*795d594fSAndroid Build Coastguard Worker } else {
1625*795d594fSAndroid Build Coastguard Worker __ Slt(rd, rs2, rs1);
1626*795d594fSAndroid Build Coastguard Worker }
1627*795d594fSAndroid Build Coastguard Worker // Calculate `rs1 > imm` as `!(rs1 < imm + 1)` and calculate
1628*795d594fSAndroid Build Coastguard Worker // `rs1 <= rs2` as `!(rs2 < rs1)` since there's only the SLT but no SGE.
1629*795d594fSAndroid Build Coastguard Worker reverse_condition = ((cond == kCondGT) == use_imm);
1630*795d594fSAndroid Build Coastguard Worker break;
1631*795d594fSAndroid Build Coastguard Worker
1632*795d594fSAndroid Build Coastguard Worker case kCondB:
1633*795d594fSAndroid Build Coastguard Worker case kCondAE:
1634*795d594fSAndroid Build Coastguard Worker if (use_imm) {
1635*795d594fSAndroid Build Coastguard Worker // Sltiu sign-extends its 12-bit immediate operand before the comparison
1636*795d594fSAndroid Build Coastguard Worker // and thus lets us compare directly with unsigned values in the ranges
1637*795d594fSAndroid Build Coastguard Worker // [0, 0x7ff] and [0x[ffffffff]fffff800, 0x[ffffffff]ffffffff].
1638*795d594fSAndroid Build Coastguard Worker DCHECK(IsInt<12>(imm));
1639*795d594fSAndroid Build Coastguard Worker __ Sltiu(rd, rs1, imm);
1640*795d594fSAndroid Build Coastguard Worker } else {
1641*795d594fSAndroid Build Coastguard Worker __ Sltu(rd, rs1, rs2);
1642*795d594fSAndroid Build Coastguard Worker }
1643*795d594fSAndroid Build Coastguard Worker // Calculate `rs1 AE rhs` as `!(rs1 B rhs)` since there's only the SLTU but no SGEU.
1644*795d594fSAndroid Build Coastguard Worker reverse_condition = (cond == kCondAE);
1645*795d594fSAndroid Build Coastguard Worker break;
1646*795d594fSAndroid Build Coastguard Worker
1647*795d594fSAndroid Build Coastguard Worker case kCondBE:
1648*795d594fSAndroid Build Coastguard Worker case kCondA:
1649*795d594fSAndroid Build Coastguard Worker if (use_imm) {
1650*795d594fSAndroid Build Coastguard Worker // Calculate `rs1 BE imm` as `rs1 B imm + 1`.
1651*795d594fSAndroid Build Coastguard Worker // Sltiu sign-extends its 12-bit immediate operand before the comparison
1652*795d594fSAndroid Build Coastguard Worker // and thus lets us compare directly with unsigned values in the ranges
1653*795d594fSAndroid Build Coastguard Worker // [0, 0x7ff] and [0x[ffffffff]fffff800, 0x[ffffffff]ffffffff].
1654*795d594fSAndroid Build Coastguard Worker DCHECK(IsInt<12>(imm + 1)); // The value that overflows would fail this check.
1655*795d594fSAndroid Build Coastguard Worker __ Sltiu(rd, rs1, imm + 1);
1656*795d594fSAndroid Build Coastguard Worker } else {
1657*795d594fSAndroid Build Coastguard Worker __ Sltu(rd, rs2, rs1);
1658*795d594fSAndroid Build Coastguard Worker }
1659*795d594fSAndroid Build Coastguard Worker // Calculate `rs1 A imm` as `!(rs1 B imm + 1)` and calculate
1660*795d594fSAndroid Build Coastguard Worker // `rs1 BE rs2` as `!(rs2 B rs1)` since there's only the SLTU but no SGEU.
1661*795d594fSAndroid Build Coastguard Worker reverse_condition = ((cond == kCondA) == use_imm);
1662*795d594fSAndroid Build Coastguard Worker break;
1663*795d594fSAndroid Build Coastguard Worker }
1664*795d594fSAndroid Build Coastguard Worker if (to_all_bits) {
1665*795d594fSAndroid Build Coastguard Worker // Store the result to all bits; in other words, "true" is represented by -1.
1666*795d594fSAndroid Build Coastguard Worker if (reverse_condition) {
1667*795d594fSAndroid Build Coastguard Worker __ Addi(rd, rd, -1); // 0 -> -1, 1 -> 0
1668*795d594fSAndroid Build Coastguard Worker } else {
1669*795d594fSAndroid Build Coastguard Worker __ Neg(rd, rd); // 0 -> 0, 1 -> -1
1670*795d594fSAndroid Build Coastguard Worker }
1671*795d594fSAndroid Build Coastguard Worker } else {
1672*795d594fSAndroid Build Coastguard Worker if (reverse_condition) {
1673*795d594fSAndroid Build Coastguard Worker __ Xori(rd, rd, 1);
1674*795d594fSAndroid Build Coastguard Worker }
1675*795d594fSAndroid Build Coastguard Worker }
1676*795d594fSAndroid Build Coastguard Worker }
1677*795d594fSAndroid Build Coastguard Worker
GenerateIntLongCompareAndBranch(IfCondition cond,LocationSummary * locations,Riscv64Label * label)1678*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenerateIntLongCompareAndBranch(IfCondition cond,
1679*795d594fSAndroid Build Coastguard Worker LocationSummary* locations,
1680*795d594fSAndroid Build Coastguard Worker Riscv64Label* label) {
1681*795d594fSAndroid Build Coastguard Worker XRegister left = locations->InAt(0).AsRegister<XRegister>();
1682*795d594fSAndroid Build Coastguard Worker Location right_location = locations->InAt(1);
1683*795d594fSAndroid Build Coastguard Worker if (right_location.IsConstant()) {
1684*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(CodeGenerator::GetInt64ValueOf(right_location.GetConstant()), 0);
1685*795d594fSAndroid Build Coastguard Worker switch (cond) {
1686*795d594fSAndroid Build Coastguard Worker case kCondEQ:
1687*795d594fSAndroid Build Coastguard Worker case kCondBE: // <= 0 if zero
1688*795d594fSAndroid Build Coastguard Worker __ Beqz(left, label);
1689*795d594fSAndroid Build Coastguard Worker break;
1690*795d594fSAndroid Build Coastguard Worker case kCondNE:
1691*795d594fSAndroid Build Coastguard Worker case kCondA: // > 0 if non-zero
1692*795d594fSAndroid Build Coastguard Worker __ Bnez(left, label);
1693*795d594fSAndroid Build Coastguard Worker break;
1694*795d594fSAndroid Build Coastguard Worker case kCondLT:
1695*795d594fSAndroid Build Coastguard Worker __ Bltz(left, label);
1696*795d594fSAndroid Build Coastguard Worker break;
1697*795d594fSAndroid Build Coastguard Worker case kCondGE:
1698*795d594fSAndroid Build Coastguard Worker __ Bgez(left, label);
1699*795d594fSAndroid Build Coastguard Worker break;
1700*795d594fSAndroid Build Coastguard Worker case kCondLE:
1701*795d594fSAndroid Build Coastguard Worker __ Blez(left, label);
1702*795d594fSAndroid Build Coastguard Worker break;
1703*795d594fSAndroid Build Coastguard Worker case kCondGT:
1704*795d594fSAndroid Build Coastguard Worker __ Bgtz(left, label);
1705*795d594fSAndroid Build Coastguard Worker break;
1706*795d594fSAndroid Build Coastguard Worker case kCondB: // always false
1707*795d594fSAndroid Build Coastguard Worker break;
1708*795d594fSAndroid Build Coastguard Worker case kCondAE: // always true
1709*795d594fSAndroid Build Coastguard Worker __ J(label);
1710*795d594fSAndroid Build Coastguard Worker break;
1711*795d594fSAndroid Build Coastguard Worker }
1712*795d594fSAndroid Build Coastguard Worker } else {
1713*795d594fSAndroid Build Coastguard Worker XRegister right_reg = right_location.AsRegister<XRegister>();
1714*795d594fSAndroid Build Coastguard Worker switch (cond) {
1715*795d594fSAndroid Build Coastguard Worker case kCondEQ:
1716*795d594fSAndroid Build Coastguard Worker __ Beq(left, right_reg, label);
1717*795d594fSAndroid Build Coastguard Worker break;
1718*795d594fSAndroid Build Coastguard Worker case kCondNE:
1719*795d594fSAndroid Build Coastguard Worker __ Bne(left, right_reg, label);
1720*795d594fSAndroid Build Coastguard Worker break;
1721*795d594fSAndroid Build Coastguard Worker case kCondLT:
1722*795d594fSAndroid Build Coastguard Worker __ Blt(left, right_reg, label);
1723*795d594fSAndroid Build Coastguard Worker break;
1724*795d594fSAndroid Build Coastguard Worker case kCondGE:
1725*795d594fSAndroid Build Coastguard Worker __ Bge(left, right_reg, label);
1726*795d594fSAndroid Build Coastguard Worker break;
1727*795d594fSAndroid Build Coastguard Worker case kCondLE:
1728*795d594fSAndroid Build Coastguard Worker __ Ble(left, right_reg, label);
1729*795d594fSAndroid Build Coastguard Worker break;
1730*795d594fSAndroid Build Coastguard Worker case kCondGT:
1731*795d594fSAndroid Build Coastguard Worker __ Bgt(left, right_reg, label);
1732*795d594fSAndroid Build Coastguard Worker break;
1733*795d594fSAndroid Build Coastguard Worker case kCondB:
1734*795d594fSAndroid Build Coastguard Worker __ Bltu(left, right_reg, label);
1735*795d594fSAndroid Build Coastguard Worker break;
1736*795d594fSAndroid Build Coastguard Worker case kCondAE:
1737*795d594fSAndroid Build Coastguard Worker __ Bgeu(left, right_reg, label);
1738*795d594fSAndroid Build Coastguard Worker break;
1739*795d594fSAndroid Build Coastguard Worker case kCondBE:
1740*795d594fSAndroid Build Coastguard Worker __ Bleu(left, right_reg, label);
1741*795d594fSAndroid Build Coastguard Worker break;
1742*795d594fSAndroid Build Coastguard Worker case kCondA:
1743*795d594fSAndroid Build Coastguard Worker __ Bgtu(left, right_reg, label);
1744*795d594fSAndroid Build Coastguard Worker break;
1745*795d594fSAndroid Build Coastguard Worker }
1746*795d594fSAndroid Build Coastguard Worker }
1747*795d594fSAndroid Build Coastguard Worker }
1748*795d594fSAndroid Build Coastguard Worker
GenerateFpCondition(IfCondition cond,bool gt_bias,DataType::Type type,LocationSummary * locations,Riscv64Label * label)1749*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenerateFpCondition(IfCondition cond,
1750*795d594fSAndroid Build Coastguard Worker bool gt_bias,
1751*795d594fSAndroid Build Coastguard Worker DataType::Type type,
1752*795d594fSAndroid Build Coastguard Worker LocationSummary* locations,
1753*795d594fSAndroid Build Coastguard Worker Riscv64Label* label) {
1754*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(label != nullptr, locations->Out().IsInvalid());
1755*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
1756*795d594fSAndroid Build Coastguard Worker XRegister rd =
1757*795d594fSAndroid Build Coastguard Worker (label != nullptr) ? srs.AllocateXRegister() : locations->Out().AsRegister<XRegister>();
1758*795d594fSAndroid Build Coastguard Worker GenerateFpCondition(cond, gt_bias, type, locations, label, rd, /*to_all_bits=*/ false);
1759*795d594fSAndroid Build Coastguard Worker }
1760*795d594fSAndroid Build Coastguard Worker
GenerateFpCondition(IfCondition cond,bool gt_bias,DataType::Type type,LocationSummary * locations,Riscv64Label * label,XRegister rd,bool to_all_bits)1761*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenerateFpCondition(IfCondition cond,
1762*795d594fSAndroid Build Coastguard Worker bool gt_bias,
1763*795d594fSAndroid Build Coastguard Worker DataType::Type type,
1764*795d594fSAndroid Build Coastguard Worker LocationSummary* locations,
1765*795d594fSAndroid Build Coastguard Worker Riscv64Label* label,
1766*795d594fSAndroid Build Coastguard Worker XRegister rd,
1767*795d594fSAndroid Build Coastguard Worker bool to_all_bits) {
1768*795d594fSAndroid Build Coastguard Worker // RISCV-V FP compare instructions yield the following values:
1769*795d594fSAndroid Build Coastguard Worker // l<r l=r l>r Unordered
1770*795d594fSAndroid Build Coastguard Worker // FEQ l,r 0 1 0 0
1771*795d594fSAndroid Build Coastguard Worker // FLT l,r 1 0 0 0
1772*795d594fSAndroid Build Coastguard Worker // FLT r,l 0 0 1 0
1773*795d594fSAndroid Build Coastguard Worker // FLE l,r 1 1 0 0
1774*795d594fSAndroid Build Coastguard Worker // FLE r,l 0 1 1 0
1775*795d594fSAndroid Build Coastguard Worker //
1776*795d594fSAndroid Build Coastguard Worker // We can calculate the `Compare` results using the following formulas:
1777*795d594fSAndroid Build Coastguard Worker // l<r l=r l>r Unordered
1778*795d594fSAndroid Build Coastguard Worker // Compare/gt_bias -1 0 1 1 = ((FLE l,r) ^ 1) - (FLT l,r)
1779*795d594fSAndroid Build Coastguard Worker // Compare/lt_bias -1 0 1 -1 = ((FLE r,l) - 1) + (FLT r,l)
1780*795d594fSAndroid Build Coastguard Worker // These are emitted in `VisitCompare()`.
1781*795d594fSAndroid Build Coastguard Worker //
1782*795d594fSAndroid Build Coastguard Worker // This function emits a fused `Condition(Compare(., .), 0)`. If we compare the
1783*795d594fSAndroid Build Coastguard Worker // `Compare` results above with 0, we get the following values and formulas:
1784*795d594fSAndroid Build Coastguard Worker // l<r l=r l>r Unordered
1785*795d594fSAndroid Build Coastguard Worker // CondEQ/- 0 1 0 0 = (FEQ l, r)
1786*795d594fSAndroid Build Coastguard Worker // CondNE/- 1 0 1 1 = (FEQ l, r) ^ 1
1787*795d594fSAndroid Build Coastguard Worker // CondLT/gt_bias 1 0 0 0 = (FLT l,r)
1788*795d594fSAndroid Build Coastguard Worker // CondLT/lt_bias 1 0 0 1 = (FLE r,l) ^ 1
1789*795d594fSAndroid Build Coastguard Worker // CondLE/gt_bias 1 1 0 0 = (FLE l,r)
1790*795d594fSAndroid Build Coastguard Worker // CondLE/lt_bias 1 1 0 1 = (FLT r,l) ^ 1
1791*795d594fSAndroid Build Coastguard Worker // CondGT/gt_bias 0 0 1 1 = (FLE l,r) ^ 1
1792*795d594fSAndroid Build Coastguard Worker // CondGT/lt_bias 0 0 1 0 = (FLT r,l)
1793*795d594fSAndroid Build Coastguard Worker // CondGE/gt_bias 0 1 1 1 = (FLT l,r) ^ 1
1794*795d594fSAndroid Build Coastguard Worker // CondGE/lt_bias 0 1 1 0 = (FLE r,l)
1795*795d594fSAndroid Build Coastguard Worker // (CondEQ/CondNE comparison with zero yields the same result with gt_bias and lt_bias.)
1796*795d594fSAndroid Build Coastguard Worker //
1797*795d594fSAndroid Build Coastguard Worker // If the condition is not materialized, the `^ 1` is not emitted,
1798*795d594fSAndroid Build Coastguard Worker // instead the condition is reversed by emitting BEQZ instead of BNEZ.
1799*795d594fSAndroid Build Coastguard Worker
1800*795d594fSAndroid Build Coastguard Worker FRegister rs1 = locations->InAt(0).AsFpuRegister<FRegister>();
1801*795d594fSAndroid Build Coastguard Worker FRegister rs2 = locations->InAt(1).AsFpuRegister<FRegister>();
1802*795d594fSAndroid Build Coastguard Worker
1803*795d594fSAndroid Build Coastguard Worker bool reverse_condition = false;
1804*795d594fSAndroid Build Coastguard Worker switch (cond) {
1805*795d594fSAndroid Build Coastguard Worker case kCondEQ:
1806*795d594fSAndroid Build Coastguard Worker FEq(rd, rs1, rs2, type);
1807*795d594fSAndroid Build Coastguard Worker break;
1808*795d594fSAndroid Build Coastguard Worker case kCondNE:
1809*795d594fSAndroid Build Coastguard Worker FEq(rd, rs1, rs2, type);
1810*795d594fSAndroid Build Coastguard Worker reverse_condition = true;
1811*795d594fSAndroid Build Coastguard Worker break;
1812*795d594fSAndroid Build Coastguard Worker case kCondLT:
1813*795d594fSAndroid Build Coastguard Worker if (gt_bias) {
1814*795d594fSAndroid Build Coastguard Worker FLt(rd, rs1, rs2, type);
1815*795d594fSAndroid Build Coastguard Worker } else {
1816*795d594fSAndroid Build Coastguard Worker FLe(rd, rs2, rs1, type);
1817*795d594fSAndroid Build Coastguard Worker reverse_condition = true;
1818*795d594fSAndroid Build Coastguard Worker }
1819*795d594fSAndroid Build Coastguard Worker break;
1820*795d594fSAndroid Build Coastguard Worker case kCondLE:
1821*795d594fSAndroid Build Coastguard Worker if (gt_bias) {
1822*795d594fSAndroid Build Coastguard Worker FLe(rd, rs1, rs2, type);
1823*795d594fSAndroid Build Coastguard Worker } else {
1824*795d594fSAndroid Build Coastguard Worker FLt(rd, rs2, rs1, type);
1825*795d594fSAndroid Build Coastguard Worker reverse_condition = true;
1826*795d594fSAndroid Build Coastguard Worker }
1827*795d594fSAndroid Build Coastguard Worker break;
1828*795d594fSAndroid Build Coastguard Worker case kCondGT:
1829*795d594fSAndroid Build Coastguard Worker if (gt_bias) {
1830*795d594fSAndroid Build Coastguard Worker FLe(rd, rs1, rs2, type);
1831*795d594fSAndroid Build Coastguard Worker reverse_condition = true;
1832*795d594fSAndroid Build Coastguard Worker } else {
1833*795d594fSAndroid Build Coastguard Worker FLt(rd, rs2, rs1, type);
1834*795d594fSAndroid Build Coastguard Worker }
1835*795d594fSAndroid Build Coastguard Worker break;
1836*795d594fSAndroid Build Coastguard Worker case kCondGE:
1837*795d594fSAndroid Build Coastguard Worker if (gt_bias) {
1838*795d594fSAndroid Build Coastguard Worker FLt(rd, rs1, rs2, type);
1839*795d594fSAndroid Build Coastguard Worker reverse_condition = true;
1840*795d594fSAndroid Build Coastguard Worker } else {
1841*795d594fSAndroid Build Coastguard Worker FLe(rd, rs2, rs1, type);
1842*795d594fSAndroid Build Coastguard Worker }
1843*795d594fSAndroid Build Coastguard Worker break;
1844*795d594fSAndroid Build Coastguard Worker default:
1845*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected floating-point condition " << cond;
1846*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
1847*795d594fSAndroid Build Coastguard Worker }
1848*795d594fSAndroid Build Coastguard Worker
1849*795d594fSAndroid Build Coastguard Worker if (label != nullptr) {
1850*795d594fSAndroid Build Coastguard Worker if (reverse_condition) {
1851*795d594fSAndroid Build Coastguard Worker __ Beqz(rd, label);
1852*795d594fSAndroid Build Coastguard Worker } else {
1853*795d594fSAndroid Build Coastguard Worker __ Bnez(rd, label);
1854*795d594fSAndroid Build Coastguard Worker }
1855*795d594fSAndroid Build Coastguard Worker } else if (to_all_bits) {
1856*795d594fSAndroid Build Coastguard Worker // Store the result to all bits; in other words, "true" is represented by -1.
1857*795d594fSAndroid Build Coastguard Worker if (reverse_condition) {
1858*795d594fSAndroid Build Coastguard Worker __ Addi(rd, rd, -1); // 0 -> -1, 1 -> 0
1859*795d594fSAndroid Build Coastguard Worker } else {
1860*795d594fSAndroid Build Coastguard Worker __ Neg(rd, rd); // 0 -> 0, 1 -> -1
1861*795d594fSAndroid Build Coastguard Worker }
1862*795d594fSAndroid Build Coastguard Worker } else {
1863*795d594fSAndroid Build Coastguard Worker if (reverse_condition) {
1864*795d594fSAndroid Build Coastguard Worker __ Xori(rd, rd, 1);
1865*795d594fSAndroid Build Coastguard Worker }
1866*795d594fSAndroid Build Coastguard Worker }
1867*795d594fSAndroid Build Coastguard Worker }
1868*795d594fSAndroid Build Coastguard Worker
GenerateFieldLoadWithBakerReadBarrier(HInstruction * instruction,Location ref,XRegister obj,uint32_t offset,Location temp,bool needs_null_check)1869*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction,
1870*795d594fSAndroid Build Coastguard Worker Location ref,
1871*795d594fSAndroid Build Coastguard Worker XRegister obj,
1872*795d594fSAndroid Build Coastguard Worker uint32_t offset,
1873*795d594fSAndroid Build Coastguard Worker Location temp,
1874*795d594fSAndroid Build Coastguard Worker bool needs_null_check) {
1875*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadWithBakerReadBarrier(
1876*795d594fSAndroid Build Coastguard Worker instruction, ref, obj, offset, /*index=*/ Location::NoLocation(), temp, needs_null_check);
1877*795d594fSAndroid Build Coastguard Worker }
1878*795d594fSAndroid Build Coastguard Worker
GenerateArrayLoadWithBakerReadBarrier(HInstruction * instruction,Location ref,XRegister obj,uint32_t data_offset,Location index,Location temp,bool needs_null_check)1879*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::GenerateArrayLoadWithBakerReadBarrier(HInstruction* instruction,
1880*795d594fSAndroid Build Coastguard Worker Location ref,
1881*795d594fSAndroid Build Coastguard Worker XRegister obj,
1882*795d594fSAndroid Build Coastguard Worker uint32_t data_offset,
1883*795d594fSAndroid Build Coastguard Worker Location index,
1884*795d594fSAndroid Build Coastguard Worker Location temp,
1885*795d594fSAndroid Build Coastguard Worker bool needs_null_check) {
1886*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadWithBakerReadBarrier(
1887*795d594fSAndroid Build Coastguard Worker instruction, ref, obj, data_offset, index, temp, needs_null_check);
1888*795d594fSAndroid Build Coastguard Worker }
1889*795d594fSAndroid Build Coastguard Worker
GenerateReferenceLoadWithBakerReadBarrier(HInstruction * instruction,Location ref,XRegister obj,uint32_t offset,Location index,Location temp,bool needs_null_check)1890*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::GenerateReferenceLoadWithBakerReadBarrier(HInstruction* instruction,
1891*795d594fSAndroid Build Coastguard Worker Location ref,
1892*795d594fSAndroid Build Coastguard Worker XRegister obj,
1893*795d594fSAndroid Build Coastguard Worker uint32_t offset,
1894*795d594fSAndroid Build Coastguard Worker Location index,
1895*795d594fSAndroid Build Coastguard Worker Location temp,
1896*795d594fSAndroid Build Coastguard Worker bool needs_null_check) {
1897*795d594fSAndroid Build Coastguard Worker // For now, use the same approach as for GC roots plus unpoison the reference if needed.
1898*795d594fSAndroid Build Coastguard Worker // TODO(riscv64): Implement checking if the holder is black.
1899*795d594fSAndroid Build Coastguard Worker UNUSED(temp);
1900*795d594fSAndroid Build Coastguard Worker
1901*795d594fSAndroid Build Coastguard Worker DCHECK(EmitBakerReadBarrier());
1902*795d594fSAndroid Build Coastguard Worker XRegister reg = ref.AsRegister<XRegister>();
1903*795d594fSAndroid Build Coastguard Worker if (index.IsValid()) {
1904*795d594fSAndroid Build Coastguard Worker DCHECK(!needs_null_check);
1905*795d594fSAndroid Build Coastguard Worker DCHECK(index.IsRegister());
1906*795d594fSAndroid Build Coastguard Worker DataType::Type type = DataType::Type::kReference;
1907*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(type, instruction->GetType());
1908*795d594fSAndroid Build Coastguard Worker if (instruction->IsArrayGet()) {
1909*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Object> */ ref = *(obj + index * element_size + offset)
1910*795d594fSAndroid Build Coastguard Worker instruction_visitor_.ShNAdd(reg, index.AsRegister<XRegister>(), obj, type);
1911*795d594fSAndroid Build Coastguard Worker } else {
1912*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Object> */ ref = *(obj + index + offset)
1913*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsInvoke());
1914*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->GetLocations()->Intrinsified());
1915*795d594fSAndroid Build Coastguard Worker __ Add(reg, index.AsRegister<XRegister>(), obj);
1916*795d594fSAndroid Build Coastguard Worker }
1917*795d594fSAndroid Build Coastguard Worker __ Loadwu(reg, reg, offset);
1918*795d594fSAndroid Build Coastguard Worker } else {
1919*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Object> */ ref = *(obj + offset)
1920*795d594fSAndroid Build Coastguard Worker __ Loadwu(reg, obj, offset);
1921*795d594fSAndroid Build Coastguard Worker if (needs_null_check) {
1922*795d594fSAndroid Build Coastguard Worker MaybeRecordImplicitNullCheck(instruction);
1923*795d594fSAndroid Build Coastguard Worker }
1924*795d594fSAndroid Build Coastguard Worker }
1925*795d594fSAndroid Build Coastguard Worker MaybeUnpoisonHeapReference(reg);
1926*795d594fSAndroid Build Coastguard Worker
1927*795d594fSAndroid Build Coastguard Worker // Slow path marking the reference.
1928*795d594fSAndroid Build Coastguard Worker XRegister tmp = RA; // Use RA as temp. It is clobbered in the slow path anyway.
1929*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path = new (GetScopedAllocator()) ReadBarrierMarkSlowPathRISCV64(
1930*795d594fSAndroid Build Coastguard Worker instruction, ref, Location::RegisterLocation(tmp));
1931*795d594fSAndroid Build Coastguard Worker AddSlowPath(slow_path);
1932*795d594fSAndroid Build Coastguard Worker
1933*795d594fSAndroid Build Coastguard Worker const int32_t entry_point_offset = ReadBarrierMarkEntrypointOffset(ref);
1934*795d594fSAndroid Build Coastguard Worker // Loading the entrypoint does not require a load acquire since it is only changed when
1935*795d594fSAndroid Build Coastguard Worker // threads are suspended or running a checkpoint.
1936*795d594fSAndroid Build Coastguard Worker __ Loadd(tmp, TR, entry_point_offset);
1937*795d594fSAndroid Build Coastguard Worker __ Bnez(tmp, slow_path->GetEntryLabel());
1938*795d594fSAndroid Build Coastguard Worker __ Bind(slow_path->GetExitLabel());
1939*795d594fSAndroid Build Coastguard Worker }
1940*795d594fSAndroid Build Coastguard Worker
AddReadBarrierSlowPath(HInstruction * instruction,Location out,Location ref,Location obj,uint32_t offset,Location index)1941*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* CodeGeneratorRISCV64::AddReadBarrierSlowPath(HInstruction* instruction,
1942*795d594fSAndroid Build Coastguard Worker Location out,
1943*795d594fSAndroid Build Coastguard Worker Location ref,
1944*795d594fSAndroid Build Coastguard Worker Location obj,
1945*795d594fSAndroid Build Coastguard Worker uint32_t offset,
1946*795d594fSAndroid Build Coastguard Worker Location index) {
1947*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
1948*795d594fSAndroid Build Coastguard Worker UNUSED(out);
1949*795d594fSAndroid Build Coastguard Worker UNUSED(ref);
1950*795d594fSAndroid Build Coastguard Worker UNUSED(obj);
1951*795d594fSAndroid Build Coastguard Worker UNUSED(offset);
1952*795d594fSAndroid Build Coastguard Worker UNUSED(index);
1953*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
1954*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
1955*795d594fSAndroid Build Coastguard Worker }
1956*795d594fSAndroid Build Coastguard Worker
GenerateReadBarrierSlow(HInstruction * instruction,Location out,Location ref,Location obj,uint32_t offset,Location index)1957*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::GenerateReadBarrierSlow(HInstruction* instruction,
1958*795d594fSAndroid Build Coastguard Worker Location out,
1959*795d594fSAndroid Build Coastguard Worker Location ref,
1960*795d594fSAndroid Build Coastguard Worker Location obj,
1961*795d594fSAndroid Build Coastguard Worker uint32_t offset,
1962*795d594fSAndroid Build Coastguard Worker Location index) {
1963*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
1964*795d594fSAndroid Build Coastguard Worker UNUSED(out);
1965*795d594fSAndroid Build Coastguard Worker UNUSED(ref);
1966*795d594fSAndroid Build Coastguard Worker UNUSED(obj);
1967*795d594fSAndroid Build Coastguard Worker UNUSED(offset);
1968*795d594fSAndroid Build Coastguard Worker UNUSED(index);
1969*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
1970*795d594fSAndroid Build Coastguard Worker }
1971*795d594fSAndroid Build Coastguard Worker
MaybeGenerateReadBarrierSlow(HInstruction * instruction,Location out,Location ref,Location obj,uint32_t offset,Location index)1972*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::MaybeGenerateReadBarrierSlow(HInstruction* instruction,
1973*795d594fSAndroid Build Coastguard Worker Location out,
1974*795d594fSAndroid Build Coastguard Worker Location ref,
1975*795d594fSAndroid Build Coastguard Worker Location obj,
1976*795d594fSAndroid Build Coastguard Worker uint32_t offset,
1977*795d594fSAndroid Build Coastguard Worker Location index) {
1978*795d594fSAndroid Build Coastguard Worker if (EmitReadBarrier()) {
1979*795d594fSAndroid Build Coastguard Worker // Baker's read barriers shall be handled by the fast path
1980*795d594fSAndroid Build Coastguard Worker // (CodeGeneratorRISCV64::GenerateReferenceLoadWithBakerReadBarrier).
1981*795d594fSAndroid Build Coastguard Worker DCHECK(!kUseBakerReadBarrier);
1982*795d594fSAndroid Build Coastguard Worker // If heap poisoning is enabled, unpoisoning will be taken care of
1983*795d594fSAndroid Build Coastguard Worker // by the runtime within the slow path.
1984*795d594fSAndroid Build Coastguard Worker GenerateReadBarrierSlow(instruction, out, ref, obj, offset, index);
1985*795d594fSAndroid Build Coastguard Worker } else if (kPoisonHeapReferences) {
1986*795d594fSAndroid Build Coastguard Worker UnpoisonHeapReference(out.AsRegister<XRegister>());
1987*795d594fSAndroid Build Coastguard Worker }
1988*795d594fSAndroid Build Coastguard Worker }
1989*795d594fSAndroid Build Coastguard Worker
GenerateReadBarrierForRootSlow(HInstruction * instruction,Location out,Location root)1990*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::GenerateReadBarrierForRootSlow(HInstruction* instruction,
1991*795d594fSAndroid Build Coastguard Worker Location out,
1992*795d594fSAndroid Build Coastguard Worker Location root) {
1993*795d594fSAndroid Build Coastguard Worker DCHECK(EmitReadBarrier());
1994*795d594fSAndroid Build Coastguard Worker
1995*795d594fSAndroid Build Coastguard Worker // Insert a slow path based read barrier *after* the GC root load.
1996*795d594fSAndroid Build Coastguard Worker //
1997*795d594fSAndroid Build Coastguard Worker // Note that GC roots are not affected by heap poisoning, so we do
1998*795d594fSAndroid Build Coastguard Worker // not need to do anything special for this here.
1999*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path =
2000*795d594fSAndroid Build Coastguard Worker new (GetScopedAllocator()) ReadBarrierForRootSlowPathRISCV64(instruction, out, root);
2001*795d594fSAndroid Build Coastguard Worker AddSlowPath(slow_path);
2002*795d594fSAndroid Build Coastguard Worker
2003*795d594fSAndroid Build Coastguard Worker __ J(slow_path->GetEntryLabel());
2004*795d594fSAndroid Build Coastguard Worker __ Bind(slow_path->GetExitLabel());
2005*795d594fSAndroid Build Coastguard Worker }
2006*795d594fSAndroid Build Coastguard Worker
HandleGoto(HInstruction * instruction,HBasicBlock * successor)2007*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::HandleGoto(HInstruction* instruction,
2008*795d594fSAndroid Build Coastguard Worker HBasicBlock* successor) {
2009*795d594fSAndroid Build Coastguard Worker if (successor->IsExitBlock()) {
2010*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->GetPrevious()->AlwaysThrows());
2011*795d594fSAndroid Build Coastguard Worker return; // no code needed
2012*795d594fSAndroid Build Coastguard Worker }
2013*795d594fSAndroid Build Coastguard Worker
2014*795d594fSAndroid Build Coastguard Worker HBasicBlock* block = instruction->GetBlock();
2015*795d594fSAndroid Build Coastguard Worker HInstruction* previous = instruction->GetPrevious();
2016*795d594fSAndroid Build Coastguard Worker HLoopInformation* info = block->GetLoopInformation();
2017*795d594fSAndroid Build Coastguard Worker
2018*795d594fSAndroid Build Coastguard Worker if (info != nullptr && info->IsBackEdge(*block) && info->HasSuspendCheck()) {
2019*795d594fSAndroid Build Coastguard Worker codegen_->MaybeIncrementHotness(info->GetSuspendCheck(), /*is_frame_entry=*/ false);
2020*795d594fSAndroid Build Coastguard Worker GenerateSuspendCheck(info->GetSuspendCheck(), successor);
2021*795d594fSAndroid Build Coastguard Worker return; // `GenerateSuspendCheck()` emitted the jump.
2022*795d594fSAndroid Build Coastguard Worker }
2023*795d594fSAndroid Build Coastguard Worker if (block->IsEntryBlock() && previous != nullptr && previous->IsSuspendCheck()) {
2024*795d594fSAndroid Build Coastguard Worker GenerateSuspendCheck(previous->AsSuspendCheck(), nullptr);
2025*795d594fSAndroid Build Coastguard Worker }
2026*795d594fSAndroid Build Coastguard Worker if (!codegen_->GoesToNextBlock(block, successor)) {
2027*795d594fSAndroid Build Coastguard Worker __ J(codegen_->GetLabelOf(successor));
2028*795d594fSAndroid Build Coastguard Worker }
2029*795d594fSAndroid Build Coastguard Worker }
2030*795d594fSAndroid Build Coastguard Worker
GenPackedSwitchWithCompares(XRegister adjusted,XRegister temp,uint32_t num_entries,HBasicBlock * switch_block)2031*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenPackedSwitchWithCompares(XRegister adjusted,
2032*795d594fSAndroid Build Coastguard Worker XRegister temp,
2033*795d594fSAndroid Build Coastguard Worker uint32_t num_entries,
2034*795d594fSAndroid Build Coastguard Worker HBasicBlock* switch_block) {
2035*795d594fSAndroid Build Coastguard Worker // Note: The `adjusted` register holds `value - lower_bound`. If the `lower_bound` is 0,
2036*795d594fSAndroid Build Coastguard Worker // `adjusted` is the original `value` register and we must not clobber it. Otherwise,
2037*795d594fSAndroid Build Coastguard Worker // `adjusted` is the `temp`. The caller already emitted the `adjusted < num_entries` check.
2038*795d594fSAndroid Build Coastguard Worker
2039*795d594fSAndroid Build Coastguard Worker // Create a set of compare/jumps.
2040*795d594fSAndroid Build Coastguard Worker ArrayRef<HBasicBlock* const> successors(switch_block->GetSuccessors());
2041*795d594fSAndroid Build Coastguard Worker uint32_t index = 0;
2042*795d594fSAndroid Build Coastguard Worker for (; num_entries - index >= 2u; index += 2u) {
2043*795d594fSAndroid Build Coastguard Worker // Jump to `successors[index]` if `value == lower_bound + index`.
2044*795d594fSAndroid Build Coastguard Worker // Note that `adjusted` holds `value - lower_bound - index`.
2045*795d594fSAndroid Build Coastguard Worker __ Beqz(adjusted, codegen_->GetLabelOf(successors[index]));
2046*795d594fSAndroid Build Coastguard Worker if (num_entries - index == 2u) {
2047*795d594fSAndroid Build Coastguard Worker break; // The last entry shall match, so the branch shall be unconditional.
2048*795d594fSAndroid Build Coastguard Worker }
2049*795d594fSAndroid Build Coastguard Worker // Jump to `successors[index + 1]` if `value == lower_bound + index + 1`.
2050*795d594fSAndroid Build Coastguard Worker // Modify `adjusted` to hold `value - lower_bound - index - 2` for this comparison.
2051*795d594fSAndroid Build Coastguard Worker __ Addi(temp, adjusted, -2);
2052*795d594fSAndroid Build Coastguard Worker adjusted = temp;
2053*795d594fSAndroid Build Coastguard Worker __ Bltz(adjusted, codegen_->GetLabelOf(successors[index + 1]));
2054*795d594fSAndroid Build Coastguard Worker }
2055*795d594fSAndroid Build Coastguard Worker // For the last entry, unconditionally jump to `successors[num_entries - 1]`.
2056*795d594fSAndroid Build Coastguard Worker __ J(codegen_->GetLabelOf(successors[num_entries - 1u]));
2057*795d594fSAndroid Build Coastguard Worker }
2058*795d594fSAndroid Build Coastguard Worker
GenTableBasedPackedSwitch(XRegister adjusted,XRegister temp,uint32_t num_entries,HBasicBlock * switch_block)2059*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenTableBasedPackedSwitch(XRegister adjusted,
2060*795d594fSAndroid Build Coastguard Worker XRegister temp,
2061*795d594fSAndroid Build Coastguard Worker uint32_t num_entries,
2062*795d594fSAndroid Build Coastguard Worker HBasicBlock* switch_block) {
2063*795d594fSAndroid Build Coastguard Worker // Note: The `adjusted` register holds `value - lower_bound`. If the `lower_bound` is 0,
2064*795d594fSAndroid Build Coastguard Worker // `adjusted` is the original `value` register and we must not clobber it. Otherwise,
2065*795d594fSAndroid Build Coastguard Worker // `adjusted` is the `temp`. The caller already emitted the `adjusted < num_entries` check.
2066*795d594fSAndroid Build Coastguard Worker
2067*795d594fSAndroid Build Coastguard Worker // Create a jump table.
2068*795d594fSAndroid Build Coastguard Worker ArenaVector<Riscv64Label*> labels(num_entries,
2069*795d594fSAndroid Build Coastguard Worker __ GetAllocator()->Adapter(kArenaAllocSwitchTable));
2070*795d594fSAndroid Build Coastguard Worker const ArenaVector<HBasicBlock*>& successors = switch_block->GetSuccessors();
2071*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < num_entries; i++) {
2072*795d594fSAndroid Build Coastguard Worker labels[i] = codegen_->GetLabelOf(successors[i]);
2073*795d594fSAndroid Build Coastguard Worker }
2074*795d594fSAndroid Build Coastguard Worker JumpTable* table = __ CreateJumpTable(std::move(labels));
2075*795d594fSAndroid Build Coastguard Worker
2076*795d594fSAndroid Build Coastguard Worker // Load the address of the jump table.
2077*795d594fSAndroid Build Coastguard Worker // Note: The `LoadLabelAddress()` emits AUIPC+ADD. It is possible to avoid the ADD and
2078*795d594fSAndroid Build Coastguard Worker // instead embed that offset in the LW below as well as all jump table entries but
2079*795d594fSAndroid Build Coastguard Worker // that would need some invasive changes in the jump table handling in the assembler.
2080*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
2081*795d594fSAndroid Build Coastguard Worker XRegister table_base = srs.AllocateXRegister();
2082*795d594fSAndroid Build Coastguard Worker __ LoadLabelAddress(table_base, table->GetLabel());
2083*795d594fSAndroid Build Coastguard Worker
2084*795d594fSAndroid Build Coastguard Worker // Load the PC difference from the jump table.
2085*795d594fSAndroid Build Coastguard Worker // TODO(riscv64): Use SH2ADD from the Zba extension.
2086*795d594fSAndroid Build Coastguard Worker __ Slli(temp, adjusted, 2);
2087*795d594fSAndroid Build Coastguard Worker __ Add(temp, temp, table_base);
2088*795d594fSAndroid Build Coastguard Worker __ Lw(temp, temp, 0);
2089*795d594fSAndroid Build Coastguard Worker
2090*795d594fSAndroid Build Coastguard Worker // Compute the absolute target address by adding the table start address
2091*795d594fSAndroid Build Coastguard Worker // (the table contains offsets to targets relative to its start).
2092*795d594fSAndroid Build Coastguard Worker __ Add(temp, temp, table_base);
2093*795d594fSAndroid Build Coastguard Worker // And jump.
2094*795d594fSAndroid Build Coastguard Worker __ Jr(temp);
2095*795d594fSAndroid Build Coastguard Worker }
2096*795d594fSAndroid Build Coastguard Worker
VecAddress(LocationSummary * locations,size_t size,XRegister * adjusted_base)2097*795d594fSAndroid Build Coastguard Worker int32_t InstructionCodeGeneratorRISCV64::VecAddress(LocationSummary* locations,
2098*795d594fSAndroid Build Coastguard Worker size_t size,
2099*795d594fSAndroid Build Coastguard Worker /*out*/ XRegister* adjusted_base) {
2100*795d594fSAndroid Build Coastguard Worker UNUSED(locations);
2101*795d594fSAndroid Build Coastguard Worker UNUSED(size);
2102*795d594fSAndroid Build Coastguard Worker UNUSED(adjusted_base);
2103*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
2104*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
2105*795d594fSAndroid Build Coastguard Worker }
2106*795d594fSAndroid Build Coastguard Worker
HandleBinaryOp(HBinaryOperation * instruction)2107*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::HandleBinaryOp(HBinaryOperation* instruction) {
2108*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(instruction->InputCount(), 2u);
2109*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
2110*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetResultType();
2111*795d594fSAndroid Build Coastguard Worker switch (type) {
2112*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
2113*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64: {
2114*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
2115*795d594fSAndroid Build Coastguard Worker HInstruction* right = instruction->InputAt(1);
2116*795d594fSAndroid Build Coastguard Worker bool can_use_imm = false;
2117*795d594fSAndroid Build Coastguard Worker if (instruction->IsMin() || instruction->IsMax()) {
2118*795d594fSAndroid Build Coastguard Worker can_use_imm = IsZeroBitPattern(instruction);
2119*795d594fSAndroid Build Coastguard Worker } else if (right->IsConstant()) {
2120*795d594fSAndroid Build Coastguard Worker int64_t imm = CodeGenerator::GetInt64ValueOf(right->AsConstant());
2121*795d594fSAndroid Build Coastguard Worker can_use_imm = IsInt<12>(instruction->IsSub() ? -imm : imm);
2122*795d594fSAndroid Build Coastguard Worker }
2123*795d594fSAndroid Build Coastguard Worker if (can_use_imm) {
2124*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::ConstantLocation(right));
2125*795d594fSAndroid Build Coastguard Worker } else {
2126*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RequiresRegister());
2127*795d594fSAndroid Build Coastguard Worker }
2128*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2129*795d594fSAndroid Build Coastguard Worker break;
2130*795d594fSAndroid Build Coastguard Worker }
2131*795d594fSAndroid Build Coastguard Worker
2132*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
2133*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
2134*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresFpuRegister());
2135*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RequiresFpuRegister());
2136*795d594fSAndroid Build Coastguard Worker if (instruction->IsMin() || instruction->IsMax()) {
2137*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresFpuRegister(), Location::kOutputOverlap);
2138*795d594fSAndroid Build Coastguard Worker } else {
2139*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
2140*795d594fSAndroid Build Coastguard Worker }
2141*795d594fSAndroid Build Coastguard Worker break;
2142*795d594fSAndroid Build Coastguard Worker
2143*795d594fSAndroid Build Coastguard Worker default:
2144*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected " << instruction->DebugName() << " type " << type;
2145*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
2146*795d594fSAndroid Build Coastguard Worker }
2147*795d594fSAndroid Build Coastguard Worker }
2148*795d594fSAndroid Build Coastguard Worker
HandleBinaryOp(HBinaryOperation * instruction)2149*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::HandleBinaryOp(HBinaryOperation* instruction) {
2150*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetType();
2151*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
2152*795d594fSAndroid Build Coastguard Worker
2153*795d594fSAndroid Build Coastguard Worker switch (type) {
2154*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
2155*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64: {
2156*795d594fSAndroid Build Coastguard Worker XRegister rd = locations->Out().AsRegister<XRegister>();
2157*795d594fSAndroid Build Coastguard Worker XRegister rs1 = locations->InAt(0).AsRegister<XRegister>();
2158*795d594fSAndroid Build Coastguard Worker Location rs2_location = locations->InAt(1);
2159*795d594fSAndroid Build Coastguard Worker
2160*795d594fSAndroid Build Coastguard Worker bool use_imm = rs2_location.IsConstant();
2161*795d594fSAndroid Build Coastguard Worker XRegister rs2 = use_imm ? kNoXRegister : rs2_location.AsRegister<XRegister>();
2162*795d594fSAndroid Build Coastguard Worker int64_t imm = use_imm ? CodeGenerator::GetInt64ValueOf(rs2_location.GetConstant()) : 0;
2163*795d594fSAndroid Build Coastguard Worker
2164*795d594fSAndroid Build Coastguard Worker if (instruction->IsAnd()) {
2165*795d594fSAndroid Build Coastguard Worker if (use_imm) {
2166*795d594fSAndroid Build Coastguard Worker __ Andi(rd, rs1, imm);
2167*795d594fSAndroid Build Coastguard Worker } else {
2168*795d594fSAndroid Build Coastguard Worker __ And(rd, rs1, rs2);
2169*795d594fSAndroid Build Coastguard Worker }
2170*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsOr()) {
2171*795d594fSAndroid Build Coastguard Worker if (use_imm) {
2172*795d594fSAndroid Build Coastguard Worker __ Ori(rd, rs1, imm);
2173*795d594fSAndroid Build Coastguard Worker } else {
2174*795d594fSAndroid Build Coastguard Worker __ Or(rd, rs1, rs2);
2175*795d594fSAndroid Build Coastguard Worker }
2176*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsXor()) {
2177*795d594fSAndroid Build Coastguard Worker if (use_imm) {
2178*795d594fSAndroid Build Coastguard Worker __ Xori(rd, rs1, imm);
2179*795d594fSAndroid Build Coastguard Worker } else {
2180*795d594fSAndroid Build Coastguard Worker __ Xor(rd, rs1, rs2);
2181*795d594fSAndroid Build Coastguard Worker }
2182*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsAdd() || instruction->IsSub()) {
2183*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kInt32) {
2184*795d594fSAndroid Build Coastguard Worker if (use_imm) {
2185*795d594fSAndroid Build Coastguard Worker __ Addiw(rd, rs1, instruction->IsSub() ? -imm : imm);
2186*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsAdd()) {
2187*795d594fSAndroid Build Coastguard Worker __ Addw(rd, rs1, rs2);
2188*795d594fSAndroid Build Coastguard Worker } else {
2189*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsSub());
2190*795d594fSAndroid Build Coastguard Worker __ Subw(rd, rs1, rs2);
2191*795d594fSAndroid Build Coastguard Worker }
2192*795d594fSAndroid Build Coastguard Worker } else {
2193*795d594fSAndroid Build Coastguard Worker if (use_imm) {
2194*795d594fSAndroid Build Coastguard Worker __ Addi(rd, rs1, instruction->IsSub() ? -imm : imm);
2195*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsAdd()) {
2196*795d594fSAndroid Build Coastguard Worker __ Add(rd, rs1, rs2);
2197*795d594fSAndroid Build Coastguard Worker } else {
2198*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsSub());
2199*795d594fSAndroid Build Coastguard Worker __ Sub(rd, rs1, rs2);
2200*795d594fSAndroid Build Coastguard Worker }
2201*795d594fSAndroid Build Coastguard Worker }
2202*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsMin()) {
2203*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(use_imm, imm == 0);
2204*795d594fSAndroid Build Coastguard Worker __ Min(rd, rs1, use_imm ? Zero : rs2);
2205*795d594fSAndroid Build Coastguard Worker } else {
2206*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsMax());
2207*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(use_imm, imm == 0);
2208*795d594fSAndroid Build Coastguard Worker __ Max(rd, rs1, use_imm ? Zero : rs2);
2209*795d594fSAndroid Build Coastguard Worker }
2210*795d594fSAndroid Build Coastguard Worker break;
2211*795d594fSAndroid Build Coastguard Worker }
2212*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
2213*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64: {
2214*795d594fSAndroid Build Coastguard Worker FRegister rd = locations->Out().AsFpuRegister<FRegister>();
2215*795d594fSAndroid Build Coastguard Worker FRegister rs1 = locations->InAt(0).AsFpuRegister<FRegister>();
2216*795d594fSAndroid Build Coastguard Worker FRegister rs2 = locations->InAt(1).AsFpuRegister<FRegister>();
2217*795d594fSAndroid Build Coastguard Worker if (instruction->IsAdd()) {
2218*795d594fSAndroid Build Coastguard Worker FAdd(rd, rs1, rs2, type);
2219*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsSub()) {
2220*795d594fSAndroid Build Coastguard Worker FSub(rd, rs1, rs2, type);
2221*795d594fSAndroid Build Coastguard Worker } else {
2222*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsMin() || instruction->IsMax());
2223*795d594fSAndroid Build Coastguard Worker // If one of the operands is NaN and the other is not, riscv64 instructions FMIN/FMAX
2224*795d594fSAndroid Build Coastguard Worker // return the other operand while we want to return the NaN operand.
2225*795d594fSAndroid Build Coastguard Worker DCHECK_NE(rd, rs1); // Requested `Location::kOutputOverlap`.
2226*795d594fSAndroid Build Coastguard Worker DCHECK_NE(rd, rs2); // Requested `Location::kOutputOverlap`.
2227*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
2228*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
2229*795d594fSAndroid Build Coastguard Worker XRegister tmp2 = srs.AllocateXRegister();
2230*795d594fSAndroid Build Coastguard Worker Riscv64Label done;
2231*795d594fSAndroid Build Coastguard Worker // Return `rs1` if it's NaN.
2232*795d594fSAndroid Build Coastguard Worker FClass(tmp, rs1, type);
2233*795d594fSAndroid Build Coastguard Worker __ Li(tmp2, kFClassNaNMinValue);
2234*795d594fSAndroid Build Coastguard Worker FMv(rd, rs1, type);
2235*795d594fSAndroid Build Coastguard Worker __ Bgeu(tmp, tmp2, &done);
2236*795d594fSAndroid Build Coastguard Worker // Return `rs2` if it's NaN.
2237*795d594fSAndroid Build Coastguard Worker FClass(tmp, rs2, type);
2238*795d594fSAndroid Build Coastguard Worker FMv(rd, rs2, type);
2239*795d594fSAndroid Build Coastguard Worker __ Bgeu(tmp, tmp2, &done);
2240*795d594fSAndroid Build Coastguard Worker // Calculate Min/Max for non-NaN arguments.
2241*795d594fSAndroid Build Coastguard Worker if (instruction->IsMin()) {
2242*795d594fSAndroid Build Coastguard Worker FMin(rd, rs1, rs2, type);
2243*795d594fSAndroid Build Coastguard Worker } else {
2244*795d594fSAndroid Build Coastguard Worker FMax(rd, rs1, rs2, type);
2245*795d594fSAndroid Build Coastguard Worker }
2246*795d594fSAndroid Build Coastguard Worker __ Bind(&done);
2247*795d594fSAndroid Build Coastguard Worker }
2248*795d594fSAndroid Build Coastguard Worker break;
2249*795d594fSAndroid Build Coastguard Worker }
2250*795d594fSAndroid Build Coastguard Worker default:
2251*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected binary operation type " << type;
2252*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
2253*795d594fSAndroid Build Coastguard Worker }
2254*795d594fSAndroid Build Coastguard Worker }
2255*795d594fSAndroid Build Coastguard Worker
HandleCondition(HCondition * instruction)2256*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::HandleCondition(HCondition* instruction) {
2257*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
2258*795d594fSAndroid Build Coastguard Worker switch (instruction->InputAt(0)->GetType()) {
2259*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
2260*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
2261*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresFpuRegister());
2262*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RequiresFpuRegister());
2263*795d594fSAndroid Build Coastguard Worker break;
2264*795d594fSAndroid Build Coastguard Worker
2265*795d594fSAndroid Build Coastguard Worker default: {
2266*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
2267*795d594fSAndroid Build Coastguard Worker HInstruction* rhs = instruction->InputAt(1);
2268*795d594fSAndroid Build Coastguard Worker bool use_imm = false;
2269*795d594fSAndroid Build Coastguard Worker if (rhs->IsConstant()) {
2270*795d594fSAndroid Build Coastguard Worker int64_t imm = CodeGenerator::GetInt64ValueOf(rhs->AsConstant());
2271*795d594fSAndroid Build Coastguard Worker if (instruction->IsEmittedAtUseSite()) {
2272*795d594fSAndroid Build Coastguard Worker // For `HIf`, materialize all non-zero constants with an `HParallelMove`.
2273*795d594fSAndroid Build Coastguard Worker // Note: For certain constants and conditions, the code could be improved.
2274*795d594fSAndroid Build Coastguard Worker // For example, 2048 takes two instructions to materialize but the negative
2275*795d594fSAndroid Build Coastguard Worker // -2048 could be embedded in ADDI for EQ/NE comparison.
2276*795d594fSAndroid Build Coastguard Worker use_imm = (imm == 0);
2277*795d594fSAndroid Build Coastguard Worker } else {
2278*795d594fSAndroid Build Coastguard Worker // Constants that cannot be embedded in an instruction's 12-bit immediate shall be
2279*795d594fSAndroid Build Coastguard Worker // materialized with an `HParallelMove`. This simplifies the code and avoids cases
2280*795d594fSAndroid Build Coastguard Worker // with arithmetic overflow. Adjust the `imm` if needed for a particular instruction.
2281*795d594fSAndroid Build Coastguard Worker switch (instruction->GetCondition()) {
2282*795d594fSAndroid Build Coastguard Worker case kCondEQ:
2283*795d594fSAndroid Build Coastguard Worker case kCondNE:
2284*795d594fSAndroid Build Coastguard Worker imm = -imm; // ADDI with negative immediate (there is no SUBI).
2285*795d594fSAndroid Build Coastguard Worker break;
2286*795d594fSAndroid Build Coastguard Worker case kCondLE:
2287*795d594fSAndroid Build Coastguard Worker case kCondGT:
2288*795d594fSAndroid Build Coastguard Worker case kCondBE:
2289*795d594fSAndroid Build Coastguard Worker case kCondA:
2290*795d594fSAndroid Build Coastguard Worker imm += 1; // SLTI/SLTIU with adjusted immediate (there is no SLEI/SLEIU).
2291*795d594fSAndroid Build Coastguard Worker break;
2292*795d594fSAndroid Build Coastguard Worker default:
2293*795d594fSAndroid Build Coastguard Worker break;
2294*795d594fSAndroid Build Coastguard Worker }
2295*795d594fSAndroid Build Coastguard Worker use_imm = IsInt<12>(imm);
2296*795d594fSAndroid Build Coastguard Worker }
2297*795d594fSAndroid Build Coastguard Worker }
2298*795d594fSAndroid Build Coastguard Worker if (use_imm) {
2299*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::ConstantLocation(rhs));
2300*795d594fSAndroid Build Coastguard Worker } else {
2301*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RequiresRegister());
2302*795d594fSAndroid Build Coastguard Worker }
2303*795d594fSAndroid Build Coastguard Worker break;
2304*795d594fSAndroid Build Coastguard Worker }
2305*795d594fSAndroid Build Coastguard Worker }
2306*795d594fSAndroid Build Coastguard Worker if (!instruction->IsEmittedAtUseSite()) {
2307*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2308*795d594fSAndroid Build Coastguard Worker }
2309*795d594fSAndroid Build Coastguard Worker }
2310*795d594fSAndroid Build Coastguard Worker
HandleCondition(HCondition * instruction)2311*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::HandleCondition(HCondition* instruction) {
2312*795d594fSAndroid Build Coastguard Worker if (instruction->IsEmittedAtUseSite()) {
2313*795d594fSAndroid Build Coastguard Worker return;
2314*795d594fSAndroid Build Coastguard Worker }
2315*795d594fSAndroid Build Coastguard Worker
2316*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->InputAt(0)->GetType();
2317*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
2318*795d594fSAndroid Build Coastguard Worker switch (type) {
2319*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
2320*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
2321*795d594fSAndroid Build Coastguard Worker GenerateFpCondition(instruction->GetCondition(), instruction->IsGtBias(), type, locations);
2322*795d594fSAndroid Build Coastguard Worker return;
2323*795d594fSAndroid Build Coastguard Worker default:
2324*795d594fSAndroid Build Coastguard Worker // Integral types and reference equality.
2325*795d594fSAndroid Build Coastguard Worker GenerateIntLongCondition(instruction->GetCondition(), locations);
2326*795d594fSAndroid Build Coastguard Worker return;
2327*795d594fSAndroid Build Coastguard Worker }
2328*795d594fSAndroid Build Coastguard Worker }
2329*795d594fSAndroid Build Coastguard Worker
HandleShift(HBinaryOperation * instruction)2330*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::HandleShift(HBinaryOperation* instruction) {
2331*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsShl() ||
2332*795d594fSAndroid Build Coastguard Worker instruction->IsShr() ||
2333*795d594fSAndroid Build Coastguard Worker instruction->IsUShr() ||
2334*795d594fSAndroid Build Coastguard Worker instruction->IsRol() ||
2335*795d594fSAndroid Build Coastguard Worker instruction->IsRor());
2336*795d594fSAndroid Build Coastguard Worker
2337*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
2338*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetResultType();
2339*795d594fSAndroid Build Coastguard Worker switch (type) {
2340*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
2341*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64: {
2342*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
2343*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
2344*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2345*795d594fSAndroid Build Coastguard Worker break;
2346*795d594fSAndroid Build Coastguard Worker }
2347*795d594fSAndroid Build Coastguard Worker default:
2348*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected shift type " << type;
2349*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
2350*795d594fSAndroid Build Coastguard Worker }
2351*795d594fSAndroid Build Coastguard Worker }
2352*795d594fSAndroid Build Coastguard Worker
HandleShift(HBinaryOperation * instruction)2353*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::HandleShift(HBinaryOperation* instruction) {
2354*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsShl() ||
2355*795d594fSAndroid Build Coastguard Worker instruction->IsShr() ||
2356*795d594fSAndroid Build Coastguard Worker instruction->IsUShr() ||
2357*795d594fSAndroid Build Coastguard Worker instruction->IsRol() ||
2358*795d594fSAndroid Build Coastguard Worker instruction->IsRor());
2359*795d594fSAndroid Build Coastguard Worker
2360*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
2361*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetType();
2362*795d594fSAndroid Build Coastguard Worker
2363*795d594fSAndroid Build Coastguard Worker switch (type) {
2364*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
2365*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64: {
2366*795d594fSAndroid Build Coastguard Worker XRegister rd = locations->Out().AsRegister<XRegister>();
2367*795d594fSAndroid Build Coastguard Worker XRegister rs1 = locations->InAt(0).AsRegister<XRegister>();
2368*795d594fSAndroid Build Coastguard Worker Location rs2_location = locations->InAt(1);
2369*795d594fSAndroid Build Coastguard Worker
2370*795d594fSAndroid Build Coastguard Worker if (rs2_location.IsConstant()) {
2371*795d594fSAndroid Build Coastguard Worker int64_t imm = CodeGenerator::GetInt64ValueOf(rs2_location.GetConstant());
2372*795d594fSAndroid Build Coastguard Worker if (instruction->IsRol()) {
2373*795d594fSAndroid Build Coastguard Worker imm = -imm;
2374*795d594fSAndroid Build Coastguard Worker }
2375*795d594fSAndroid Build Coastguard Worker uint32_t shamt =
2376*795d594fSAndroid Build Coastguard Worker imm & (type == DataType::Type::kInt32 ? kMaxIntShiftDistance : kMaxLongShiftDistance);
2377*795d594fSAndroid Build Coastguard Worker
2378*795d594fSAndroid Build Coastguard Worker if (shamt == 0) {
2379*795d594fSAndroid Build Coastguard Worker if (rd != rs1) {
2380*795d594fSAndroid Build Coastguard Worker __ Mv(rd, rs1);
2381*795d594fSAndroid Build Coastguard Worker }
2382*795d594fSAndroid Build Coastguard Worker } else if (type == DataType::Type::kInt32) {
2383*795d594fSAndroid Build Coastguard Worker if (instruction->IsShl()) {
2384*795d594fSAndroid Build Coastguard Worker __ Slliw(rd, rs1, shamt);
2385*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsShr()) {
2386*795d594fSAndroid Build Coastguard Worker __ Sraiw(rd, rs1, shamt);
2387*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsUShr()) {
2388*795d594fSAndroid Build Coastguard Worker __ Srliw(rd, rs1, shamt);
2389*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsRol()) {
2390*795d594fSAndroid Build Coastguard Worker __ Roriw(rd, rs1, shamt);
2391*795d594fSAndroid Build Coastguard Worker } else {
2392*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsRor());
2393*795d594fSAndroid Build Coastguard Worker __ Roriw(rd, rs1, shamt);
2394*795d594fSAndroid Build Coastguard Worker }
2395*795d594fSAndroid Build Coastguard Worker } else {
2396*795d594fSAndroid Build Coastguard Worker if (instruction->IsShl()) {
2397*795d594fSAndroid Build Coastguard Worker __ Slli(rd, rs1, shamt);
2398*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsShr()) {
2399*795d594fSAndroid Build Coastguard Worker __ Srai(rd, rs1, shamt);
2400*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsUShr()) {
2401*795d594fSAndroid Build Coastguard Worker __ Srli(rd, rs1, shamt);
2402*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsRol()) {
2403*795d594fSAndroid Build Coastguard Worker __ Rori(rd, rs1, shamt);
2404*795d594fSAndroid Build Coastguard Worker } else {
2405*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsRor());
2406*795d594fSAndroid Build Coastguard Worker __ Rori(rd, rs1, shamt);
2407*795d594fSAndroid Build Coastguard Worker }
2408*795d594fSAndroid Build Coastguard Worker }
2409*795d594fSAndroid Build Coastguard Worker } else {
2410*795d594fSAndroid Build Coastguard Worker XRegister rs2 = rs2_location.AsRegister<XRegister>();
2411*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kInt32) {
2412*795d594fSAndroid Build Coastguard Worker if (instruction->IsShl()) {
2413*795d594fSAndroid Build Coastguard Worker __ Sllw(rd, rs1, rs2);
2414*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsShr()) {
2415*795d594fSAndroid Build Coastguard Worker __ Sraw(rd, rs1, rs2);
2416*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsUShr()) {
2417*795d594fSAndroid Build Coastguard Worker __ Srlw(rd, rs1, rs2);
2418*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsRol()) {
2419*795d594fSAndroid Build Coastguard Worker __ Rolw(rd, rs1, rs2);
2420*795d594fSAndroid Build Coastguard Worker } else {
2421*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsRor());
2422*795d594fSAndroid Build Coastguard Worker __ Rorw(rd, rs1, rs2);
2423*795d594fSAndroid Build Coastguard Worker }
2424*795d594fSAndroid Build Coastguard Worker } else {
2425*795d594fSAndroid Build Coastguard Worker if (instruction->IsShl()) {
2426*795d594fSAndroid Build Coastguard Worker __ Sll(rd, rs1, rs2);
2427*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsShr()) {
2428*795d594fSAndroid Build Coastguard Worker __ Sra(rd, rs1, rs2);
2429*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsUShr()) {
2430*795d594fSAndroid Build Coastguard Worker __ Srl(rd, rs1, rs2);
2431*795d594fSAndroid Build Coastguard Worker } else if (instruction->IsRol()) {
2432*795d594fSAndroid Build Coastguard Worker __ Rol(rd, rs1, rs2);
2433*795d594fSAndroid Build Coastguard Worker } else {
2434*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsRor());
2435*795d594fSAndroid Build Coastguard Worker __ Ror(rd, rs1, rs2);
2436*795d594fSAndroid Build Coastguard Worker }
2437*795d594fSAndroid Build Coastguard Worker }
2438*795d594fSAndroid Build Coastguard Worker }
2439*795d594fSAndroid Build Coastguard Worker break;
2440*795d594fSAndroid Build Coastguard Worker }
2441*795d594fSAndroid Build Coastguard Worker default:
2442*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected shift operation type " << type;
2443*795d594fSAndroid Build Coastguard Worker }
2444*795d594fSAndroid Build Coastguard Worker }
2445*795d594fSAndroid Build Coastguard Worker
MaybeMarkGCCard(XRegister object,XRegister value,bool value_can_be_null)2446*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::MaybeMarkGCCard(XRegister object,
2447*795d594fSAndroid Build Coastguard Worker XRegister value,
2448*795d594fSAndroid Build Coastguard Worker bool value_can_be_null) {
2449*795d594fSAndroid Build Coastguard Worker Riscv64Label done;
2450*795d594fSAndroid Build Coastguard Worker if (value_can_be_null) {
2451*795d594fSAndroid Build Coastguard Worker __ Beqz(value, &done);
2452*795d594fSAndroid Build Coastguard Worker }
2453*795d594fSAndroid Build Coastguard Worker MarkGCCard(object);
2454*795d594fSAndroid Build Coastguard Worker __ Bind(&done);
2455*795d594fSAndroid Build Coastguard Worker }
2456*795d594fSAndroid Build Coastguard Worker
MarkGCCard(XRegister object)2457*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::MarkGCCard(XRegister object) {
2458*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
2459*795d594fSAndroid Build Coastguard Worker XRegister card = srs.AllocateXRegister();
2460*795d594fSAndroid Build Coastguard Worker XRegister temp = srs.AllocateXRegister();
2461*795d594fSAndroid Build Coastguard Worker // Load the address of the card table into `card`.
2462*795d594fSAndroid Build Coastguard Worker __ Loadd(card, TR, Thread::CardTableOffset<kRiscv64PointerSize>().Int32Value());
2463*795d594fSAndroid Build Coastguard Worker
2464*795d594fSAndroid Build Coastguard Worker // Calculate the address of the card corresponding to `object`.
2465*795d594fSAndroid Build Coastguard Worker __ Srli(temp, object, gc::accounting::CardTable::kCardShift);
2466*795d594fSAndroid Build Coastguard Worker __ Add(temp, card, temp);
2467*795d594fSAndroid Build Coastguard Worker // Write the `art::gc::accounting::CardTable::kCardDirty` value into the
2468*795d594fSAndroid Build Coastguard Worker // `object`'s card.
2469*795d594fSAndroid Build Coastguard Worker //
2470*795d594fSAndroid Build Coastguard Worker // Register `card` contains the address of the card table. Note that the card
2471*795d594fSAndroid Build Coastguard Worker // table's base is biased during its creation so that it always starts at an
2472*795d594fSAndroid Build Coastguard Worker // address whose least-significant byte is equal to `kCardDirty` (see
2473*795d594fSAndroid Build Coastguard Worker // art::gc::accounting::CardTable::Create). Therefore the SB instruction
2474*795d594fSAndroid Build Coastguard Worker // below writes the `kCardDirty` (byte) value into the `object`'s card
2475*795d594fSAndroid Build Coastguard Worker // (located at `card + object >> kCardShift`).
2476*795d594fSAndroid Build Coastguard Worker //
2477*795d594fSAndroid Build Coastguard Worker // This dual use of the value in register `card` (1. to calculate the location
2478*795d594fSAndroid Build Coastguard Worker // of the card to mark; and 2. to load the `kCardDirty` value) saves a load
2479*795d594fSAndroid Build Coastguard Worker // (no need to explicitly load `kCardDirty` as an immediate value).
2480*795d594fSAndroid Build Coastguard Worker __ Sb(card, temp, 0); // No scratch register left for `Storeb()`.
2481*795d594fSAndroid Build Coastguard Worker }
2482*795d594fSAndroid Build Coastguard Worker
CheckGCCardIsValid(XRegister object)2483*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::CheckGCCardIsValid(XRegister object) {
2484*795d594fSAndroid Build Coastguard Worker Riscv64Label done;
2485*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
2486*795d594fSAndroid Build Coastguard Worker XRegister card = srs.AllocateXRegister();
2487*795d594fSAndroid Build Coastguard Worker XRegister temp = srs.AllocateXRegister();
2488*795d594fSAndroid Build Coastguard Worker // Load the address of the card table into `card`.
2489*795d594fSAndroid Build Coastguard Worker __ Loadd(card, TR, Thread::CardTableOffset<kRiscv64PointerSize>().Int32Value());
2490*795d594fSAndroid Build Coastguard Worker
2491*795d594fSAndroid Build Coastguard Worker // Calculate the address of the card corresponding to `object`.
2492*795d594fSAndroid Build Coastguard Worker __ Srli(temp, object, gc::accounting::CardTable::kCardShift);
2493*795d594fSAndroid Build Coastguard Worker __ Add(temp, card, temp);
2494*795d594fSAndroid Build Coastguard Worker // assert (!clean || !self->is_gc_marking)
2495*795d594fSAndroid Build Coastguard Worker __ Lb(temp, temp, 0);
2496*795d594fSAndroid Build Coastguard Worker static_assert(gc::accounting::CardTable::kCardClean == 0);
2497*795d594fSAndroid Build Coastguard Worker __ Bnez(temp, &done);
2498*795d594fSAndroid Build Coastguard Worker __ Loadw(temp, TR, Thread::IsGcMarkingOffset<kRiscv64PointerSize>().Int32Value());
2499*795d594fSAndroid Build Coastguard Worker __ Beqz(temp, &done);
2500*795d594fSAndroid Build Coastguard Worker __ Unimp();
2501*795d594fSAndroid Build Coastguard Worker __ Bind(&done);
2502*795d594fSAndroid Build Coastguard Worker }
2503*795d594fSAndroid Build Coastguard Worker
HandleFieldSet(HInstruction * instruction)2504*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::HandleFieldSet(HInstruction* instruction) {
2505*795d594fSAndroid Build Coastguard Worker LocationSummary* locations =
2506*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, LocationSummary::kNoCall);
2507*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
2508*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, ValueLocationForStore(instruction->InputAt(1)));
2509*795d594fSAndroid Build Coastguard Worker }
2510*795d594fSAndroid Build Coastguard Worker
HandleFieldSet(HInstruction * instruction,const FieldInfo & field_info,bool value_can_be_null,WriteBarrierKind write_barrier_kind)2511*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::HandleFieldSet(HInstruction* instruction,
2512*795d594fSAndroid Build Coastguard Worker const FieldInfo& field_info,
2513*795d594fSAndroid Build Coastguard Worker bool value_can_be_null,
2514*795d594fSAndroid Build Coastguard Worker WriteBarrierKind write_barrier_kind) {
2515*795d594fSAndroid Build Coastguard Worker DataType::Type type = field_info.GetFieldType();
2516*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
2517*795d594fSAndroid Build Coastguard Worker XRegister obj = locations->InAt(0).AsRegister<XRegister>();
2518*795d594fSAndroid Build Coastguard Worker Location value = locations->InAt(1);
2519*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(value.IsConstant(), IsZeroBitPattern(value.GetConstant()));
2520*795d594fSAndroid Build Coastguard Worker bool is_volatile = field_info.IsVolatile();
2521*795d594fSAndroid Build Coastguard Worker uint32_t offset = field_info.GetFieldOffset().Uint32Value();
2522*795d594fSAndroid Build Coastguard Worker
2523*795d594fSAndroid Build Coastguard Worker if (is_volatile) {
2524*795d594fSAndroid Build Coastguard Worker StoreSeqCst(value, obj, offset, type, instruction);
2525*795d594fSAndroid Build Coastguard Worker } else {
2526*795d594fSAndroid Build Coastguard Worker Store(value, obj, offset, type);
2527*795d594fSAndroid Build Coastguard Worker codegen_->MaybeRecordImplicitNullCheck(instruction);
2528*795d594fSAndroid Build Coastguard Worker }
2529*795d594fSAndroid Build Coastguard Worker
2530*795d594fSAndroid Build Coastguard Worker bool needs_write_barrier =
2531*795d594fSAndroid Build Coastguard Worker codegen_->StoreNeedsWriteBarrier(type, instruction->InputAt(1), write_barrier_kind);
2532*795d594fSAndroid Build Coastguard Worker if (needs_write_barrier) {
2533*795d594fSAndroid Build Coastguard Worker if (value.IsConstant()) {
2534*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(write_barrier_kind, WriteBarrierKind::kEmitBeingReliedOn);
2535*795d594fSAndroid Build Coastguard Worker codegen_->MarkGCCard(obj);
2536*795d594fSAndroid Build Coastguard Worker } else {
2537*795d594fSAndroid Build Coastguard Worker codegen_->MaybeMarkGCCard(
2538*795d594fSAndroid Build Coastguard Worker obj,
2539*795d594fSAndroid Build Coastguard Worker value.AsRegister<XRegister>(),
2540*795d594fSAndroid Build Coastguard Worker value_can_be_null && write_barrier_kind == WriteBarrierKind::kEmitNotBeingReliedOn);
2541*795d594fSAndroid Build Coastguard Worker }
2542*795d594fSAndroid Build Coastguard Worker } else if (codegen_->ShouldCheckGCCard(type, instruction->InputAt(1), write_barrier_kind)) {
2543*795d594fSAndroid Build Coastguard Worker codegen_->CheckGCCardIsValid(obj);
2544*795d594fSAndroid Build Coastguard Worker }
2545*795d594fSAndroid Build Coastguard Worker }
2546*795d594fSAndroid Build Coastguard Worker
HandleFieldGet(HInstruction * instruction)2547*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::HandleFieldGet(HInstruction* instruction) {
2548*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
2549*795d594fSAndroid Build Coastguard Worker
2550*795d594fSAndroid Build Coastguard Worker bool object_field_get_with_read_barrier =
2551*795d594fSAndroid Build Coastguard Worker (instruction->GetType() == DataType::Type::kReference) && codegen_->EmitReadBarrier();
2552*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(
2553*795d594fSAndroid Build Coastguard Worker instruction,
2554*795d594fSAndroid Build Coastguard Worker object_field_get_with_read_barrier
2555*795d594fSAndroid Build Coastguard Worker ? LocationSummary::kCallOnSlowPath
2556*795d594fSAndroid Build Coastguard Worker : LocationSummary::kNoCall);
2557*795d594fSAndroid Build Coastguard Worker
2558*795d594fSAndroid Build Coastguard Worker // Input for object receiver.
2559*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
2560*795d594fSAndroid Build Coastguard Worker
2561*795d594fSAndroid Build Coastguard Worker if (DataType::IsFloatingPointType(instruction->GetType())) {
2562*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresFpuRegister());
2563*795d594fSAndroid Build Coastguard Worker } else {
2564*795d594fSAndroid Build Coastguard Worker // The output overlaps for an object field get when read barriers
2565*795d594fSAndroid Build Coastguard Worker // are enabled: we do not want the load to overwrite the object's
2566*795d594fSAndroid Build Coastguard Worker // location, as we need it to emit the read barrier.
2567*795d594fSAndroid Build Coastguard Worker locations->SetOut(
2568*795d594fSAndroid Build Coastguard Worker Location::RequiresRegister(),
2569*795d594fSAndroid Build Coastguard Worker object_field_get_with_read_barrier ? Location::kOutputOverlap : Location::kNoOutputOverlap);
2570*795d594fSAndroid Build Coastguard Worker }
2571*795d594fSAndroid Build Coastguard Worker
2572*795d594fSAndroid Build Coastguard Worker if (object_field_get_with_read_barrier && kUseBakerReadBarrier) {
2573*795d594fSAndroid Build Coastguard Worker locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
2574*795d594fSAndroid Build Coastguard Worker // We need a temporary register for the read barrier marking slow
2575*795d594fSAndroid Build Coastguard Worker // path in CodeGeneratorRISCV64::GenerateFieldLoadWithBakerReadBarrier.
2576*795d594fSAndroid Build Coastguard Worker locations->AddTemp(Location::RequiresRegister());
2577*795d594fSAndroid Build Coastguard Worker }
2578*795d594fSAndroid Build Coastguard Worker }
2579*795d594fSAndroid Build Coastguard Worker
HandleFieldGet(HInstruction * instruction,const FieldInfo & field_info)2580*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::HandleFieldGet(HInstruction* instruction,
2581*795d594fSAndroid Build Coastguard Worker const FieldInfo& field_info) {
2582*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
2583*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(DataType::Size(field_info.GetFieldType()), DataType::Size(instruction->GetType()));
2584*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetType();
2585*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
2586*795d594fSAndroid Build Coastguard Worker Location obj_loc = locations->InAt(0);
2587*795d594fSAndroid Build Coastguard Worker XRegister obj = obj_loc.AsRegister<XRegister>();
2588*795d594fSAndroid Build Coastguard Worker Location dst_loc = locations->Out();
2589*795d594fSAndroid Build Coastguard Worker bool is_volatile = field_info.IsVolatile();
2590*795d594fSAndroid Build Coastguard Worker uint32_t offset = field_info.GetFieldOffset().Uint32Value();
2591*795d594fSAndroid Build Coastguard Worker
2592*795d594fSAndroid Build Coastguard Worker if (is_volatile) {
2593*795d594fSAndroid Build Coastguard Worker codegen_->GenerateMemoryBarrier(MemBarrierKind::kAnyAny);
2594*795d594fSAndroid Build Coastguard Worker }
2595*795d594fSAndroid Build Coastguard Worker
2596*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kReference && codegen_->EmitBakerReadBarrier()) {
2597*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Object> */ dst = *(obj + offset)
2598*795d594fSAndroid Build Coastguard Worker Location temp_loc = locations->GetTemp(0);
2599*795d594fSAndroid Build Coastguard Worker // Note that a potential implicit null check is handled in this
2600*795d594fSAndroid Build Coastguard Worker // CodeGeneratorRISCV64::GenerateFieldLoadWithBakerReadBarrier call.
2601*795d594fSAndroid Build Coastguard Worker codegen_->GenerateFieldLoadWithBakerReadBarrier(instruction,
2602*795d594fSAndroid Build Coastguard Worker dst_loc,
2603*795d594fSAndroid Build Coastguard Worker obj,
2604*795d594fSAndroid Build Coastguard Worker offset,
2605*795d594fSAndroid Build Coastguard Worker temp_loc,
2606*795d594fSAndroid Build Coastguard Worker /* needs_null_check= */ true);
2607*795d594fSAndroid Build Coastguard Worker } else {
2608*795d594fSAndroid Build Coastguard Worker Load(dst_loc, obj, offset, type);
2609*795d594fSAndroid Build Coastguard Worker codegen_->MaybeRecordImplicitNullCheck(instruction);
2610*795d594fSAndroid Build Coastguard Worker }
2611*795d594fSAndroid Build Coastguard Worker
2612*795d594fSAndroid Build Coastguard Worker if (is_volatile) {
2613*795d594fSAndroid Build Coastguard Worker codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny);
2614*795d594fSAndroid Build Coastguard Worker }
2615*795d594fSAndroid Build Coastguard Worker
2616*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kReference && !codegen_->EmitBakerReadBarrier()) {
2617*795d594fSAndroid Build Coastguard Worker // If read barriers are enabled, emit read barriers other than
2618*795d594fSAndroid Build Coastguard Worker // Baker's using a slow path (and also unpoison the loaded
2619*795d594fSAndroid Build Coastguard Worker // reference, if heap poisoning is enabled).
2620*795d594fSAndroid Build Coastguard Worker codegen_->MaybeGenerateReadBarrierSlow(instruction, dst_loc, dst_loc, obj_loc, offset);
2621*795d594fSAndroid Build Coastguard Worker }
2622*795d594fSAndroid Build Coastguard Worker }
2623*795d594fSAndroid Build Coastguard Worker
GenerateMethodEntryExitHook(HInstruction * instruction)2624*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::GenerateMethodEntryExitHook(HInstruction* instruction) {
2625*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path =
2626*795d594fSAndroid Build Coastguard Worker new (codegen_->GetScopedAllocator()) MethodEntryExitHooksSlowPathRISCV64(instruction);
2627*795d594fSAndroid Build Coastguard Worker codegen_->AddSlowPath(slow_path);
2628*795d594fSAndroid Build Coastguard Worker
2629*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope temps(GetAssembler());
2630*795d594fSAndroid Build Coastguard Worker XRegister tmp = temps.AllocateXRegister();
2631*795d594fSAndroid Build Coastguard Worker
2632*795d594fSAndroid Build Coastguard Worker if (instruction->IsMethodExitHook()) {
2633*795d594fSAndroid Build Coastguard Worker // Check if we are required to check if the caller needs a deoptimization. Strictly speaking it
2634*795d594fSAndroid Build Coastguard Worker // would be sufficient to check if CheckCallerForDeopt bit is set. Though it is faster to check
2635*795d594fSAndroid Build Coastguard Worker // if it is just non-zero. kCHA bit isn't used in debuggable runtimes as cha optimization is
2636*795d594fSAndroid Build Coastguard Worker // disabled in debuggable runtime. The other bit is used when this method itself requires a
2637*795d594fSAndroid Build Coastguard Worker // deoptimization due to redefinition. So it is safe to just check for non-zero value here.
2638*795d594fSAndroid Build Coastguard Worker __ Loadwu(tmp, SP, codegen_->GetStackOffsetOfShouldDeoptimizeFlag());
2639*795d594fSAndroid Build Coastguard Worker __ Bnez(tmp, slow_path->GetEntryLabel());
2640*795d594fSAndroid Build Coastguard Worker }
2641*795d594fSAndroid Build Coastguard Worker
2642*795d594fSAndroid Build Coastguard Worker uint64_t hook_offset = instruction->IsMethodExitHook() ?
2643*795d594fSAndroid Build Coastguard Worker instrumentation::Instrumentation::HaveMethodExitListenersOffset().SizeValue() :
2644*795d594fSAndroid Build Coastguard Worker instrumentation::Instrumentation::HaveMethodEntryListenersOffset().SizeValue();
2645*795d594fSAndroid Build Coastguard Worker auto [base_hook_address, hook_imm12] = SplitJitAddress(
2646*795d594fSAndroid Build Coastguard Worker reinterpret_cast64<uint64_t>(Runtime::Current()->GetInstrumentation()) + hook_offset);
2647*795d594fSAndroid Build Coastguard Worker __ LoadConst64(tmp, base_hook_address);
2648*795d594fSAndroid Build Coastguard Worker __ Lbu(tmp, tmp, hook_imm12);
2649*795d594fSAndroid Build Coastguard Worker // Check if there are any method entry / exit listeners. If no, continue.
2650*795d594fSAndroid Build Coastguard Worker __ Beqz(tmp, slow_path->GetExitLabel());
2651*795d594fSAndroid Build Coastguard Worker // Check if there are any slow (jvmti / trace with thread cpu time) method entry / exit listeners.
2652*795d594fSAndroid Build Coastguard Worker // If yes, just take the slow path.
2653*795d594fSAndroid Build Coastguard Worker static_assert(instrumentation::Instrumentation::kFastTraceListeners == 1u);
2654*795d594fSAndroid Build Coastguard Worker __ Addi(tmp, tmp, -1);
2655*795d594fSAndroid Build Coastguard Worker __ Bnez(tmp, slow_path->GetEntryLabel());
2656*795d594fSAndroid Build Coastguard Worker
2657*795d594fSAndroid Build Coastguard Worker // Allocate second core scratch register. We can no longer use `Stored()`
2658*795d594fSAndroid Build Coastguard Worker // and similar macro instructions because there is no core scratch register left.
2659*795d594fSAndroid Build Coastguard Worker XRegister tmp2 = temps.AllocateXRegister();
2660*795d594fSAndroid Build Coastguard Worker
2661*795d594fSAndroid Build Coastguard Worker // Check if there is place in the buffer to store a new entry, if no, take the slow path.
2662*795d594fSAndroid Build Coastguard Worker int32_t trace_buffer_curr_entry_offset =
2663*795d594fSAndroid Build Coastguard Worker Thread::TraceBufferCurrPtrOffset<kRiscv64PointerSize>().Int32Value();
2664*795d594fSAndroid Build Coastguard Worker __ Loadd(tmp, TR, trace_buffer_curr_entry_offset);
2665*795d594fSAndroid Build Coastguard Worker __ Loadd(tmp2, TR, Thread::TraceBufferPtrOffset<kRiscv64PointerSize>().SizeValue());
2666*795d594fSAndroid Build Coastguard Worker __ Addi(tmp, tmp, -dchecked_integral_cast<int32_t>(kNumEntriesForWallClock * sizeof(void*)));
2667*795d594fSAndroid Build Coastguard Worker __ Blt(tmp, tmp2, slow_path->GetEntryLabel());
2668*795d594fSAndroid Build Coastguard Worker
2669*795d594fSAndroid Build Coastguard Worker // Update the index in the `Thread`. Temporarily free `tmp2` to be used by `Stored()`.
2670*795d594fSAndroid Build Coastguard Worker temps.FreeXRegister(tmp2);
2671*795d594fSAndroid Build Coastguard Worker __ Stored(tmp, TR, trace_buffer_curr_entry_offset);
2672*795d594fSAndroid Build Coastguard Worker tmp2 = temps.AllocateXRegister();
2673*795d594fSAndroid Build Coastguard Worker
2674*795d594fSAndroid Build Coastguard Worker // Record method pointer and trace action.
2675*795d594fSAndroid Build Coastguard Worker __ Ld(tmp2, SP, 0);
2676*795d594fSAndroid Build Coastguard Worker // Use last two bits to encode trace method action. For MethodEntry it is 0
2677*795d594fSAndroid Build Coastguard Worker // so no need to set the bits since they are 0 already.
2678*795d594fSAndroid Build Coastguard Worker DCHECK_GE(ArtMethod::Alignment(kRuntimePointerSize), static_cast<size_t>(4));
2679*795d594fSAndroid Build Coastguard Worker static_assert(enum_cast<int32_t>(TraceAction::kTraceMethodEnter) == 0);
2680*795d594fSAndroid Build Coastguard Worker static_assert(enum_cast<int32_t>(TraceAction::kTraceMethodExit) == 1);
2681*795d594fSAndroid Build Coastguard Worker if (instruction->IsMethodExitHook()) {
2682*795d594fSAndroid Build Coastguard Worker __ Ori(tmp2, tmp2, enum_cast<int32_t>(TraceAction::kTraceMethodExit));
2683*795d594fSAndroid Build Coastguard Worker }
2684*795d594fSAndroid Build Coastguard Worker static_assert(IsInt<12>(kMethodOffsetInBytes)); // No free scratch register for `Stored()`.
2685*795d594fSAndroid Build Coastguard Worker __ Sd(tmp2, tmp, kMethodOffsetInBytes);
2686*795d594fSAndroid Build Coastguard Worker
2687*795d594fSAndroid Build Coastguard Worker // Record the timestamp.
2688*795d594fSAndroid Build Coastguard Worker __ RdTime(tmp2);
2689*795d594fSAndroid Build Coastguard Worker static_assert(IsInt<12>(kTimestampOffsetInBytes)); // No free scratch register for `Stored()`.
2690*795d594fSAndroid Build Coastguard Worker __ Sd(tmp2, tmp, kTimestampOffsetInBytes);
2691*795d594fSAndroid Build Coastguard Worker
2692*795d594fSAndroid Build Coastguard Worker __ Bind(slow_path->GetExitLabel());
2693*795d594fSAndroid Build Coastguard Worker }
2694*795d594fSAndroid Build Coastguard Worker
VisitAbove(HAbove * instruction)2695*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitAbove(HAbove* instruction) {
2696*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
2697*795d594fSAndroid Build Coastguard Worker }
2698*795d594fSAndroid Build Coastguard Worker
VisitAbove(HAbove * instruction)2699*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitAbove(HAbove* instruction) {
2700*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
2701*795d594fSAndroid Build Coastguard Worker }
2702*795d594fSAndroid Build Coastguard Worker
VisitAboveOrEqual(HAboveOrEqual * instruction)2703*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitAboveOrEqual(HAboveOrEqual* instruction) {
2704*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
2705*795d594fSAndroid Build Coastguard Worker }
2706*795d594fSAndroid Build Coastguard Worker
VisitAboveOrEqual(HAboveOrEqual * instruction)2707*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitAboveOrEqual(HAboveOrEqual* instruction) {
2708*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
2709*795d594fSAndroid Build Coastguard Worker }
2710*795d594fSAndroid Build Coastguard Worker
VisitAbs(HAbs * abs)2711*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitAbs(HAbs* abs) {
2712*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(abs);
2713*795d594fSAndroid Build Coastguard Worker switch (abs->GetResultType()) {
2714*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
2715*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
2716*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
2717*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2718*795d594fSAndroid Build Coastguard Worker break;
2719*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
2720*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
2721*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresFpuRegister());
2722*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
2723*795d594fSAndroid Build Coastguard Worker break;
2724*795d594fSAndroid Build Coastguard Worker default:
2725*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected abs type " << abs->GetResultType();
2726*795d594fSAndroid Build Coastguard Worker }
2727*795d594fSAndroid Build Coastguard Worker }
2728*795d594fSAndroid Build Coastguard Worker
VisitAbs(HAbs * abs)2729*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitAbs(HAbs* abs) {
2730*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = abs->GetLocations();
2731*795d594fSAndroid Build Coastguard Worker switch (abs->GetResultType()) {
2732*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32: {
2733*795d594fSAndroid Build Coastguard Worker XRegister in = locations->InAt(0).AsRegister<XRegister>();
2734*795d594fSAndroid Build Coastguard Worker XRegister out = locations->Out().AsRegister<XRegister>();
2735*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
2736*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
2737*795d594fSAndroid Build Coastguard Worker __ Sraiw(tmp, in, 31);
2738*795d594fSAndroid Build Coastguard Worker __ Xor(out, in, tmp);
2739*795d594fSAndroid Build Coastguard Worker __ Subw(out, out, tmp);
2740*795d594fSAndroid Build Coastguard Worker break;
2741*795d594fSAndroid Build Coastguard Worker }
2742*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64: {
2743*795d594fSAndroid Build Coastguard Worker XRegister in = locations->InAt(0).AsRegister<XRegister>();
2744*795d594fSAndroid Build Coastguard Worker XRegister out = locations->Out().AsRegister<XRegister>();
2745*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
2746*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
2747*795d594fSAndroid Build Coastguard Worker __ Srai(tmp, in, 63);
2748*795d594fSAndroid Build Coastguard Worker __ Xor(out, in, tmp);
2749*795d594fSAndroid Build Coastguard Worker __ Sub(out, out, tmp);
2750*795d594fSAndroid Build Coastguard Worker break;
2751*795d594fSAndroid Build Coastguard Worker }
2752*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
2753*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
2754*795d594fSAndroid Build Coastguard Worker FAbs(locations->Out().AsFpuRegister<FRegister>(),
2755*795d594fSAndroid Build Coastguard Worker locations->InAt(0).AsFpuRegister<FRegister>(),
2756*795d594fSAndroid Build Coastguard Worker abs->GetResultType());
2757*795d594fSAndroid Build Coastguard Worker break;
2758*795d594fSAndroid Build Coastguard Worker default:
2759*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected abs type " << abs->GetResultType();
2760*795d594fSAndroid Build Coastguard Worker }
2761*795d594fSAndroid Build Coastguard Worker }
2762*795d594fSAndroid Build Coastguard Worker
VisitAdd(HAdd * instruction)2763*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitAdd(HAdd* instruction) {
2764*795d594fSAndroid Build Coastguard Worker HandleBinaryOp(instruction);
2765*795d594fSAndroid Build Coastguard Worker }
2766*795d594fSAndroid Build Coastguard Worker
VisitAdd(HAdd * instruction)2767*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitAdd(HAdd* instruction) {
2768*795d594fSAndroid Build Coastguard Worker HandleBinaryOp(instruction);
2769*795d594fSAndroid Build Coastguard Worker }
2770*795d594fSAndroid Build Coastguard Worker
VisitAnd(HAnd * instruction)2771*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitAnd(HAnd* instruction) {
2772*795d594fSAndroid Build Coastguard Worker HandleBinaryOp(instruction);
2773*795d594fSAndroid Build Coastguard Worker }
2774*795d594fSAndroid Build Coastguard Worker
VisitAnd(HAnd * instruction)2775*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitAnd(HAnd* instruction) {
2776*795d594fSAndroid Build Coastguard Worker HandleBinaryOp(instruction);
2777*795d594fSAndroid Build Coastguard Worker }
2778*795d594fSAndroid Build Coastguard Worker
VisitArrayGet(HArrayGet * instruction)2779*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitArrayGet(HArrayGet* instruction) {
2780*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetType();
2781*795d594fSAndroid Build Coastguard Worker bool object_array_get_with_read_barrier =
2782*795d594fSAndroid Build Coastguard Worker (type == DataType::Type::kReference) && codegen_->EmitReadBarrier();
2783*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator())
2784*795d594fSAndroid Build Coastguard Worker LocationSummary(instruction,
2785*795d594fSAndroid Build Coastguard Worker object_array_get_with_read_barrier ? LocationSummary::kCallOnSlowPath :
2786*795d594fSAndroid Build Coastguard Worker LocationSummary::kNoCall);
2787*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
2788*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
2789*795d594fSAndroid Build Coastguard Worker if (DataType::IsFloatingPointType(type)) {
2790*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
2791*795d594fSAndroid Build Coastguard Worker } else {
2792*795d594fSAndroid Build Coastguard Worker // The output overlaps in the case of an object array get with
2793*795d594fSAndroid Build Coastguard Worker // read barriers enabled: we do not want the move to overwrite the
2794*795d594fSAndroid Build Coastguard Worker // array's location, as we need it to emit the read barrier.
2795*795d594fSAndroid Build Coastguard Worker locations->SetOut(
2796*795d594fSAndroid Build Coastguard Worker Location::RequiresRegister(),
2797*795d594fSAndroid Build Coastguard Worker object_array_get_with_read_barrier ? Location::kOutputOverlap : Location::kNoOutputOverlap);
2798*795d594fSAndroid Build Coastguard Worker }
2799*795d594fSAndroid Build Coastguard Worker if (object_array_get_with_read_barrier && kUseBakerReadBarrier) {
2800*795d594fSAndroid Build Coastguard Worker locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
2801*795d594fSAndroid Build Coastguard Worker // We need a temporary register for the read barrier marking slow
2802*795d594fSAndroid Build Coastguard Worker // path in CodeGeneratorRISCV64::GenerateArrayLoadWithBakerReadBarrier.
2803*795d594fSAndroid Build Coastguard Worker locations->AddTemp(Location::RequiresRegister());
2804*795d594fSAndroid Build Coastguard Worker }
2805*795d594fSAndroid Build Coastguard Worker }
2806*795d594fSAndroid Build Coastguard Worker
VisitArrayGet(HArrayGet * instruction)2807*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitArrayGet(HArrayGet* instruction) {
2808*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
2809*795d594fSAndroid Build Coastguard Worker Location obj_loc = locations->InAt(0);
2810*795d594fSAndroid Build Coastguard Worker XRegister obj = obj_loc.AsRegister<XRegister>();
2811*795d594fSAndroid Build Coastguard Worker Location out_loc = locations->Out();
2812*795d594fSAndroid Build Coastguard Worker Location index = locations->InAt(1);
2813*795d594fSAndroid Build Coastguard Worker uint32_t data_offset = CodeGenerator::GetArrayDataOffset(instruction);
2814*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetType();
2815*795d594fSAndroid Build Coastguard Worker const bool maybe_compressed_char_at =
2816*795d594fSAndroid Build Coastguard Worker mirror::kUseStringCompression && instruction->IsStringCharAt();
2817*795d594fSAndroid Build Coastguard Worker
2818*795d594fSAndroid Build Coastguard Worker Riscv64Label string_char_at_done;
2819*795d594fSAndroid Build Coastguard Worker if (maybe_compressed_char_at) {
2820*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(type, DataType::Type::kUint16);
2821*795d594fSAndroid Build Coastguard Worker uint32_t count_offset = mirror::String::CountOffset().Uint32Value();
2822*795d594fSAndroid Build Coastguard Worker Riscv64Label uncompressed_load;
2823*795d594fSAndroid Build Coastguard Worker {
2824*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
2825*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
2826*795d594fSAndroid Build Coastguard Worker __ Loadw(tmp, obj, count_offset);
2827*795d594fSAndroid Build Coastguard Worker codegen_->MaybeRecordImplicitNullCheck(instruction);
2828*795d594fSAndroid Build Coastguard Worker __ Andi(tmp, tmp, 0x1);
2829*795d594fSAndroid Build Coastguard Worker static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u,
2830*795d594fSAndroid Build Coastguard Worker "Expecting 0=compressed, 1=uncompressed");
2831*795d594fSAndroid Build Coastguard Worker __ Bnez(tmp, &uncompressed_load);
2832*795d594fSAndroid Build Coastguard Worker }
2833*795d594fSAndroid Build Coastguard Worker XRegister out = out_loc.AsRegister<XRegister>();
2834*795d594fSAndroid Build Coastguard Worker if (index.IsConstant()) {
2835*795d594fSAndroid Build Coastguard Worker int32_t const_index = index.GetConstant()->AsIntConstant()->GetValue();
2836*795d594fSAndroid Build Coastguard Worker __ Loadbu(out, obj, data_offset + const_index);
2837*795d594fSAndroid Build Coastguard Worker } else {
2838*795d594fSAndroid Build Coastguard Worker __ Add(out, obj, index.AsRegister<XRegister>());
2839*795d594fSAndroid Build Coastguard Worker __ Loadbu(out, out, data_offset);
2840*795d594fSAndroid Build Coastguard Worker }
2841*795d594fSAndroid Build Coastguard Worker __ J(&string_char_at_done);
2842*795d594fSAndroid Build Coastguard Worker __ Bind(&uncompressed_load);
2843*795d594fSAndroid Build Coastguard Worker }
2844*795d594fSAndroid Build Coastguard Worker
2845*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kReference && codegen_->EmitBakerReadBarrier()) {
2846*795d594fSAndroid Build Coastguard Worker static_assert(
2847*795d594fSAndroid Build Coastguard Worker sizeof(mirror::HeapReference<mirror::Object>) == sizeof(int32_t),
2848*795d594fSAndroid Build Coastguard Worker "art::mirror::HeapReference<art::mirror::Object> and int32_t have different sizes.");
2849*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Object> */ out =
2850*795d594fSAndroid Build Coastguard Worker // *(obj + data_offset + index * sizeof(HeapReference<Object>))
2851*795d594fSAndroid Build Coastguard Worker // Note that a potential implicit null check could be handled in these
2852*795d594fSAndroid Build Coastguard Worker // `CodeGeneratorRISCV64::Generate{Array,Field}LoadWithBakerReadBarrier()` calls
2853*795d594fSAndroid Build Coastguard Worker // but we currently do not support implicit null checks on `HArrayGet`.
2854*795d594fSAndroid Build Coastguard Worker DCHECK(!instruction->CanDoImplicitNullCheckOn(instruction->InputAt(0)));
2855*795d594fSAndroid Build Coastguard Worker Location temp = locations->GetTemp(0);
2856*795d594fSAndroid Build Coastguard Worker if (index.IsConstant()) {
2857*795d594fSAndroid Build Coastguard Worker // Array load with a constant index can be treated as a field load.
2858*795d594fSAndroid Build Coastguard Worker static constexpr size_t shift = DataType::SizeShift(DataType::Type::kReference);
2859*795d594fSAndroid Build Coastguard Worker size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << shift) + data_offset;
2860*795d594fSAndroid Build Coastguard Worker codegen_->GenerateFieldLoadWithBakerReadBarrier(instruction,
2861*795d594fSAndroid Build Coastguard Worker out_loc,
2862*795d594fSAndroid Build Coastguard Worker obj,
2863*795d594fSAndroid Build Coastguard Worker offset,
2864*795d594fSAndroid Build Coastguard Worker temp,
2865*795d594fSAndroid Build Coastguard Worker /* needs_null_check= */ false);
2866*795d594fSAndroid Build Coastguard Worker } else {
2867*795d594fSAndroid Build Coastguard Worker codegen_->GenerateArrayLoadWithBakerReadBarrier(instruction,
2868*795d594fSAndroid Build Coastguard Worker out_loc,
2869*795d594fSAndroid Build Coastguard Worker obj,
2870*795d594fSAndroid Build Coastguard Worker data_offset,
2871*795d594fSAndroid Build Coastguard Worker index,
2872*795d594fSAndroid Build Coastguard Worker temp,
2873*795d594fSAndroid Build Coastguard Worker /* needs_null_check= */ false);
2874*795d594fSAndroid Build Coastguard Worker }
2875*795d594fSAndroid Build Coastguard Worker } else if (index.IsConstant()) {
2876*795d594fSAndroid Build Coastguard Worker int32_t const_index = index.GetConstant()->AsIntConstant()->GetValue();
2877*795d594fSAndroid Build Coastguard Worker int32_t offset = data_offset + (const_index << DataType::SizeShift(type));
2878*795d594fSAndroid Build Coastguard Worker Load(out_loc, obj, offset, type);
2879*795d594fSAndroid Build Coastguard Worker if (!maybe_compressed_char_at) {
2880*795d594fSAndroid Build Coastguard Worker codegen_->MaybeRecordImplicitNullCheck(instruction);
2881*795d594fSAndroid Build Coastguard Worker }
2882*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kReference) {
2883*795d594fSAndroid Build Coastguard Worker DCHECK(!codegen_->EmitBakerReadBarrier());
2884*795d594fSAndroid Build Coastguard Worker // If read barriers are enabled, emit read barriers other than Baker's using
2885*795d594fSAndroid Build Coastguard Worker // a slow path (and also unpoison the loaded reference, if heap poisoning is enabled).
2886*795d594fSAndroid Build Coastguard Worker codegen_->MaybeGenerateReadBarrierSlow(instruction, out_loc, out_loc, obj_loc, offset);
2887*795d594fSAndroid Build Coastguard Worker }
2888*795d594fSAndroid Build Coastguard Worker } else {
2889*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
2890*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
2891*795d594fSAndroid Build Coastguard Worker ShNAdd(tmp, index.AsRegister<XRegister>(), obj, type);
2892*795d594fSAndroid Build Coastguard Worker Load(out_loc, tmp, data_offset, type);
2893*795d594fSAndroid Build Coastguard Worker if (!maybe_compressed_char_at) {
2894*795d594fSAndroid Build Coastguard Worker codegen_->MaybeRecordImplicitNullCheck(instruction);
2895*795d594fSAndroid Build Coastguard Worker }
2896*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kReference) {
2897*795d594fSAndroid Build Coastguard Worker DCHECK(!codegen_->EmitBakerReadBarrier());
2898*795d594fSAndroid Build Coastguard Worker // If read barriers are enabled, emit read barriers other than Baker's using
2899*795d594fSAndroid Build Coastguard Worker // a slow path (and also unpoison the loaded reference, if heap poisoning is enabled).
2900*795d594fSAndroid Build Coastguard Worker codegen_->MaybeGenerateReadBarrierSlow(
2901*795d594fSAndroid Build Coastguard Worker instruction, out_loc, out_loc, obj_loc, data_offset, index);
2902*795d594fSAndroid Build Coastguard Worker }
2903*795d594fSAndroid Build Coastguard Worker }
2904*795d594fSAndroid Build Coastguard Worker
2905*795d594fSAndroid Build Coastguard Worker if (maybe_compressed_char_at) {
2906*795d594fSAndroid Build Coastguard Worker __ Bind(&string_char_at_done);
2907*795d594fSAndroid Build Coastguard Worker }
2908*795d594fSAndroid Build Coastguard Worker }
2909*795d594fSAndroid Build Coastguard Worker
VisitArrayLength(HArrayLength * instruction)2910*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitArrayLength(HArrayLength* instruction) {
2911*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
2912*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
2913*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
2914*795d594fSAndroid Build Coastguard Worker }
2915*795d594fSAndroid Build Coastguard Worker
VisitArrayLength(HArrayLength * instruction)2916*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitArrayLength(HArrayLength* instruction) {
2917*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
2918*795d594fSAndroid Build Coastguard Worker uint32_t offset = CodeGenerator::GetArrayLengthOffset(instruction);
2919*795d594fSAndroid Build Coastguard Worker XRegister obj = locations->InAt(0).AsRegister<XRegister>();
2920*795d594fSAndroid Build Coastguard Worker XRegister out = locations->Out().AsRegister<XRegister>();
2921*795d594fSAndroid Build Coastguard Worker __ Loadwu(out, obj, offset); // Unsigned for string length; does not matter for other arrays.
2922*795d594fSAndroid Build Coastguard Worker codegen_->MaybeRecordImplicitNullCheck(instruction);
2923*795d594fSAndroid Build Coastguard Worker // Mask out compression flag from String's array length.
2924*795d594fSAndroid Build Coastguard Worker if (mirror::kUseStringCompression && instruction->IsStringLength()) {
2925*795d594fSAndroid Build Coastguard Worker __ Srli(out, out, 1u);
2926*795d594fSAndroid Build Coastguard Worker }
2927*795d594fSAndroid Build Coastguard Worker }
2928*795d594fSAndroid Build Coastguard Worker
VisitArraySet(HArraySet * instruction)2929*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitArraySet(HArraySet* instruction) {
2930*795d594fSAndroid Build Coastguard Worker bool needs_type_check = instruction->NeedsTypeCheck();
2931*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(
2932*795d594fSAndroid Build Coastguard Worker instruction,
2933*795d594fSAndroid Build Coastguard Worker needs_type_check ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall);
2934*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
2935*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
2936*795d594fSAndroid Build Coastguard Worker locations->SetInAt(2, ValueLocationForStore(instruction->GetValue()));
2937*795d594fSAndroid Build Coastguard Worker if (kPoisonHeapReferences &&
2938*795d594fSAndroid Build Coastguard Worker instruction->GetComponentType() == DataType::Type::kReference &&
2939*795d594fSAndroid Build Coastguard Worker !locations->InAt(1).IsConstant() &&
2940*795d594fSAndroid Build Coastguard Worker !locations->InAt(2).IsConstant()) {
2941*795d594fSAndroid Build Coastguard Worker locations->AddTemp(Location::RequiresRegister());
2942*795d594fSAndroid Build Coastguard Worker }
2943*795d594fSAndroid Build Coastguard Worker }
2944*795d594fSAndroid Build Coastguard Worker
VisitArraySet(HArraySet * instruction)2945*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitArraySet(HArraySet* instruction) {
2946*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
2947*795d594fSAndroid Build Coastguard Worker XRegister array = locations->InAt(0).AsRegister<XRegister>();
2948*795d594fSAndroid Build Coastguard Worker Location index = locations->InAt(1);
2949*795d594fSAndroid Build Coastguard Worker Location value = locations->InAt(2);
2950*795d594fSAndroid Build Coastguard Worker DataType::Type value_type = instruction->GetComponentType();
2951*795d594fSAndroid Build Coastguard Worker bool needs_type_check = instruction->NeedsTypeCheck();
2952*795d594fSAndroid Build Coastguard Worker const WriteBarrierKind write_barrier_kind = instruction->GetWriteBarrierKind();
2953*795d594fSAndroid Build Coastguard Worker bool needs_write_barrier =
2954*795d594fSAndroid Build Coastguard Worker codegen_->StoreNeedsWriteBarrier(value_type, instruction->GetValue(), write_barrier_kind);
2955*795d594fSAndroid Build Coastguard Worker size_t data_offset = mirror::Array::DataOffset(DataType::Size(value_type)).Uint32Value();
2956*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path = nullptr;
2957*795d594fSAndroid Build Coastguard Worker
2958*795d594fSAndroid Build Coastguard Worker if (needs_write_barrier) {
2959*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(value_type, DataType::Type::kReference);
2960*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(value.IsConstant(), value.GetConstant()->IsArithmeticZero());
2961*795d594fSAndroid Build Coastguard Worker const bool storing_constant_zero = value.IsConstant();
2962*795d594fSAndroid Build Coastguard Worker // The WriteBarrierKind::kEmitNotBeingReliedOn case is able to skip the write barrier when its
2963*795d594fSAndroid Build Coastguard Worker // value is null (without an extra CompareAndBranchIfZero since we already checked if the
2964*795d594fSAndroid Build Coastguard Worker // value is null for the type check).
2965*795d594fSAndroid Build Coastguard Worker bool skip_marking_gc_card = false;
2966*795d594fSAndroid Build Coastguard Worker Riscv64Label skip_writing_card;
2967*795d594fSAndroid Build Coastguard Worker if (!storing_constant_zero) {
2968*795d594fSAndroid Build Coastguard Worker Riscv64Label do_store;
2969*795d594fSAndroid Build Coastguard Worker
2970*795d594fSAndroid Build Coastguard Worker bool can_value_be_null = instruction->GetValueCanBeNull();
2971*795d594fSAndroid Build Coastguard Worker skip_marking_gc_card =
2972*795d594fSAndroid Build Coastguard Worker can_value_be_null && write_barrier_kind == WriteBarrierKind::kEmitNotBeingReliedOn;
2973*795d594fSAndroid Build Coastguard Worker if (can_value_be_null) {
2974*795d594fSAndroid Build Coastguard Worker if (skip_marking_gc_card) {
2975*795d594fSAndroid Build Coastguard Worker __ Beqz(value.AsRegister<XRegister>(), &skip_writing_card);
2976*795d594fSAndroid Build Coastguard Worker } else {
2977*795d594fSAndroid Build Coastguard Worker __ Beqz(value.AsRegister<XRegister>(), &do_store);
2978*795d594fSAndroid Build Coastguard Worker }
2979*795d594fSAndroid Build Coastguard Worker }
2980*795d594fSAndroid Build Coastguard Worker
2981*795d594fSAndroid Build Coastguard Worker if (needs_type_check) {
2982*795d594fSAndroid Build Coastguard Worker slow_path = new (codegen_->GetScopedAllocator()) ArraySetSlowPathRISCV64(instruction);
2983*795d594fSAndroid Build Coastguard Worker codegen_->AddSlowPath(slow_path);
2984*795d594fSAndroid Build Coastguard Worker
2985*795d594fSAndroid Build Coastguard Worker uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
2986*795d594fSAndroid Build Coastguard Worker uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value();
2987*795d594fSAndroid Build Coastguard Worker uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value();
2988*795d594fSAndroid Build Coastguard Worker
2989*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
2990*795d594fSAndroid Build Coastguard Worker XRegister temp1 = srs.AllocateXRegister();
2991*795d594fSAndroid Build Coastguard Worker XRegister temp2 = srs.AllocateXRegister();
2992*795d594fSAndroid Build Coastguard Worker
2993*795d594fSAndroid Build Coastguard Worker // Note that when read barriers are enabled, the type checks are performed
2994*795d594fSAndroid Build Coastguard Worker // without read barriers. This is fine, even in the case where a class object
2995*795d594fSAndroid Build Coastguard Worker // is in the from-space after the flip, as a comparison involving such a type
2996*795d594fSAndroid Build Coastguard Worker // would not produce a false positive; it may of course produce a false
2997*795d594fSAndroid Build Coastguard Worker // negative, in which case we would take the ArraySet slow path.
2998*795d594fSAndroid Build Coastguard Worker
2999*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp1 = array->klass_
3000*795d594fSAndroid Build Coastguard Worker __ Loadwu(temp1, array, class_offset);
3001*795d594fSAndroid Build Coastguard Worker codegen_->MaybeRecordImplicitNullCheck(instruction);
3002*795d594fSAndroid Build Coastguard Worker codegen_->MaybeUnpoisonHeapReference(temp1);
3003*795d594fSAndroid Build Coastguard Worker
3004*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp2 = temp1->component_type_
3005*795d594fSAndroid Build Coastguard Worker __ Loadwu(temp2, temp1, component_offset);
3006*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp1 = value->klass_
3007*795d594fSAndroid Build Coastguard Worker __ Loadwu(temp1, value.AsRegister<XRegister>(), class_offset);
3008*795d594fSAndroid Build Coastguard Worker // If heap poisoning is enabled, no need to unpoison `temp1`
3009*795d594fSAndroid Build Coastguard Worker // nor `temp2`, as we are comparing two poisoned references.
3010*795d594fSAndroid Build Coastguard Worker if (instruction->StaticTypeOfArrayIsObjectArray()) {
3011*795d594fSAndroid Build Coastguard Worker Riscv64Label do_put;
3012*795d594fSAndroid Build Coastguard Worker __ Beq(temp1, temp2, &do_put);
3013*795d594fSAndroid Build Coastguard Worker // If heap poisoning is enabled, the `temp2` reference has
3014*795d594fSAndroid Build Coastguard Worker // not been unpoisoned yet; unpoison it now.
3015*795d594fSAndroid Build Coastguard Worker codegen_->MaybeUnpoisonHeapReference(temp2);
3016*795d594fSAndroid Build Coastguard Worker
3017*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp1 = temp2->super_class_
3018*795d594fSAndroid Build Coastguard Worker __ Loadwu(temp1, temp2, super_offset);
3019*795d594fSAndroid Build Coastguard Worker // If heap poisoning is enabled, no need to unpoison
3020*795d594fSAndroid Build Coastguard Worker // `temp1`, as we are comparing against null below.
3021*795d594fSAndroid Build Coastguard Worker __ Bnez(temp1, slow_path->GetEntryLabel());
3022*795d594fSAndroid Build Coastguard Worker __ Bind(&do_put);
3023*795d594fSAndroid Build Coastguard Worker } else {
3024*795d594fSAndroid Build Coastguard Worker __ Bne(temp1, temp2, slow_path->GetEntryLabel());
3025*795d594fSAndroid Build Coastguard Worker }
3026*795d594fSAndroid Build Coastguard Worker }
3027*795d594fSAndroid Build Coastguard Worker
3028*795d594fSAndroid Build Coastguard Worker if (can_value_be_null && !skip_marking_gc_card) {
3029*795d594fSAndroid Build Coastguard Worker DCHECK(do_store.IsLinked());
3030*795d594fSAndroid Build Coastguard Worker __ Bind(&do_store);
3031*795d594fSAndroid Build Coastguard Worker }
3032*795d594fSAndroid Build Coastguard Worker }
3033*795d594fSAndroid Build Coastguard Worker
3034*795d594fSAndroid Build Coastguard Worker DCHECK_NE(write_barrier_kind, WriteBarrierKind::kDontEmit);
3035*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(storing_constant_zero,
3036*795d594fSAndroid Build Coastguard Worker write_barrier_kind == WriteBarrierKind::kEmitBeingReliedOn);
3037*795d594fSAndroid Build Coastguard Worker codegen_->MarkGCCard(array);
3038*795d594fSAndroid Build Coastguard Worker
3039*795d594fSAndroid Build Coastguard Worker if (skip_marking_gc_card) {
3040*795d594fSAndroid Build Coastguard Worker // Note that we don't check that the GC card is valid as it can be correctly clean.
3041*795d594fSAndroid Build Coastguard Worker DCHECK(skip_writing_card.IsLinked());
3042*795d594fSAndroid Build Coastguard Worker __ Bind(&skip_writing_card);
3043*795d594fSAndroid Build Coastguard Worker }
3044*795d594fSAndroid Build Coastguard Worker } else if (codegen_->ShouldCheckGCCard(value_type, instruction->GetValue(), write_barrier_kind)) {
3045*795d594fSAndroid Build Coastguard Worker codegen_->CheckGCCardIsValid(array);
3046*795d594fSAndroid Build Coastguard Worker }
3047*795d594fSAndroid Build Coastguard Worker
3048*795d594fSAndroid Build Coastguard Worker if (index.IsConstant()) {
3049*795d594fSAndroid Build Coastguard Worker int32_t const_index = index.GetConstant()->AsIntConstant()->GetValue();
3050*795d594fSAndroid Build Coastguard Worker int32_t offset = data_offset + (const_index << DataType::SizeShift(value_type));
3051*795d594fSAndroid Build Coastguard Worker Store(value, array, offset, value_type);
3052*795d594fSAndroid Build Coastguard Worker } else {
3053*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
3054*795d594fSAndroid Build Coastguard Worker // Heap poisoning needs two scratch registers in `Store()`, except for null constants.
3055*795d594fSAndroid Build Coastguard Worker XRegister tmp =
3056*795d594fSAndroid Build Coastguard Worker (kPoisonHeapReferences && value_type == DataType::Type::kReference && !value.IsConstant())
3057*795d594fSAndroid Build Coastguard Worker ? locations->GetTemp(0).AsRegister<XRegister>()
3058*795d594fSAndroid Build Coastguard Worker : srs.AllocateXRegister();
3059*795d594fSAndroid Build Coastguard Worker ShNAdd(tmp, index.AsRegister<XRegister>(), array, value_type);
3060*795d594fSAndroid Build Coastguard Worker Store(value, tmp, data_offset, value_type);
3061*795d594fSAndroid Build Coastguard Worker }
3062*795d594fSAndroid Build Coastguard Worker // There must be no instructions between the `Store()` and the `MaybeRecordImplicitNullCheck()`.
3063*795d594fSAndroid Build Coastguard Worker // We can avoid this if the type check makes the null check unconditionally.
3064*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(needs_type_check, needs_write_barrier);
3065*795d594fSAndroid Build Coastguard Worker if (!(needs_type_check && !instruction->GetValueCanBeNull())) {
3066*795d594fSAndroid Build Coastguard Worker codegen_->MaybeRecordImplicitNullCheck(instruction);
3067*795d594fSAndroid Build Coastguard Worker }
3068*795d594fSAndroid Build Coastguard Worker
3069*795d594fSAndroid Build Coastguard Worker if (slow_path != nullptr) {
3070*795d594fSAndroid Build Coastguard Worker __ Bind(slow_path->GetExitLabel());
3071*795d594fSAndroid Build Coastguard Worker }
3072*795d594fSAndroid Build Coastguard Worker }
3073*795d594fSAndroid Build Coastguard Worker
VisitBelow(HBelow * instruction)3074*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitBelow(HBelow* instruction) {
3075*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
3076*795d594fSAndroid Build Coastguard Worker }
3077*795d594fSAndroid Build Coastguard Worker
VisitBelow(HBelow * instruction)3078*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitBelow(HBelow* instruction) {
3079*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
3080*795d594fSAndroid Build Coastguard Worker }
3081*795d594fSAndroid Build Coastguard Worker
VisitBelowOrEqual(HBelowOrEqual * instruction)3082*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitBelowOrEqual(HBelowOrEqual* instruction) {
3083*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
3084*795d594fSAndroid Build Coastguard Worker }
3085*795d594fSAndroid Build Coastguard Worker
VisitBelowOrEqual(HBelowOrEqual * instruction)3086*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitBelowOrEqual(HBelowOrEqual* instruction) {
3087*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
3088*795d594fSAndroid Build Coastguard Worker }
3089*795d594fSAndroid Build Coastguard Worker
VisitBooleanNot(HBooleanNot * instruction)3090*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitBooleanNot(HBooleanNot* instruction) {
3091*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
3092*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
3093*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
3094*795d594fSAndroid Build Coastguard Worker }
3095*795d594fSAndroid Build Coastguard Worker
VisitBooleanNot(HBooleanNot * instruction)3096*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitBooleanNot(HBooleanNot* instruction) {
3097*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
3098*795d594fSAndroid Build Coastguard Worker __ Xori(locations->Out().AsRegister<XRegister>(), locations->InAt(0).AsRegister<XRegister>(), 1);
3099*795d594fSAndroid Build Coastguard Worker }
3100*795d594fSAndroid Build Coastguard Worker
VisitBoundsCheck(HBoundsCheck * instruction)3101*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitBoundsCheck(HBoundsCheck* instruction) {
3102*795d594fSAndroid Build Coastguard Worker RegisterSet caller_saves = RegisterSet::Empty();
3103*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
3104*795d594fSAndroid Build Coastguard Worker caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
3105*795d594fSAndroid Build Coastguard Worker caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
3106*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction, caller_saves);
3107*795d594fSAndroid Build Coastguard Worker
3108*795d594fSAndroid Build Coastguard Worker HInstruction* index = instruction->InputAt(0);
3109*795d594fSAndroid Build Coastguard Worker HInstruction* length = instruction->InputAt(1);
3110*795d594fSAndroid Build Coastguard Worker
3111*795d594fSAndroid Build Coastguard Worker bool const_index = false;
3112*795d594fSAndroid Build Coastguard Worker bool const_length = false;
3113*795d594fSAndroid Build Coastguard Worker
3114*795d594fSAndroid Build Coastguard Worker if (length->IsConstant()) {
3115*795d594fSAndroid Build Coastguard Worker if (index->IsConstant()) {
3116*795d594fSAndroid Build Coastguard Worker const_index = true;
3117*795d594fSAndroid Build Coastguard Worker const_length = true;
3118*795d594fSAndroid Build Coastguard Worker } else {
3119*795d594fSAndroid Build Coastguard Worker int32_t length_value = length->AsIntConstant()->GetValue();
3120*795d594fSAndroid Build Coastguard Worker if (length_value == 0 || length_value == 1) {
3121*795d594fSAndroid Build Coastguard Worker const_length = true;
3122*795d594fSAndroid Build Coastguard Worker }
3123*795d594fSAndroid Build Coastguard Worker }
3124*795d594fSAndroid Build Coastguard Worker } else if (index->IsConstant()) {
3125*795d594fSAndroid Build Coastguard Worker int32_t index_value = index->AsIntConstant()->GetValue();
3126*795d594fSAndroid Build Coastguard Worker if (index_value <= 0) {
3127*795d594fSAndroid Build Coastguard Worker const_index = true;
3128*795d594fSAndroid Build Coastguard Worker }
3129*795d594fSAndroid Build Coastguard Worker }
3130*795d594fSAndroid Build Coastguard Worker
3131*795d594fSAndroid Build Coastguard Worker locations->SetInAt(
3132*795d594fSAndroid Build Coastguard Worker 0,
3133*795d594fSAndroid Build Coastguard Worker const_index ? Location::ConstantLocation(index) : Location::RequiresRegister());
3134*795d594fSAndroid Build Coastguard Worker locations->SetInAt(
3135*795d594fSAndroid Build Coastguard Worker 1,
3136*795d594fSAndroid Build Coastguard Worker const_length ? Location::ConstantLocation(length) : Location::RequiresRegister());
3137*795d594fSAndroid Build Coastguard Worker }
3138*795d594fSAndroid Build Coastguard Worker
VisitBoundsCheck(HBoundsCheck * instruction)3139*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitBoundsCheck(HBoundsCheck* instruction) {
3140*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
3141*795d594fSAndroid Build Coastguard Worker Location index_loc = locations->InAt(0);
3142*795d594fSAndroid Build Coastguard Worker Location length_loc = locations->InAt(1);
3143*795d594fSAndroid Build Coastguard Worker
3144*795d594fSAndroid Build Coastguard Worker if (length_loc.IsConstant()) {
3145*795d594fSAndroid Build Coastguard Worker int32_t length = length_loc.GetConstant()->AsIntConstant()->GetValue();
3146*795d594fSAndroid Build Coastguard Worker if (index_loc.IsConstant()) {
3147*795d594fSAndroid Build Coastguard Worker int32_t index = index_loc.GetConstant()->AsIntConstant()->GetValue();
3148*795d594fSAndroid Build Coastguard Worker if (index < 0 || index >= length) {
3149*795d594fSAndroid Build Coastguard Worker BoundsCheckSlowPathRISCV64* slow_path =
3150*795d594fSAndroid Build Coastguard Worker new (codegen_->GetScopedAllocator()) BoundsCheckSlowPathRISCV64(instruction);
3151*795d594fSAndroid Build Coastguard Worker codegen_->AddSlowPath(slow_path);
3152*795d594fSAndroid Build Coastguard Worker __ J(slow_path->GetEntryLabel());
3153*795d594fSAndroid Build Coastguard Worker } else {
3154*795d594fSAndroid Build Coastguard Worker // Nothing to be done.
3155*795d594fSAndroid Build Coastguard Worker }
3156*795d594fSAndroid Build Coastguard Worker return;
3157*795d594fSAndroid Build Coastguard Worker }
3158*795d594fSAndroid Build Coastguard Worker
3159*795d594fSAndroid Build Coastguard Worker BoundsCheckSlowPathRISCV64* slow_path =
3160*795d594fSAndroid Build Coastguard Worker new (codegen_->GetScopedAllocator()) BoundsCheckSlowPathRISCV64(instruction);
3161*795d594fSAndroid Build Coastguard Worker codegen_->AddSlowPath(slow_path);
3162*795d594fSAndroid Build Coastguard Worker XRegister index = index_loc.AsRegister<XRegister>();
3163*795d594fSAndroid Build Coastguard Worker if (length == 0) {
3164*795d594fSAndroid Build Coastguard Worker __ J(slow_path->GetEntryLabel());
3165*795d594fSAndroid Build Coastguard Worker } else {
3166*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(length, 1);
3167*795d594fSAndroid Build Coastguard Worker __ Bnez(index, slow_path->GetEntryLabel());
3168*795d594fSAndroid Build Coastguard Worker }
3169*795d594fSAndroid Build Coastguard Worker } else {
3170*795d594fSAndroid Build Coastguard Worker XRegister length = length_loc.AsRegister<XRegister>();
3171*795d594fSAndroid Build Coastguard Worker BoundsCheckSlowPathRISCV64* slow_path =
3172*795d594fSAndroid Build Coastguard Worker new (codegen_->GetScopedAllocator()) BoundsCheckSlowPathRISCV64(instruction);
3173*795d594fSAndroid Build Coastguard Worker codegen_->AddSlowPath(slow_path);
3174*795d594fSAndroid Build Coastguard Worker if (index_loc.IsConstant()) {
3175*795d594fSAndroid Build Coastguard Worker int32_t index = index_loc.GetConstant()->AsIntConstant()->GetValue();
3176*795d594fSAndroid Build Coastguard Worker if (index < 0) {
3177*795d594fSAndroid Build Coastguard Worker __ J(slow_path->GetEntryLabel());
3178*795d594fSAndroid Build Coastguard Worker } else {
3179*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(index, 0);
3180*795d594fSAndroid Build Coastguard Worker __ Blez(length, slow_path->GetEntryLabel());
3181*795d594fSAndroid Build Coastguard Worker }
3182*795d594fSAndroid Build Coastguard Worker } else {
3183*795d594fSAndroid Build Coastguard Worker XRegister index = index_loc.AsRegister<XRegister>();
3184*795d594fSAndroid Build Coastguard Worker __ Bgeu(index, length, slow_path->GetEntryLabel());
3185*795d594fSAndroid Build Coastguard Worker }
3186*795d594fSAndroid Build Coastguard Worker }
3187*795d594fSAndroid Build Coastguard Worker }
3188*795d594fSAndroid Build Coastguard Worker
VisitBoundType(HBoundType * instruction)3189*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitBoundType([[maybe_unused]] HBoundType* instruction) {
3190*795d594fSAndroid Build Coastguard Worker // Nothing to do, this should be removed during prepare for register allocator.
3191*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unreachable";
3192*795d594fSAndroid Build Coastguard Worker }
3193*795d594fSAndroid Build Coastguard Worker
VisitBoundType(HBoundType * instruction)3194*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitBoundType([[maybe_unused]] HBoundType* instruction) {
3195*795d594fSAndroid Build Coastguard Worker // Nothing to do, this should be removed during prepare for register allocator.
3196*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unreachable";
3197*795d594fSAndroid Build Coastguard Worker }
3198*795d594fSAndroid Build Coastguard Worker
3199*795d594fSAndroid Build Coastguard Worker // Temp is used for read barrier.
NumberOfInstanceOfTemps(bool emit_read_barrier,TypeCheckKind type_check_kind)3200*795d594fSAndroid Build Coastguard Worker static size_t NumberOfInstanceOfTemps(bool emit_read_barrier, TypeCheckKind type_check_kind) {
3201*795d594fSAndroid Build Coastguard Worker if (emit_read_barrier &&
3202*795d594fSAndroid Build Coastguard Worker (kUseBakerReadBarrier ||
3203*795d594fSAndroid Build Coastguard Worker type_check_kind == TypeCheckKind::kAbstractClassCheck ||
3204*795d594fSAndroid Build Coastguard Worker type_check_kind == TypeCheckKind::kClassHierarchyCheck ||
3205*795d594fSAndroid Build Coastguard Worker type_check_kind == TypeCheckKind::kArrayObjectCheck)) {
3206*795d594fSAndroid Build Coastguard Worker return 1;
3207*795d594fSAndroid Build Coastguard Worker }
3208*795d594fSAndroid Build Coastguard Worker return 0;
3209*795d594fSAndroid Build Coastguard Worker }
3210*795d594fSAndroid Build Coastguard Worker
3211*795d594fSAndroid Build Coastguard Worker // Interface case has 3 temps, one for holding the number of interfaces, one for the current
3212*795d594fSAndroid Build Coastguard Worker // interface pointer, one for loading the current interface.
3213*795d594fSAndroid Build Coastguard Worker // The other checks have one temp for loading the object's class and maybe a temp for read barrier.
NumberOfCheckCastTemps(bool emit_read_barrier,TypeCheckKind type_check_kind)3214*795d594fSAndroid Build Coastguard Worker static size_t NumberOfCheckCastTemps(bool emit_read_barrier, TypeCheckKind type_check_kind) {
3215*795d594fSAndroid Build Coastguard Worker if (type_check_kind == TypeCheckKind::kInterfaceCheck) {
3216*795d594fSAndroid Build Coastguard Worker return 3;
3217*795d594fSAndroid Build Coastguard Worker }
3218*795d594fSAndroid Build Coastguard Worker return 1 + NumberOfInstanceOfTemps(emit_read_barrier, type_check_kind);
3219*795d594fSAndroid Build Coastguard Worker }
3220*795d594fSAndroid Build Coastguard Worker
VisitCheckCast(HCheckCast * instruction)3221*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitCheckCast(HCheckCast* instruction) {
3222*795d594fSAndroid Build Coastguard Worker TypeCheckKind type_check_kind = instruction->GetTypeCheckKind();
3223*795d594fSAndroid Build Coastguard Worker LocationSummary::CallKind call_kind = codegen_->GetCheckCastCallKind(instruction);
3224*795d594fSAndroid Build Coastguard Worker LocationSummary* locations =
3225*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, call_kind);
3226*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
3227*795d594fSAndroid Build Coastguard Worker if (type_check_kind == TypeCheckKind::kBitstringCheck) {
3228*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)));
3229*795d594fSAndroid Build Coastguard Worker locations->SetInAt(2, Location::ConstantLocation(instruction->InputAt(2)));
3230*795d594fSAndroid Build Coastguard Worker locations->SetInAt(3, Location::ConstantLocation(instruction->InputAt(3)));
3231*795d594fSAndroid Build Coastguard Worker } else {
3232*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RequiresRegister());
3233*795d594fSAndroid Build Coastguard Worker }
3234*795d594fSAndroid Build Coastguard Worker locations->AddRegisterTemps(NumberOfCheckCastTemps(codegen_->EmitReadBarrier(), type_check_kind));
3235*795d594fSAndroid Build Coastguard Worker }
3236*795d594fSAndroid Build Coastguard Worker
VisitCheckCast(HCheckCast * instruction)3237*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitCheckCast(HCheckCast* instruction) {
3238*795d594fSAndroid Build Coastguard Worker TypeCheckKind type_check_kind = instruction->GetTypeCheckKind();
3239*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
3240*795d594fSAndroid Build Coastguard Worker Location obj_loc = locations->InAt(0);
3241*795d594fSAndroid Build Coastguard Worker XRegister obj = obj_loc.AsRegister<XRegister>();
3242*795d594fSAndroid Build Coastguard Worker Location cls = (type_check_kind == TypeCheckKind::kBitstringCheck)
3243*795d594fSAndroid Build Coastguard Worker ? Location::NoLocation()
3244*795d594fSAndroid Build Coastguard Worker : locations->InAt(1);
3245*795d594fSAndroid Build Coastguard Worker Location temp_loc = locations->GetTemp(0);
3246*795d594fSAndroid Build Coastguard Worker XRegister temp = temp_loc.AsRegister<XRegister>();
3247*795d594fSAndroid Build Coastguard Worker const size_t num_temps = NumberOfCheckCastTemps(codegen_->EmitReadBarrier(), type_check_kind);
3248*795d594fSAndroid Build Coastguard Worker DCHECK_GE(num_temps, 1u);
3249*795d594fSAndroid Build Coastguard Worker DCHECK_LE(num_temps, 3u);
3250*795d594fSAndroid Build Coastguard Worker Location maybe_temp2_loc = (num_temps >= 2) ? locations->GetTemp(1) : Location::NoLocation();
3251*795d594fSAndroid Build Coastguard Worker Location maybe_temp3_loc = (num_temps >= 3) ? locations->GetTemp(2) : Location::NoLocation();
3252*795d594fSAndroid Build Coastguard Worker const uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
3253*795d594fSAndroid Build Coastguard Worker const uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value();
3254*795d594fSAndroid Build Coastguard Worker const uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value();
3255*795d594fSAndroid Build Coastguard Worker const uint32_t primitive_offset = mirror::Class::PrimitiveTypeOffset().Int32Value();
3256*795d594fSAndroid Build Coastguard Worker const uint32_t iftable_offset = mirror::Class::IfTableOffset().Uint32Value();
3257*795d594fSAndroid Build Coastguard Worker const uint32_t array_length_offset = mirror::Array::LengthOffset().Uint32Value();
3258*795d594fSAndroid Build Coastguard Worker const uint32_t object_array_data_offset =
3259*795d594fSAndroid Build Coastguard Worker mirror::Array::DataOffset(kHeapReferenceSize).Uint32Value();
3260*795d594fSAndroid Build Coastguard Worker Riscv64Label done;
3261*795d594fSAndroid Build Coastguard Worker
3262*795d594fSAndroid Build Coastguard Worker bool is_type_check_slow_path_fatal = codegen_->IsTypeCheckSlowPathFatal(instruction);
3263*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path =
3264*795d594fSAndroid Build Coastguard Worker new (codegen_->GetScopedAllocator()) TypeCheckSlowPathRISCV64(
3265*795d594fSAndroid Build Coastguard Worker instruction, is_type_check_slow_path_fatal);
3266*795d594fSAndroid Build Coastguard Worker codegen_->AddSlowPath(slow_path);
3267*795d594fSAndroid Build Coastguard Worker
3268*795d594fSAndroid Build Coastguard Worker // Avoid this check if we know `obj` is not null.
3269*795d594fSAndroid Build Coastguard Worker if (instruction->MustDoNullCheck()) {
3270*795d594fSAndroid Build Coastguard Worker __ Beqz(obj, &done);
3271*795d594fSAndroid Build Coastguard Worker }
3272*795d594fSAndroid Build Coastguard Worker
3273*795d594fSAndroid Build Coastguard Worker switch (type_check_kind) {
3274*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kExactCheck:
3275*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kArrayCheck: {
3276*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp = obj->klass_
3277*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadTwoRegisters(instruction,
3278*795d594fSAndroid Build Coastguard Worker temp_loc,
3279*795d594fSAndroid Build Coastguard Worker obj_loc,
3280*795d594fSAndroid Build Coastguard Worker class_offset,
3281*795d594fSAndroid Build Coastguard Worker maybe_temp2_loc,
3282*795d594fSAndroid Build Coastguard Worker kWithoutReadBarrier);
3283*795d594fSAndroid Build Coastguard Worker // Jump to slow path for throwing the exception or doing a
3284*795d594fSAndroid Build Coastguard Worker // more involved array check.
3285*795d594fSAndroid Build Coastguard Worker __ Bne(temp, cls.AsRegister<XRegister>(), slow_path->GetEntryLabel());
3286*795d594fSAndroid Build Coastguard Worker break;
3287*795d594fSAndroid Build Coastguard Worker }
3288*795d594fSAndroid Build Coastguard Worker
3289*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kAbstractClassCheck: {
3290*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp = obj->klass_
3291*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadTwoRegisters(instruction,
3292*795d594fSAndroid Build Coastguard Worker temp_loc,
3293*795d594fSAndroid Build Coastguard Worker obj_loc,
3294*795d594fSAndroid Build Coastguard Worker class_offset,
3295*795d594fSAndroid Build Coastguard Worker maybe_temp2_loc,
3296*795d594fSAndroid Build Coastguard Worker kWithoutReadBarrier);
3297*795d594fSAndroid Build Coastguard Worker // If the class is abstract, we eagerly fetch the super class of the
3298*795d594fSAndroid Build Coastguard Worker // object to avoid doing a comparison we know will fail.
3299*795d594fSAndroid Build Coastguard Worker Riscv64Label loop;
3300*795d594fSAndroid Build Coastguard Worker __ Bind(&loop);
3301*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp = temp->super_class_
3302*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadOneRegister(instruction,
3303*795d594fSAndroid Build Coastguard Worker temp_loc,
3304*795d594fSAndroid Build Coastguard Worker super_offset,
3305*795d594fSAndroid Build Coastguard Worker maybe_temp2_loc,
3306*795d594fSAndroid Build Coastguard Worker kWithoutReadBarrier);
3307*795d594fSAndroid Build Coastguard Worker // If the class reference currently in `temp` is null, jump to the slow path to throw the
3308*795d594fSAndroid Build Coastguard Worker // exception.
3309*795d594fSAndroid Build Coastguard Worker __ Beqz(temp, slow_path->GetEntryLabel());
3310*795d594fSAndroid Build Coastguard Worker // Otherwise, compare the classes.
3311*795d594fSAndroid Build Coastguard Worker __ Bne(temp, cls.AsRegister<XRegister>(), &loop);
3312*795d594fSAndroid Build Coastguard Worker break;
3313*795d594fSAndroid Build Coastguard Worker }
3314*795d594fSAndroid Build Coastguard Worker
3315*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kClassHierarchyCheck: {
3316*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp = obj->klass_
3317*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadTwoRegisters(instruction,
3318*795d594fSAndroid Build Coastguard Worker temp_loc,
3319*795d594fSAndroid Build Coastguard Worker obj_loc,
3320*795d594fSAndroid Build Coastguard Worker class_offset,
3321*795d594fSAndroid Build Coastguard Worker maybe_temp2_loc,
3322*795d594fSAndroid Build Coastguard Worker kWithoutReadBarrier);
3323*795d594fSAndroid Build Coastguard Worker // Walk over the class hierarchy to find a match.
3324*795d594fSAndroid Build Coastguard Worker Riscv64Label loop;
3325*795d594fSAndroid Build Coastguard Worker __ Bind(&loop);
3326*795d594fSAndroid Build Coastguard Worker __ Beq(temp, cls.AsRegister<XRegister>(), &done);
3327*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp = temp->super_class_
3328*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadOneRegister(instruction,
3329*795d594fSAndroid Build Coastguard Worker temp_loc,
3330*795d594fSAndroid Build Coastguard Worker super_offset,
3331*795d594fSAndroid Build Coastguard Worker maybe_temp2_loc,
3332*795d594fSAndroid Build Coastguard Worker kWithoutReadBarrier);
3333*795d594fSAndroid Build Coastguard Worker // If the class reference currently in `temp` is null, jump to the slow path to throw the
3334*795d594fSAndroid Build Coastguard Worker // exception. Otherwise, jump to the beginning of the loop.
3335*795d594fSAndroid Build Coastguard Worker __ Bnez(temp, &loop);
3336*795d594fSAndroid Build Coastguard Worker __ J(slow_path->GetEntryLabel());
3337*795d594fSAndroid Build Coastguard Worker break;
3338*795d594fSAndroid Build Coastguard Worker }
3339*795d594fSAndroid Build Coastguard Worker
3340*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kArrayObjectCheck: {
3341*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp = obj->klass_
3342*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadTwoRegisters(instruction,
3343*795d594fSAndroid Build Coastguard Worker temp_loc,
3344*795d594fSAndroid Build Coastguard Worker obj_loc,
3345*795d594fSAndroid Build Coastguard Worker class_offset,
3346*795d594fSAndroid Build Coastguard Worker maybe_temp2_loc,
3347*795d594fSAndroid Build Coastguard Worker kWithoutReadBarrier);
3348*795d594fSAndroid Build Coastguard Worker // Do an exact check.
3349*795d594fSAndroid Build Coastguard Worker __ Beq(temp, cls.AsRegister<XRegister>(), &done);
3350*795d594fSAndroid Build Coastguard Worker // Otherwise, we need to check that the object's class is a non-primitive array.
3351*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp = temp->component_type_
3352*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadOneRegister(instruction,
3353*795d594fSAndroid Build Coastguard Worker temp_loc,
3354*795d594fSAndroid Build Coastguard Worker component_offset,
3355*795d594fSAndroid Build Coastguard Worker maybe_temp2_loc,
3356*795d594fSAndroid Build Coastguard Worker kWithoutReadBarrier);
3357*795d594fSAndroid Build Coastguard Worker // If the component type is null, jump to the slow path to throw the exception.
3358*795d594fSAndroid Build Coastguard Worker __ Beqz(temp, slow_path->GetEntryLabel());
3359*795d594fSAndroid Build Coastguard Worker // Otherwise, the object is indeed an array, further check that this component
3360*795d594fSAndroid Build Coastguard Worker // type is not a primitive type.
3361*795d594fSAndroid Build Coastguard Worker __ Loadhu(temp, temp, primitive_offset);
3362*795d594fSAndroid Build Coastguard Worker static_assert(Primitive::kPrimNot == 0, "Expected 0 for kPrimNot");
3363*795d594fSAndroid Build Coastguard Worker __ Bnez(temp, slow_path->GetEntryLabel());
3364*795d594fSAndroid Build Coastguard Worker break;
3365*795d594fSAndroid Build Coastguard Worker }
3366*795d594fSAndroid Build Coastguard Worker
3367*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kUnresolvedCheck:
3368*795d594fSAndroid Build Coastguard Worker // We always go into the type check slow path for the unresolved check case.
3369*795d594fSAndroid Build Coastguard Worker // We cannot directly call the CheckCast runtime entry point
3370*795d594fSAndroid Build Coastguard Worker // without resorting to a type checking slow path here (i.e. by
3371*795d594fSAndroid Build Coastguard Worker // calling InvokeRuntime directly), as it would require to
3372*795d594fSAndroid Build Coastguard Worker // assign fixed registers for the inputs of this HInstanceOf
3373*795d594fSAndroid Build Coastguard Worker // instruction (following the runtime calling convention), which
3374*795d594fSAndroid Build Coastguard Worker // might be cluttered by the potential first read barrier
3375*795d594fSAndroid Build Coastguard Worker // emission at the beginning of this method.
3376*795d594fSAndroid Build Coastguard Worker __ J(slow_path->GetEntryLabel());
3377*795d594fSAndroid Build Coastguard Worker break;
3378*795d594fSAndroid Build Coastguard Worker
3379*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kInterfaceCheck: {
3380*795d594fSAndroid Build Coastguard Worker // Avoid read barriers to improve performance of the fast path. We can not get false
3381*795d594fSAndroid Build Coastguard Worker // positives by doing this. False negatives are handled by the slow path.
3382*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp = obj->klass_
3383*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadTwoRegisters(instruction,
3384*795d594fSAndroid Build Coastguard Worker temp_loc,
3385*795d594fSAndroid Build Coastguard Worker obj_loc,
3386*795d594fSAndroid Build Coastguard Worker class_offset,
3387*795d594fSAndroid Build Coastguard Worker maybe_temp2_loc,
3388*795d594fSAndroid Build Coastguard Worker kWithoutReadBarrier);
3389*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp = temp->iftable_
3390*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadOneRegister(instruction,
3391*795d594fSAndroid Build Coastguard Worker temp_loc,
3392*795d594fSAndroid Build Coastguard Worker iftable_offset,
3393*795d594fSAndroid Build Coastguard Worker maybe_temp2_loc,
3394*795d594fSAndroid Build Coastguard Worker kWithoutReadBarrier);
3395*795d594fSAndroid Build Coastguard Worker XRegister temp2 = maybe_temp2_loc.AsRegister<XRegister>();
3396*795d594fSAndroid Build Coastguard Worker XRegister temp3 = maybe_temp3_loc.AsRegister<XRegister>();
3397*795d594fSAndroid Build Coastguard Worker // Load the size of the `IfTable`. The `Class::iftable_` is never null.
3398*795d594fSAndroid Build Coastguard Worker __ Loadw(temp2, temp, array_length_offset);
3399*795d594fSAndroid Build Coastguard Worker // Loop through the iftable and check if any class matches.
3400*795d594fSAndroid Build Coastguard Worker Riscv64Label loop;
3401*795d594fSAndroid Build Coastguard Worker __ Bind(&loop);
3402*795d594fSAndroid Build Coastguard Worker __ Beqz(temp2, slow_path->GetEntryLabel());
3403*795d594fSAndroid Build Coastguard Worker __ Lwu(temp3, temp, object_array_data_offset);
3404*795d594fSAndroid Build Coastguard Worker codegen_->MaybeUnpoisonHeapReference(temp3);
3405*795d594fSAndroid Build Coastguard Worker // Go to next interface.
3406*795d594fSAndroid Build Coastguard Worker __ Addi(temp, temp, 2 * kHeapReferenceSize);
3407*795d594fSAndroid Build Coastguard Worker __ Addi(temp2, temp2, -2);
3408*795d594fSAndroid Build Coastguard Worker // Compare the classes and continue the loop if they do not match.
3409*795d594fSAndroid Build Coastguard Worker __ Bne(temp3, cls.AsRegister<XRegister>(), &loop);
3410*795d594fSAndroid Build Coastguard Worker break;
3411*795d594fSAndroid Build Coastguard Worker }
3412*795d594fSAndroid Build Coastguard Worker
3413*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kBitstringCheck: {
3414*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp = obj->klass_
3415*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadTwoRegisters(instruction,
3416*795d594fSAndroid Build Coastguard Worker temp_loc,
3417*795d594fSAndroid Build Coastguard Worker obj_loc,
3418*795d594fSAndroid Build Coastguard Worker class_offset,
3419*795d594fSAndroid Build Coastguard Worker maybe_temp2_loc,
3420*795d594fSAndroid Build Coastguard Worker kWithoutReadBarrier);
3421*795d594fSAndroid Build Coastguard Worker
3422*795d594fSAndroid Build Coastguard Worker GenerateBitstringTypeCheckCompare(instruction, temp);
3423*795d594fSAndroid Build Coastguard Worker __ Bnez(temp, slow_path->GetEntryLabel());
3424*795d594fSAndroid Build Coastguard Worker break;
3425*795d594fSAndroid Build Coastguard Worker }
3426*795d594fSAndroid Build Coastguard Worker }
3427*795d594fSAndroid Build Coastguard Worker
3428*795d594fSAndroid Build Coastguard Worker __ Bind(&done);
3429*795d594fSAndroid Build Coastguard Worker __ Bind(slow_path->GetExitLabel());
3430*795d594fSAndroid Build Coastguard Worker }
3431*795d594fSAndroid Build Coastguard Worker
VisitClassTableGet(HClassTableGet * instruction)3432*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitClassTableGet(HClassTableGet* instruction) {
3433*795d594fSAndroid Build Coastguard Worker LocationSummary* locations =
3434*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, LocationSummary::kNoCall);
3435*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
3436*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
3437*795d594fSAndroid Build Coastguard Worker }
3438*795d594fSAndroid Build Coastguard Worker
VisitClassTableGet(HClassTableGet * instruction)3439*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitClassTableGet(HClassTableGet* instruction) {
3440*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
3441*795d594fSAndroid Build Coastguard Worker XRegister in = locations->InAt(0).AsRegister<XRegister>();
3442*795d594fSAndroid Build Coastguard Worker XRegister out = locations->Out().AsRegister<XRegister>();
3443*795d594fSAndroid Build Coastguard Worker if (instruction->GetTableKind() == HClassTableGet::TableKind::kVTable) {
3444*795d594fSAndroid Build Coastguard Worker MemberOffset method_offset =
3445*795d594fSAndroid Build Coastguard Worker mirror::Class::EmbeddedVTableEntryOffset(instruction->GetIndex(), kRiscv64PointerSize);
3446*795d594fSAndroid Build Coastguard Worker __ Loadd(out, in, method_offset.SizeValue());
3447*795d594fSAndroid Build Coastguard Worker } else {
3448*795d594fSAndroid Build Coastguard Worker uint32_t method_offset = dchecked_integral_cast<uint32_t>(
3449*795d594fSAndroid Build Coastguard Worker ImTable::OffsetOfElement(instruction->GetIndex(), kRiscv64PointerSize));
3450*795d594fSAndroid Build Coastguard Worker __ Loadd(out, in, mirror::Class::ImtPtrOffset(kRiscv64PointerSize).Uint32Value());
3451*795d594fSAndroid Build Coastguard Worker __ Loadd(out, out, method_offset);
3452*795d594fSAndroid Build Coastguard Worker }
3453*795d594fSAndroid Build Coastguard Worker }
3454*795d594fSAndroid Build Coastguard Worker
GetExceptionTlsOffset()3455*795d594fSAndroid Build Coastguard Worker static int32_t GetExceptionTlsOffset() {
3456*795d594fSAndroid Build Coastguard Worker return Thread::ExceptionOffset<kRiscv64PointerSize>().Int32Value();
3457*795d594fSAndroid Build Coastguard Worker }
3458*795d594fSAndroid Build Coastguard Worker
VisitClearException(HClearException * instruction)3459*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitClearException(HClearException* instruction) {
3460*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, LocationSummary::kNoCall);
3461*795d594fSAndroid Build Coastguard Worker }
3462*795d594fSAndroid Build Coastguard Worker
VisitClearException(HClearException * instruction)3463*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitClearException(
3464*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] HClearException* instruction) {
3465*795d594fSAndroid Build Coastguard Worker __ Stored(Zero, TR, GetExceptionTlsOffset());
3466*795d594fSAndroid Build Coastguard Worker }
3467*795d594fSAndroid Build Coastguard Worker
VisitClinitCheck(HClinitCheck * instruction)3468*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitClinitCheck(HClinitCheck* instruction) {
3469*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(
3470*795d594fSAndroid Build Coastguard Worker instruction, LocationSummary::kCallOnSlowPath);
3471*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
3472*795d594fSAndroid Build Coastguard Worker if (instruction->HasUses()) {
3473*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::SameAsFirstInput());
3474*795d594fSAndroid Build Coastguard Worker }
3475*795d594fSAndroid Build Coastguard Worker // Rely on the type initialization to save everything we need.
3476*795d594fSAndroid Build Coastguard Worker locations->SetCustomSlowPathCallerSaves(OneRegInReferenceOutSaveEverythingCallerSaves());
3477*795d594fSAndroid Build Coastguard Worker }
3478*795d594fSAndroid Build Coastguard Worker
VisitClinitCheck(HClinitCheck * instruction)3479*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitClinitCheck(HClinitCheck* instruction) {
3480*795d594fSAndroid Build Coastguard Worker // We assume the class is not null.
3481*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path = new (codegen_->GetScopedAllocator()) LoadClassSlowPathRISCV64(
3482*795d594fSAndroid Build Coastguard Worker instruction->GetLoadClass(), instruction);
3483*795d594fSAndroid Build Coastguard Worker codegen_->AddSlowPath(slow_path);
3484*795d594fSAndroid Build Coastguard Worker GenerateClassInitializationCheck(slow_path,
3485*795d594fSAndroid Build Coastguard Worker instruction->GetLocations()->InAt(0).AsRegister<XRegister>());
3486*795d594fSAndroid Build Coastguard Worker }
3487*795d594fSAndroid Build Coastguard Worker
VisitCompare(HCompare * instruction)3488*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitCompare(HCompare* instruction) {
3489*795d594fSAndroid Build Coastguard Worker DataType::Type compare_type = instruction->GetComparisonType();
3490*795d594fSAndroid Build Coastguard Worker
3491*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
3492*795d594fSAndroid Build Coastguard Worker
3493*795d594fSAndroid Build Coastguard Worker switch (compare_type) {
3494*795d594fSAndroid Build Coastguard Worker case DataType::Type::kBool:
3495*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint8:
3496*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt8:
3497*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint16:
3498*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt16:
3499*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
3500*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint32:
3501*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
3502*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint64:
3503*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
3504*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, RegisterOrZeroBitPatternLocation(instruction->InputAt(1)));
3505*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
3506*795d594fSAndroid Build Coastguard Worker break;
3507*795d594fSAndroid Build Coastguard Worker
3508*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
3509*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
3510*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresFpuRegister());
3511*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RequiresFpuRegister());
3512*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
3513*795d594fSAndroid Build Coastguard Worker break;
3514*795d594fSAndroid Build Coastguard Worker
3515*795d594fSAndroid Build Coastguard Worker default:
3516*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected type for compare operation " << compare_type;
3517*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
3518*795d594fSAndroid Build Coastguard Worker }
3519*795d594fSAndroid Build Coastguard Worker }
3520*795d594fSAndroid Build Coastguard Worker
VisitCompare(HCompare * instruction)3521*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitCompare(HCompare* instruction) {
3522*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
3523*795d594fSAndroid Build Coastguard Worker XRegister result = locations->Out().AsRegister<XRegister>();
3524*795d594fSAndroid Build Coastguard Worker DataType::Type in_type = instruction->InputAt(0)->GetType();
3525*795d594fSAndroid Build Coastguard Worker DataType::Type compare_type = instruction->GetComparisonType();
3526*795d594fSAndroid Build Coastguard Worker
3527*795d594fSAndroid Build Coastguard Worker // 0 if: left == right
3528*795d594fSAndroid Build Coastguard Worker // 1 if: left > right
3529*795d594fSAndroid Build Coastguard Worker // -1 if: left < right
3530*795d594fSAndroid Build Coastguard Worker switch (compare_type) {
3531*795d594fSAndroid Build Coastguard Worker case DataType::Type::kBool:
3532*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint8:
3533*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt8:
3534*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint16:
3535*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt16:
3536*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
3537*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64: {
3538*795d594fSAndroid Build Coastguard Worker XRegister left = locations->InAt(0).AsRegister<XRegister>();
3539*795d594fSAndroid Build Coastguard Worker XRegister right = InputXRegisterOrZero(locations->InAt(1));
3540*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
3541*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
3542*795d594fSAndroid Build Coastguard Worker __ Slt(tmp, left, right);
3543*795d594fSAndroid Build Coastguard Worker __ Slt(result, right, left);
3544*795d594fSAndroid Build Coastguard Worker __ Sub(result, result, tmp);
3545*795d594fSAndroid Build Coastguard Worker break;
3546*795d594fSAndroid Build Coastguard Worker }
3547*795d594fSAndroid Build Coastguard Worker
3548*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint32:
3549*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint64: {
3550*795d594fSAndroid Build Coastguard Worker XRegister left = locations->InAt(0).AsRegister<XRegister>();
3551*795d594fSAndroid Build Coastguard Worker XRegister right = InputXRegisterOrZero(locations->InAt(1));
3552*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
3553*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
3554*795d594fSAndroid Build Coastguard Worker __ Sltu(tmp, left, right);
3555*795d594fSAndroid Build Coastguard Worker __ Sltu(result, right, left);
3556*795d594fSAndroid Build Coastguard Worker __ Sub(result, result, tmp);
3557*795d594fSAndroid Build Coastguard Worker break;
3558*795d594fSAndroid Build Coastguard Worker }
3559*795d594fSAndroid Build Coastguard Worker
3560*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
3561*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64: {
3562*795d594fSAndroid Build Coastguard Worker FRegister left = locations->InAt(0).AsFpuRegister<FRegister>();
3563*795d594fSAndroid Build Coastguard Worker FRegister right = locations->InAt(1).AsFpuRegister<FRegister>();
3564*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
3565*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
3566*795d594fSAndroid Build Coastguard Worker if (instruction->IsGtBias()) {
3567*795d594fSAndroid Build Coastguard Worker // ((FLE l,r) ^ 1) - (FLT l,r); see `GenerateFpCondition()`.
3568*795d594fSAndroid Build Coastguard Worker FLe(tmp, left, right, in_type);
3569*795d594fSAndroid Build Coastguard Worker FLt(result, left, right, in_type);
3570*795d594fSAndroid Build Coastguard Worker __ Xori(tmp, tmp, 1);
3571*795d594fSAndroid Build Coastguard Worker __ Sub(result, tmp, result);
3572*795d594fSAndroid Build Coastguard Worker } else {
3573*795d594fSAndroid Build Coastguard Worker // ((FLE r,l) - 1) + (FLT r,l); see `GenerateFpCondition()`.
3574*795d594fSAndroid Build Coastguard Worker FLe(tmp, right, left, in_type);
3575*795d594fSAndroid Build Coastguard Worker FLt(result, right, left, in_type);
3576*795d594fSAndroid Build Coastguard Worker __ Addi(tmp, tmp, -1);
3577*795d594fSAndroid Build Coastguard Worker __ Add(result, result, tmp);
3578*795d594fSAndroid Build Coastguard Worker }
3579*795d594fSAndroid Build Coastguard Worker break;
3580*795d594fSAndroid Build Coastguard Worker }
3581*795d594fSAndroid Build Coastguard Worker
3582*795d594fSAndroid Build Coastguard Worker default:
3583*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented compare type " << in_type;
3584*795d594fSAndroid Build Coastguard Worker }
3585*795d594fSAndroid Build Coastguard Worker }
3586*795d594fSAndroid Build Coastguard Worker
VisitConstructorFence(HConstructorFence * instruction)3587*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitConstructorFence(HConstructorFence* instruction) {
3588*795d594fSAndroid Build Coastguard Worker instruction->SetLocations(nullptr);
3589*795d594fSAndroid Build Coastguard Worker }
3590*795d594fSAndroid Build Coastguard Worker
VisitConstructorFence(HConstructorFence * instruction)3591*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitConstructorFence(
3592*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] HConstructorFence* instruction) {
3593*795d594fSAndroid Build Coastguard Worker codegen_->GenerateMemoryBarrier(MemBarrierKind::kStoreStore);
3594*795d594fSAndroid Build Coastguard Worker }
3595*795d594fSAndroid Build Coastguard Worker
VisitCurrentMethod(HCurrentMethod * instruction)3596*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitCurrentMethod(HCurrentMethod* instruction) {
3597*795d594fSAndroid Build Coastguard Worker LocationSummary* locations =
3598*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, LocationSummary::kNoCall);
3599*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RegisterLocation(kArtMethodRegister));
3600*795d594fSAndroid Build Coastguard Worker }
3601*795d594fSAndroid Build Coastguard Worker
VisitCurrentMethod(HCurrentMethod * instruction)3602*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitCurrentMethod(
3603*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] HCurrentMethod* instruction) {
3604*795d594fSAndroid Build Coastguard Worker // Nothing to do, the method is already at its location.
3605*795d594fSAndroid Build Coastguard Worker }
3606*795d594fSAndroid Build Coastguard Worker
VisitShouldDeoptimizeFlag(HShouldDeoptimizeFlag * instruction)3607*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitShouldDeoptimizeFlag(HShouldDeoptimizeFlag* instruction) {
3608*795d594fSAndroid Build Coastguard Worker LocationSummary* locations =
3609*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, LocationSummary::kNoCall);
3610*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister());
3611*795d594fSAndroid Build Coastguard Worker }
3612*795d594fSAndroid Build Coastguard Worker
VisitShouldDeoptimizeFlag(HShouldDeoptimizeFlag * instruction)3613*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitShouldDeoptimizeFlag(
3614*795d594fSAndroid Build Coastguard Worker HShouldDeoptimizeFlag* instruction) {
3615*795d594fSAndroid Build Coastguard Worker __ Loadw(instruction->GetLocations()->Out().AsRegister<XRegister>(),
3616*795d594fSAndroid Build Coastguard Worker SP,
3617*795d594fSAndroid Build Coastguard Worker codegen_->GetStackOffsetOfShouldDeoptimizeFlag());
3618*795d594fSAndroid Build Coastguard Worker }
3619*795d594fSAndroid Build Coastguard Worker
VisitDeoptimize(HDeoptimize * instruction)3620*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitDeoptimize(HDeoptimize* instruction) {
3621*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator())
3622*795d594fSAndroid Build Coastguard Worker LocationSummary(instruction, LocationSummary::kCallOnSlowPath);
3623*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
3624*795d594fSAndroid Build Coastguard Worker RegisterSet caller_saves = RegisterSet::Empty();
3625*795d594fSAndroid Build Coastguard Worker caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
3626*795d594fSAndroid Build Coastguard Worker locations->SetCustomSlowPathCallerSaves(caller_saves);
3627*795d594fSAndroid Build Coastguard Worker if (IsBooleanValueOrMaterializedCondition(instruction->InputAt(0))) {
3628*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
3629*795d594fSAndroid Build Coastguard Worker }
3630*795d594fSAndroid Build Coastguard Worker }
3631*795d594fSAndroid Build Coastguard Worker
VisitDeoptimize(HDeoptimize * instruction)3632*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitDeoptimize(HDeoptimize* instruction) {
3633*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path =
3634*795d594fSAndroid Build Coastguard Worker deopt_slow_paths_.NewSlowPath<DeoptimizationSlowPathRISCV64>(instruction);
3635*795d594fSAndroid Build Coastguard Worker GenerateTestAndBranch(instruction,
3636*795d594fSAndroid Build Coastguard Worker /* condition_input_index= */ 0,
3637*795d594fSAndroid Build Coastguard Worker slow_path->GetEntryLabel(),
3638*795d594fSAndroid Build Coastguard Worker /* false_target= */ nullptr);
3639*795d594fSAndroid Build Coastguard Worker }
3640*795d594fSAndroid Build Coastguard Worker
VisitDiv(HDiv * instruction)3641*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitDiv(HDiv* instruction) {
3642*795d594fSAndroid Build Coastguard Worker LocationSummary* locations =
3643*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, LocationSummary::kNoCall);
3644*795d594fSAndroid Build Coastguard Worker switch (instruction->GetResultType()) {
3645*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
3646*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
3647*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
3648*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
3649*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
3650*795d594fSAndroid Build Coastguard Worker break;
3651*795d594fSAndroid Build Coastguard Worker
3652*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
3653*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
3654*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresFpuRegister());
3655*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RequiresFpuRegister());
3656*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
3657*795d594fSAndroid Build Coastguard Worker break;
3658*795d594fSAndroid Build Coastguard Worker
3659*795d594fSAndroid Build Coastguard Worker default:
3660*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected div type " << instruction->GetResultType();
3661*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
3662*795d594fSAndroid Build Coastguard Worker }
3663*795d594fSAndroid Build Coastguard Worker }
3664*795d594fSAndroid Build Coastguard Worker
VisitDiv(HDiv * instruction)3665*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitDiv(HDiv* instruction) {
3666*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetType();
3667*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
3668*795d594fSAndroid Build Coastguard Worker
3669*795d594fSAndroid Build Coastguard Worker switch (type) {
3670*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
3671*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
3672*795d594fSAndroid Build Coastguard Worker GenerateDivRemIntegral(instruction);
3673*795d594fSAndroid Build Coastguard Worker break;
3674*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
3675*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64: {
3676*795d594fSAndroid Build Coastguard Worker FRegister dst = locations->Out().AsFpuRegister<FRegister>();
3677*795d594fSAndroid Build Coastguard Worker FRegister lhs = locations->InAt(0).AsFpuRegister<FRegister>();
3678*795d594fSAndroid Build Coastguard Worker FRegister rhs = locations->InAt(1).AsFpuRegister<FRegister>();
3679*795d594fSAndroid Build Coastguard Worker FDiv(dst, lhs, rhs, type);
3680*795d594fSAndroid Build Coastguard Worker break;
3681*795d594fSAndroid Build Coastguard Worker }
3682*795d594fSAndroid Build Coastguard Worker default:
3683*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected div type " << type;
3684*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
3685*795d594fSAndroid Build Coastguard Worker }
3686*795d594fSAndroid Build Coastguard Worker }
3687*795d594fSAndroid Build Coastguard Worker
VisitDivZeroCheck(HDivZeroCheck * instruction)3688*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitDivZeroCheck(HDivZeroCheck* instruction) {
3689*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction);
3690*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
3691*795d594fSAndroid Build Coastguard Worker }
3692*795d594fSAndroid Build Coastguard Worker
VisitDivZeroCheck(HDivZeroCheck * instruction)3693*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitDivZeroCheck(HDivZeroCheck* instruction) {
3694*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path =
3695*795d594fSAndroid Build Coastguard Worker new (codegen_->GetScopedAllocator()) DivZeroCheckSlowPathRISCV64(instruction);
3696*795d594fSAndroid Build Coastguard Worker codegen_->AddSlowPath(slow_path);
3697*795d594fSAndroid Build Coastguard Worker Location value = instruction->GetLocations()->InAt(0);
3698*795d594fSAndroid Build Coastguard Worker
3699*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetType();
3700*795d594fSAndroid Build Coastguard Worker
3701*795d594fSAndroid Build Coastguard Worker if (!DataType::IsIntegralType(type)) {
3702*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected type " << type << " for DivZeroCheck.";
3703*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
3704*795d594fSAndroid Build Coastguard Worker }
3705*795d594fSAndroid Build Coastguard Worker
3706*795d594fSAndroid Build Coastguard Worker if (value.IsConstant()) {
3707*795d594fSAndroid Build Coastguard Worker int64_t divisor = codegen_->GetInt64ValueOf(value.GetConstant()->AsConstant());
3708*795d594fSAndroid Build Coastguard Worker if (divisor == 0) {
3709*795d594fSAndroid Build Coastguard Worker __ J(slow_path->GetEntryLabel());
3710*795d594fSAndroid Build Coastguard Worker } else {
3711*795d594fSAndroid Build Coastguard Worker // A division by a non-null constant is valid. We don't need to perform
3712*795d594fSAndroid Build Coastguard Worker // any check, so simply fall through.
3713*795d594fSAndroid Build Coastguard Worker }
3714*795d594fSAndroid Build Coastguard Worker } else {
3715*795d594fSAndroid Build Coastguard Worker __ Beqz(value.AsRegister<XRegister>(), slow_path->GetEntryLabel());
3716*795d594fSAndroid Build Coastguard Worker }
3717*795d594fSAndroid Build Coastguard Worker }
3718*795d594fSAndroid Build Coastguard Worker
VisitDoubleConstant(HDoubleConstant * instruction)3719*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitDoubleConstant(HDoubleConstant* instruction) {
3720*795d594fSAndroid Build Coastguard Worker LocationSummary* locations =
3721*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, LocationSummary::kNoCall);
3722*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::ConstantLocation(instruction));
3723*795d594fSAndroid Build Coastguard Worker }
3724*795d594fSAndroid Build Coastguard Worker
VisitDoubleConstant(HDoubleConstant * instruction)3725*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitDoubleConstant(
3726*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] HDoubleConstant* instruction) {
3727*795d594fSAndroid Build Coastguard Worker // Will be generated at use site.
3728*795d594fSAndroid Build Coastguard Worker }
3729*795d594fSAndroid Build Coastguard Worker
VisitEqual(HEqual * instruction)3730*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitEqual(HEqual* instruction) {
3731*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
3732*795d594fSAndroid Build Coastguard Worker }
3733*795d594fSAndroid Build Coastguard Worker
VisitEqual(HEqual * instruction)3734*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitEqual(HEqual* instruction) {
3735*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
3736*795d594fSAndroid Build Coastguard Worker }
3737*795d594fSAndroid Build Coastguard Worker
VisitExit(HExit * instruction)3738*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitExit(HExit* instruction) {
3739*795d594fSAndroid Build Coastguard Worker instruction->SetLocations(nullptr);
3740*795d594fSAndroid Build Coastguard Worker }
3741*795d594fSAndroid Build Coastguard Worker
VisitExit(HExit * instruction)3742*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitExit([[maybe_unused]] HExit* instruction) {}
3743*795d594fSAndroid Build Coastguard Worker
VisitFloatConstant(HFloatConstant * instruction)3744*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitFloatConstant(HFloatConstant* instruction) {
3745*795d594fSAndroid Build Coastguard Worker LocationSummary* locations =
3746*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, LocationSummary::kNoCall);
3747*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::ConstantLocation(instruction));
3748*795d594fSAndroid Build Coastguard Worker }
3749*795d594fSAndroid Build Coastguard Worker
VisitFloatConstant(HFloatConstant * instruction)3750*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitFloatConstant(
3751*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] HFloatConstant* instruction) {
3752*795d594fSAndroid Build Coastguard Worker // Will be generated at use site.
3753*795d594fSAndroid Build Coastguard Worker }
3754*795d594fSAndroid Build Coastguard Worker
VisitGoto(HGoto * instruction)3755*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitGoto(HGoto* instruction) {
3756*795d594fSAndroid Build Coastguard Worker instruction->SetLocations(nullptr);
3757*795d594fSAndroid Build Coastguard Worker }
3758*795d594fSAndroid Build Coastguard Worker
VisitGoto(HGoto * instruction)3759*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitGoto(HGoto* instruction) {
3760*795d594fSAndroid Build Coastguard Worker HandleGoto(instruction, instruction->GetSuccessor());
3761*795d594fSAndroid Build Coastguard Worker }
3762*795d594fSAndroid Build Coastguard Worker
VisitGreaterThan(HGreaterThan * instruction)3763*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitGreaterThan(HGreaterThan* instruction) {
3764*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
3765*795d594fSAndroid Build Coastguard Worker }
3766*795d594fSAndroid Build Coastguard Worker
VisitGreaterThan(HGreaterThan * instruction)3767*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitGreaterThan(HGreaterThan* instruction) {
3768*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
3769*795d594fSAndroid Build Coastguard Worker }
3770*795d594fSAndroid Build Coastguard Worker
VisitGreaterThanOrEqual(HGreaterThanOrEqual * instruction)3771*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitGreaterThanOrEqual(HGreaterThanOrEqual* instruction) {
3772*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
3773*795d594fSAndroid Build Coastguard Worker }
3774*795d594fSAndroid Build Coastguard Worker
VisitGreaterThanOrEqual(HGreaterThanOrEqual * instruction)3775*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitGreaterThanOrEqual(HGreaterThanOrEqual* instruction) {
3776*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
3777*795d594fSAndroid Build Coastguard Worker }
3778*795d594fSAndroid Build Coastguard Worker
VisitIf(HIf * instruction)3779*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitIf(HIf* instruction) {
3780*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
3781*795d594fSAndroid Build Coastguard Worker if (IsBooleanValueOrMaterializedCondition(instruction->InputAt(0))) {
3782*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
3783*795d594fSAndroid Build Coastguard Worker if (GetGraph()->IsCompilingBaseline() &&
3784*795d594fSAndroid Build Coastguard Worker codegen_->GetCompilerOptions().ProfileBranches() &&
3785*795d594fSAndroid Build Coastguard Worker !Runtime::Current()->IsAotCompiler()) {
3786*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->InputAt(0)->IsCondition());
3787*795d594fSAndroid Build Coastguard Worker ProfilingInfo* info = GetGraph()->GetProfilingInfo();
3788*795d594fSAndroid Build Coastguard Worker DCHECK(info != nullptr);
3789*795d594fSAndroid Build Coastguard Worker BranchCache* cache = info->GetBranchCache(instruction->GetDexPc());
3790*795d594fSAndroid Build Coastguard Worker if (cache != nullptr) {
3791*795d594fSAndroid Build Coastguard Worker locations->AddTemp(Location::RequiresRegister());
3792*795d594fSAndroid Build Coastguard Worker }
3793*795d594fSAndroid Build Coastguard Worker }
3794*795d594fSAndroid Build Coastguard Worker }
3795*795d594fSAndroid Build Coastguard Worker }
3796*795d594fSAndroid Build Coastguard Worker
VisitIf(HIf * instruction)3797*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitIf(HIf* instruction) {
3798*795d594fSAndroid Build Coastguard Worker HBasicBlock* true_successor = instruction->IfTrueSuccessor();
3799*795d594fSAndroid Build Coastguard Worker HBasicBlock* false_successor = instruction->IfFalseSuccessor();
3800*795d594fSAndroid Build Coastguard Worker Riscv64Label* true_target = codegen_->GoesToNextBlock(instruction->GetBlock(), true_successor)
3801*795d594fSAndroid Build Coastguard Worker ? nullptr
3802*795d594fSAndroid Build Coastguard Worker : codegen_->GetLabelOf(true_successor);
3803*795d594fSAndroid Build Coastguard Worker Riscv64Label* false_target = codegen_->GoesToNextBlock(instruction->GetBlock(), false_successor)
3804*795d594fSAndroid Build Coastguard Worker ? nullptr
3805*795d594fSAndroid Build Coastguard Worker : codegen_->GetLabelOf(false_successor);
3806*795d594fSAndroid Build Coastguard Worker if (IsBooleanValueOrMaterializedCondition(instruction->InputAt(0))) {
3807*795d594fSAndroid Build Coastguard Worker if (GetGraph()->IsCompilingBaseline() &&
3808*795d594fSAndroid Build Coastguard Worker codegen_->GetCompilerOptions().ProfileBranches() &&
3809*795d594fSAndroid Build Coastguard Worker !Runtime::Current()->IsAotCompiler()) {
3810*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->InputAt(0)->IsCondition());
3811*795d594fSAndroid Build Coastguard Worker ProfilingInfo* info = GetGraph()->GetProfilingInfo();
3812*795d594fSAndroid Build Coastguard Worker DCHECK(info != nullptr);
3813*795d594fSAndroid Build Coastguard Worker BranchCache* cache = info->GetBranchCache(instruction->GetDexPc());
3814*795d594fSAndroid Build Coastguard Worker // Currently, not all If branches are profiled.
3815*795d594fSAndroid Build Coastguard Worker if (cache != nullptr) {
3816*795d594fSAndroid Build Coastguard Worker uint64_t address =
3817*795d594fSAndroid Build Coastguard Worker reinterpret_cast64<uint64_t>(cache) + BranchCache::FalseOffset().Int32Value();
3818*795d594fSAndroid Build Coastguard Worker static_assert(
3819*795d594fSAndroid Build Coastguard Worker BranchCache::TrueOffset().Int32Value() - BranchCache::FalseOffset().Int32Value() == 2,
3820*795d594fSAndroid Build Coastguard Worker "Unexpected offsets for BranchCache");
3821*795d594fSAndroid Build Coastguard Worker Riscv64Label done;
3822*795d594fSAndroid Build Coastguard Worker XRegister condition = instruction->GetLocations()->InAt(0).AsRegister<XRegister>();
3823*795d594fSAndroid Build Coastguard Worker XRegister temp = instruction->GetLocations()->GetTemp(0).AsRegister<XRegister>();
3824*795d594fSAndroid Build Coastguard Worker __ LoadConst64(temp, address);
3825*795d594fSAndroid Build Coastguard Worker __ Sh1Add(temp, condition, temp);
3826*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
3827*795d594fSAndroid Build Coastguard Worker XRegister counter = srs.AllocateXRegister();
3828*795d594fSAndroid Build Coastguard Worker __ Loadhu(counter, temp, 0);
3829*795d594fSAndroid Build Coastguard Worker __ Addi(counter, counter, 1);
3830*795d594fSAndroid Build Coastguard Worker {
3831*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs2(GetAssembler());
3832*795d594fSAndroid Build Coastguard Worker XRegister overflow = srs2.AllocateXRegister();
3833*795d594fSAndroid Build Coastguard Worker __ Srli(overflow, counter, 16);
3834*795d594fSAndroid Build Coastguard Worker __ Bnez(overflow, &done);
3835*795d594fSAndroid Build Coastguard Worker }
3836*795d594fSAndroid Build Coastguard Worker __ Storeh(counter, temp, 0);
3837*795d594fSAndroid Build Coastguard Worker __ Bind(&done);
3838*795d594fSAndroid Build Coastguard Worker }
3839*795d594fSAndroid Build Coastguard Worker }
3840*795d594fSAndroid Build Coastguard Worker }
3841*795d594fSAndroid Build Coastguard Worker GenerateTestAndBranch(instruction, /* condition_input_index= */ 0, true_target, false_target);
3842*795d594fSAndroid Build Coastguard Worker }
3843*795d594fSAndroid Build Coastguard Worker
VisitInstanceFieldGet(HInstanceFieldGet * instruction)3844*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
3845*795d594fSAndroid Build Coastguard Worker HandleFieldGet(instruction);
3846*795d594fSAndroid Build Coastguard Worker }
3847*795d594fSAndroid Build Coastguard Worker
VisitInstanceFieldGet(HInstanceFieldGet * instruction)3848*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
3849*795d594fSAndroid Build Coastguard Worker HandleFieldGet(instruction, instruction->GetFieldInfo());
3850*795d594fSAndroid Build Coastguard Worker }
3851*795d594fSAndroid Build Coastguard Worker
VisitInstanceFieldSet(HInstanceFieldSet * instruction)3852*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
3853*795d594fSAndroid Build Coastguard Worker HandleFieldSet(instruction);
3854*795d594fSAndroid Build Coastguard Worker }
3855*795d594fSAndroid Build Coastguard Worker
VisitInstanceFieldSet(HInstanceFieldSet * instruction)3856*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
3857*795d594fSAndroid Build Coastguard Worker HandleFieldSet(instruction,
3858*795d594fSAndroid Build Coastguard Worker instruction->GetFieldInfo(),
3859*795d594fSAndroid Build Coastguard Worker instruction->GetValueCanBeNull(),
3860*795d594fSAndroid Build Coastguard Worker instruction->GetWriteBarrierKind());
3861*795d594fSAndroid Build Coastguard Worker }
3862*795d594fSAndroid Build Coastguard Worker
VisitInstanceOf(HInstanceOf * instruction)3863*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitInstanceOf(HInstanceOf* instruction) {
3864*795d594fSAndroid Build Coastguard Worker LocationSummary::CallKind call_kind = LocationSummary::kNoCall;
3865*795d594fSAndroid Build Coastguard Worker TypeCheckKind type_check_kind = instruction->GetTypeCheckKind();
3866*795d594fSAndroid Build Coastguard Worker bool baker_read_barrier_slow_path = false;
3867*795d594fSAndroid Build Coastguard Worker switch (type_check_kind) {
3868*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kExactCheck:
3869*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kAbstractClassCheck:
3870*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kClassHierarchyCheck:
3871*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kArrayObjectCheck:
3872*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kInterfaceCheck: {
3873*795d594fSAndroid Build Coastguard Worker bool needs_read_barrier = codegen_->InstanceOfNeedsReadBarrier(instruction);
3874*795d594fSAndroid Build Coastguard Worker call_kind = needs_read_barrier ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall;
3875*795d594fSAndroid Build Coastguard Worker baker_read_barrier_slow_path = (kUseBakerReadBarrier && needs_read_barrier) &&
3876*795d594fSAndroid Build Coastguard Worker (type_check_kind != TypeCheckKind::kInterfaceCheck);
3877*795d594fSAndroid Build Coastguard Worker break;
3878*795d594fSAndroid Build Coastguard Worker }
3879*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kArrayCheck:
3880*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kUnresolvedCheck:
3881*795d594fSAndroid Build Coastguard Worker call_kind = LocationSummary::kCallOnSlowPath;
3882*795d594fSAndroid Build Coastguard Worker break;
3883*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kBitstringCheck:
3884*795d594fSAndroid Build Coastguard Worker break;
3885*795d594fSAndroid Build Coastguard Worker }
3886*795d594fSAndroid Build Coastguard Worker
3887*795d594fSAndroid Build Coastguard Worker LocationSummary* locations =
3888*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, call_kind);
3889*795d594fSAndroid Build Coastguard Worker if (baker_read_barrier_slow_path) {
3890*795d594fSAndroid Build Coastguard Worker locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
3891*795d594fSAndroid Build Coastguard Worker }
3892*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
3893*795d594fSAndroid Build Coastguard Worker if (type_check_kind == TypeCheckKind::kBitstringCheck) {
3894*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1)));
3895*795d594fSAndroid Build Coastguard Worker locations->SetInAt(2, Location::ConstantLocation(instruction->InputAt(2)));
3896*795d594fSAndroid Build Coastguard Worker locations->SetInAt(3, Location::ConstantLocation(instruction->InputAt(3)));
3897*795d594fSAndroid Build Coastguard Worker } else {
3898*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RequiresRegister());
3899*795d594fSAndroid Build Coastguard Worker }
3900*795d594fSAndroid Build Coastguard Worker // The output does overlap inputs.
3901*795d594fSAndroid Build Coastguard Worker // Note that TypeCheckSlowPathRISCV64 uses this register too.
3902*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
3903*795d594fSAndroid Build Coastguard Worker locations->AddRegisterTemps(
3904*795d594fSAndroid Build Coastguard Worker NumberOfInstanceOfTemps(codegen_->EmitReadBarrier(), type_check_kind));
3905*795d594fSAndroid Build Coastguard Worker }
3906*795d594fSAndroid Build Coastguard Worker
VisitInstanceOf(HInstanceOf * instruction)3907*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitInstanceOf(HInstanceOf* instruction) {
3908*795d594fSAndroid Build Coastguard Worker TypeCheckKind type_check_kind = instruction->GetTypeCheckKind();
3909*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
3910*795d594fSAndroid Build Coastguard Worker Location obj_loc = locations->InAt(0);
3911*795d594fSAndroid Build Coastguard Worker XRegister obj = obj_loc.AsRegister<XRegister>();
3912*795d594fSAndroid Build Coastguard Worker Location cls = (type_check_kind == TypeCheckKind::kBitstringCheck)
3913*795d594fSAndroid Build Coastguard Worker ? Location::NoLocation()
3914*795d594fSAndroid Build Coastguard Worker : locations->InAt(1);
3915*795d594fSAndroid Build Coastguard Worker Location out_loc = locations->Out();
3916*795d594fSAndroid Build Coastguard Worker XRegister out = out_loc.AsRegister<XRegister>();
3917*795d594fSAndroid Build Coastguard Worker const size_t num_temps = NumberOfInstanceOfTemps(codegen_->EmitReadBarrier(), type_check_kind);
3918*795d594fSAndroid Build Coastguard Worker DCHECK_LE(num_temps, 1u);
3919*795d594fSAndroid Build Coastguard Worker Location maybe_temp_loc = (num_temps >= 1) ? locations->GetTemp(0) : Location::NoLocation();
3920*795d594fSAndroid Build Coastguard Worker const uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
3921*795d594fSAndroid Build Coastguard Worker const uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value();
3922*795d594fSAndroid Build Coastguard Worker const uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value();
3923*795d594fSAndroid Build Coastguard Worker const uint32_t primitive_offset = mirror::Class::PrimitiveTypeOffset().Int32Value();
3924*795d594fSAndroid Build Coastguard Worker const uint32_t iftable_offset = mirror::Class::IfTableOffset().Uint32Value();
3925*795d594fSAndroid Build Coastguard Worker const uint32_t array_length_offset = mirror::Array::LengthOffset().Uint32Value();
3926*795d594fSAndroid Build Coastguard Worker const uint32_t object_array_data_offset =
3927*795d594fSAndroid Build Coastguard Worker mirror::Array::DataOffset(kHeapReferenceSize).Uint32Value();
3928*795d594fSAndroid Build Coastguard Worker Riscv64Label done;
3929*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path = nullptr;
3930*795d594fSAndroid Build Coastguard Worker
3931*795d594fSAndroid Build Coastguard Worker // Return 0 if `obj` is null.
3932*795d594fSAndroid Build Coastguard Worker // Avoid this check if we know `obj` is not null.
3933*795d594fSAndroid Build Coastguard Worker if (instruction->MustDoNullCheck()) {
3934*795d594fSAndroid Build Coastguard Worker __ Mv(out, Zero);
3935*795d594fSAndroid Build Coastguard Worker __ Beqz(obj, &done);
3936*795d594fSAndroid Build Coastguard Worker }
3937*795d594fSAndroid Build Coastguard Worker
3938*795d594fSAndroid Build Coastguard Worker switch (type_check_kind) {
3939*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kExactCheck: {
3940*795d594fSAndroid Build Coastguard Worker ReadBarrierOption read_barrier_option =
3941*795d594fSAndroid Build Coastguard Worker codegen_->ReadBarrierOptionForInstanceOf(instruction);
3942*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ out = obj->klass_
3943*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadTwoRegisters(
3944*795d594fSAndroid Build Coastguard Worker instruction, out_loc, obj_loc, class_offset, maybe_temp_loc, read_barrier_option);
3945*795d594fSAndroid Build Coastguard Worker // Classes must be equal for the instanceof to succeed.
3946*795d594fSAndroid Build Coastguard Worker __ Xor(out, out, cls.AsRegister<XRegister>());
3947*795d594fSAndroid Build Coastguard Worker __ Seqz(out, out);
3948*795d594fSAndroid Build Coastguard Worker break;
3949*795d594fSAndroid Build Coastguard Worker }
3950*795d594fSAndroid Build Coastguard Worker
3951*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kAbstractClassCheck: {
3952*795d594fSAndroid Build Coastguard Worker ReadBarrierOption read_barrier_option =
3953*795d594fSAndroid Build Coastguard Worker codegen_->ReadBarrierOptionForInstanceOf(instruction);
3954*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ out = obj->klass_
3955*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadTwoRegisters(
3956*795d594fSAndroid Build Coastguard Worker instruction, out_loc, obj_loc, class_offset, maybe_temp_loc, read_barrier_option);
3957*795d594fSAndroid Build Coastguard Worker // If the class is abstract, we eagerly fetch the super class of the
3958*795d594fSAndroid Build Coastguard Worker // object to avoid doing a comparison we know will fail.
3959*795d594fSAndroid Build Coastguard Worker Riscv64Label loop;
3960*795d594fSAndroid Build Coastguard Worker __ Bind(&loop);
3961*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ out = out->super_class_
3962*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadOneRegister(
3963*795d594fSAndroid Build Coastguard Worker instruction, out_loc, super_offset, maybe_temp_loc, read_barrier_option);
3964*795d594fSAndroid Build Coastguard Worker // If `out` is null, we use it for the result, and jump to `done`.
3965*795d594fSAndroid Build Coastguard Worker __ Beqz(out, &done);
3966*795d594fSAndroid Build Coastguard Worker __ Bne(out, cls.AsRegister<XRegister>(), &loop);
3967*795d594fSAndroid Build Coastguard Worker __ LoadConst32(out, 1);
3968*795d594fSAndroid Build Coastguard Worker break;
3969*795d594fSAndroid Build Coastguard Worker }
3970*795d594fSAndroid Build Coastguard Worker
3971*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kClassHierarchyCheck: {
3972*795d594fSAndroid Build Coastguard Worker ReadBarrierOption read_barrier_option =
3973*795d594fSAndroid Build Coastguard Worker codegen_->ReadBarrierOptionForInstanceOf(instruction);
3974*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ out = obj->klass_
3975*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadTwoRegisters(
3976*795d594fSAndroid Build Coastguard Worker instruction, out_loc, obj_loc, class_offset, maybe_temp_loc, read_barrier_option);
3977*795d594fSAndroid Build Coastguard Worker // Walk over the class hierarchy to find a match.
3978*795d594fSAndroid Build Coastguard Worker Riscv64Label loop, success;
3979*795d594fSAndroid Build Coastguard Worker __ Bind(&loop);
3980*795d594fSAndroid Build Coastguard Worker __ Beq(out, cls.AsRegister<XRegister>(), &success);
3981*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ out = out->super_class_
3982*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadOneRegister(
3983*795d594fSAndroid Build Coastguard Worker instruction, out_loc, super_offset, maybe_temp_loc, read_barrier_option);
3984*795d594fSAndroid Build Coastguard Worker __ Bnez(out, &loop);
3985*795d594fSAndroid Build Coastguard Worker // If `out` is null, we use it for the result, and jump to `done`.
3986*795d594fSAndroid Build Coastguard Worker __ J(&done);
3987*795d594fSAndroid Build Coastguard Worker __ Bind(&success);
3988*795d594fSAndroid Build Coastguard Worker __ LoadConst32(out, 1);
3989*795d594fSAndroid Build Coastguard Worker break;
3990*795d594fSAndroid Build Coastguard Worker }
3991*795d594fSAndroid Build Coastguard Worker
3992*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kArrayObjectCheck: {
3993*795d594fSAndroid Build Coastguard Worker ReadBarrierOption read_barrier_option =
3994*795d594fSAndroid Build Coastguard Worker codegen_->ReadBarrierOptionForInstanceOf(instruction);
3995*795d594fSAndroid Build Coastguard Worker // FIXME(riscv64): We currently have marking entrypoints for 29 registers.
3996*795d594fSAndroid Build Coastguard Worker // We need to either store entrypoint for register `N` in entry `N-A` where
3997*795d594fSAndroid Build Coastguard Worker // `A` can be up to 5 (Zero, RA, SP, GP, TP are not valid registers for
3998*795d594fSAndroid Build Coastguard Worker // marking), or define two more entrypoints, or request an additional temp
3999*795d594fSAndroid Build Coastguard Worker // from the register allocator instead of using a scratch register.
4000*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
4001*795d594fSAndroid Build Coastguard Worker Location tmp = Location::RegisterLocation(srs.AllocateXRegister());
4002*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ tmp = obj->klass_
4003*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadTwoRegisters(
4004*795d594fSAndroid Build Coastguard Worker instruction, tmp, obj_loc, class_offset, maybe_temp_loc, read_barrier_option);
4005*795d594fSAndroid Build Coastguard Worker // Do an exact check.
4006*795d594fSAndroid Build Coastguard Worker __ LoadConst32(out, 1);
4007*795d594fSAndroid Build Coastguard Worker __ Beq(tmp.AsRegister<XRegister>(), cls.AsRegister<XRegister>(), &done);
4008*795d594fSAndroid Build Coastguard Worker // Otherwise, we need to check that the object's class is a non-primitive array.
4009*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ out = out->component_type_
4010*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadTwoRegisters(
4011*795d594fSAndroid Build Coastguard Worker instruction, out_loc, tmp, component_offset, maybe_temp_loc, read_barrier_option);
4012*795d594fSAndroid Build Coastguard Worker // If `out` is null, we use it for the result, and jump to `done`.
4013*795d594fSAndroid Build Coastguard Worker __ Beqz(out, &done);
4014*795d594fSAndroid Build Coastguard Worker __ Loadhu(out, out, primitive_offset);
4015*795d594fSAndroid Build Coastguard Worker static_assert(Primitive::kPrimNot == 0, "Expected 0 for kPrimNot");
4016*795d594fSAndroid Build Coastguard Worker __ Seqz(out, out);
4017*795d594fSAndroid Build Coastguard Worker break;
4018*795d594fSAndroid Build Coastguard Worker }
4019*795d594fSAndroid Build Coastguard Worker
4020*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kArrayCheck: {
4021*795d594fSAndroid Build Coastguard Worker // No read barrier since the slow path will retry upon failure.
4022*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ out = obj->klass_
4023*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadTwoRegisters(
4024*795d594fSAndroid Build Coastguard Worker instruction, out_loc, obj_loc, class_offset, maybe_temp_loc, kWithoutReadBarrier);
4025*795d594fSAndroid Build Coastguard Worker DCHECK(locations->OnlyCallsOnSlowPath());
4026*795d594fSAndroid Build Coastguard Worker slow_path = new (codegen_->GetScopedAllocator())
4027*795d594fSAndroid Build Coastguard Worker TypeCheckSlowPathRISCV64(instruction, /* is_fatal= */ false);
4028*795d594fSAndroid Build Coastguard Worker codegen_->AddSlowPath(slow_path);
4029*795d594fSAndroid Build Coastguard Worker __ Bne(out, cls.AsRegister<XRegister>(), slow_path->GetEntryLabel());
4030*795d594fSAndroid Build Coastguard Worker __ LoadConst32(out, 1);
4031*795d594fSAndroid Build Coastguard Worker break;
4032*795d594fSAndroid Build Coastguard Worker }
4033*795d594fSAndroid Build Coastguard Worker
4034*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kInterfaceCheck: {
4035*795d594fSAndroid Build Coastguard Worker if (codegen_->InstanceOfNeedsReadBarrier(instruction)) {
4036*795d594fSAndroid Build Coastguard Worker DCHECK(locations->OnlyCallsOnSlowPath());
4037*795d594fSAndroid Build Coastguard Worker slow_path = new (codegen_->GetScopedAllocator()) TypeCheckSlowPathRISCV64(
4038*795d594fSAndroid Build Coastguard Worker instruction, /* is_fatal= */ false);
4039*795d594fSAndroid Build Coastguard Worker codegen_->AddSlowPath(slow_path);
4040*795d594fSAndroid Build Coastguard Worker if (codegen_->EmitNonBakerReadBarrier()) {
4041*795d594fSAndroid Build Coastguard Worker __ J(slow_path->GetEntryLabel());
4042*795d594fSAndroid Build Coastguard Worker break;
4043*795d594fSAndroid Build Coastguard Worker }
4044*795d594fSAndroid Build Coastguard Worker // For Baker read barrier, take the slow path while marking.
4045*795d594fSAndroid Build Coastguard Worker __ Loadw(out, TR, Thread::IsGcMarkingOffset<kRiscv64PointerSize>().Int32Value());
4046*795d594fSAndroid Build Coastguard Worker __ Bnez(out, slow_path->GetEntryLabel());
4047*795d594fSAndroid Build Coastguard Worker }
4048*795d594fSAndroid Build Coastguard Worker
4049*795d594fSAndroid Build Coastguard Worker // Fast-path without read barriers.
4050*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
4051*795d594fSAndroid Build Coastguard Worker XRegister temp = srs.AllocateXRegister();
4052*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp = obj->klass_
4053*795d594fSAndroid Build Coastguard Worker __ Loadwu(temp, obj, class_offset);
4054*795d594fSAndroid Build Coastguard Worker codegen_->MaybeUnpoisonHeapReference(temp);
4055*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp = temp->iftable_
4056*795d594fSAndroid Build Coastguard Worker __ Loadwu(temp, temp, iftable_offset);
4057*795d594fSAndroid Build Coastguard Worker codegen_->MaybeUnpoisonHeapReference(temp);
4058*795d594fSAndroid Build Coastguard Worker // Load the size of the `IfTable`. The `Class::iftable_` is never null.
4059*795d594fSAndroid Build Coastguard Worker __ Loadw(out, temp, array_length_offset);
4060*795d594fSAndroid Build Coastguard Worker // Loop through the `IfTable` and check if any class matches.
4061*795d594fSAndroid Build Coastguard Worker Riscv64Label loop;
4062*795d594fSAndroid Build Coastguard Worker XRegister temp2 = srs.AllocateXRegister();
4063*795d594fSAndroid Build Coastguard Worker __ Bind(&loop);
4064*795d594fSAndroid Build Coastguard Worker __ Beqz(out, &done); // If taken, the result in `out` is already 0 (false).
4065*795d594fSAndroid Build Coastguard Worker __ Loadwu(temp2, temp, object_array_data_offset);
4066*795d594fSAndroid Build Coastguard Worker codegen_->MaybeUnpoisonHeapReference(temp2);
4067*795d594fSAndroid Build Coastguard Worker // Go to next interface.
4068*795d594fSAndroid Build Coastguard Worker __ Addi(temp, temp, 2 * kHeapReferenceSize);
4069*795d594fSAndroid Build Coastguard Worker __ Addi(out, out, -2);
4070*795d594fSAndroid Build Coastguard Worker // Compare the classes and continue the loop if they do not match.
4071*795d594fSAndroid Build Coastguard Worker __ Bne(cls.AsRegister<XRegister>(), temp2, &loop);
4072*795d594fSAndroid Build Coastguard Worker __ LoadConst32(out, 1);
4073*795d594fSAndroid Build Coastguard Worker break;
4074*795d594fSAndroid Build Coastguard Worker }
4075*795d594fSAndroid Build Coastguard Worker
4076*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kUnresolvedCheck: {
4077*795d594fSAndroid Build Coastguard Worker // Note that we indeed only call on slow path, but we always go
4078*795d594fSAndroid Build Coastguard Worker // into the slow path for the unresolved check case.
4079*795d594fSAndroid Build Coastguard Worker //
4080*795d594fSAndroid Build Coastguard Worker // We cannot directly call the InstanceofNonTrivial runtime
4081*795d594fSAndroid Build Coastguard Worker // entry point without resorting to a type checking slow path
4082*795d594fSAndroid Build Coastguard Worker // here (i.e. by calling InvokeRuntime directly), as it would
4083*795d594fSAndroid Build Coastguard Worker // require to assign fixed registers for the inputs of this
4084*795d594fSAndroid Build Coastguard Worker // HInstanceOf instruction (following the runtime calling
4085*795d594fSAndroid Build Coastguard Worker // convention), which might be cluttered by the potential first
4086*795d594fSAndroid Build Coastguard Worker // read barrier emission at the beginning of this method.
4087*795d594fSAndroid Build Coastguard Worker //
4088*795d594fSAndroid Build Coastguard Worker // TODO: Introduce a new runtime entry point taking the object
4089*795d594fSAndroid Build Coastguard Worker // to test (instead of its class) as argument, and let it deal
4090*795d594fSAndroid Build Coastguard Worker // with the read barrier issues. This will let us refactor this
4091*795d594fSAndroid Build Coastguard Worker // case of the `switch` code as it was previously (with a direct
4092*795d594fSAndroid Build Coastguard Worker // call to the runtime not using a type checking slow path).
4093*795d594fSAndroid Build Coastguard Worker // This should also be beneficial for the other cases above.
4094*795d594fSAndroid Build Coastguard Worker DCHECK(locations->OnlyCallsOnSlowPath());
4095*795d594fSAndroid Build Coastguard Worker slow_path = new (codegen_->GetScopedAllocator()) TypeCheckSlowPathRISCV64(
4096*795d594fSAndroid Build Coastguard Worker instruction, /* is_fatal= */ false);
4097*795d594fSAndroid Build Coastguard Worker codegen_->AddSlowPath(slow_path);
4098*795d594fSAndroid Build Coastguard Worker __ J(slow_path->GetEntryLabel());
4099*795d594fSAndroid Build Coastguard Worker break;
4100*795d594fSAndroid Build Coastguard Worker }
4101*795d594fSAndroid Build Coastguard Worker
4102*795d594fSAndroid Build Coastguard Worker case TypeCheckKind::kBitstringCheck: {
4103*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp = obj->klass_
4104*795d594fSAndroid Build Coastguard Worker GenerateReferenceLoadTwoRegisters(
4105*795d594fSAndroid Build Coastguard Worker instruction, out_loc, obj_loc, class_offset, maybe_temp_loc, kWithoutReadBarrier);
4106*795d594fSAndroid Build Coastguard Worker
4107*795d594fSAndroid Build Coastguard Worker GenerateBitstringTypeCheckCompare(instruction, out);
4108*795d594fSAndroid Build Coastguard Worker __ Beqz(out, out);
4109*795d594fSAndroid Build Coastguard Worker break;
4110*795d594fSAndroid Build Coastguard Worker }
4111*795d594fSAndroid Build Coastguard Worker }
4112*795d594fSAndroid Build Coastguard Worker
4113*795d594fSAndroid Build Coastguard Worker __ Bind(&done);
4114*795d594fSAndroid Build Coastguard Worker
4115*795d594fSAndroid Build Coastguard Worker if (slow_path != nullptr) {
4116*795d594fSAndroid Build Coastguard Worker __ Bind(slow_path->GetExitLabel());
4117*795d594fSAndroid Build Coastguard Worker }
4118*795d594fSAndroid Build Coastguard Worker }
4119*795d594fSAndroid Build Coastguard Worker
VisitIntConstant(HIntConstant * instruction)4120*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitIntConstant(HIntConstant* instruction) {
4121*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
4122*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::ConstantLocation(instruction));
4123*795d594fSAndroid Build Coastguard Worker }
4124*795d594fSAndroid Build Coastguard Worker
VisitIntConstant(HIntConstant * instruction)4125*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitIntConstant([[maybe_unused]] HIntConstant* instruction) {
4126*795d594fSAndroid Build Coastguard Worker // Will be generated at use site.
4127*795d594fSAndroid Build Coastguard Worker }
4128*795d594fSAndroid Build Coastguard Worker
VisitIntermediateAddress(HIntermediateAddress * instruction)4129*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitIntermediateAddress(HIntermediateAddress* instruction) {
4130*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
4131*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
4132*795d594fSAndroid Build Coastguard Worker }
4133*795d594fSAndroid Build Coastguard Worker
VisitIntermediateAddress(HIntermediateAddress * instruction)4134*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitIntermediateAddress(HIntermediateAddress* instruction) {
4135*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
4136*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
4137*795d594fSAndroid Build Coastguard Worker }
4138*795d594fSAndroid Build Coastguard Worker
VisitInvokeUnresolved(HInvokeUnresolved * instruction)4139*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitInvokeUnresolved(HInvokeUnresolved* instruction) {
4140*795d594fSAndroid Build Coastguard Worker // The trampoline uses the same calling convention as dex calling conventions, except
4141*795d594fSAndroid Build Coastguard Worker // instead of loading arg0/A0 with the target Method*, arg0/A0 will contain the method_idx.
4142*795d594fSAndroid Build Coastguard Worker HandleInvoke(instruction);
4143*795d594fSAndroid Build Coastguard Worker }
4144*795d594fSAndroid Build Coastguard Worker
VisitInvokeUnresolved(HInvokeUnresolved * instruction)4145*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitInvokeUnresolved(HInvokeUnresolved* instruction) {
4146*795d594fSAndroid Build Coastguard Worker codegen_->GenerateInvokeUnresolvedRuntimeCall(instruction);
4147*795d594fSAndroid Build Coastguard Worker }
4148*795d594fSAndroid Build Coastguard Worker
VisitInvokeInterface(HInvokeInterface * instruction)4149*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitInvokeInterface(HInvokeInterface* instruction) {
4150*795d594fSAndroid Build Coastguard Worker HandleInvoke(instruction);
4151*795d594fSAndroid Build Coastguard Worker // Use T0 as the hidden argument for `art_quick_imt_conflict_trampoline`.
4152*795d594fSAndroid Build Coastguard Worker if (instruction->GetHiddenArgumentLoadKind() == MethodLoadKind::kRecursive) {
4153*795d594fSAndroid Build Coastguard Worker instruction->GetLocations()->SetInAt(instruction->GetNumberOfArguments() - 1,
4154*795d594fSAndroid Build Coastguard Worker Location::RegisterLocation(T0));
4155*795d594fSAndroid Build Coastguard Worker } else {
4156*795d594fSAndroid Build Coastguard Worker instruction->GetLocations()->AddTemp(Location::RegisterLocation(T0));
4157*795d594fSAndroid Build Coastguard Worker }
4158*795d594fSAndroid Build Coastguard Worker }
4159*795d594fSAndroid Build Coastguard Worker
VisitInvokeInterface(HInvokeInterface * instruction)4160*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitInvokeInterface(HInvokeInterface* instruction) {
4161*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
4162*795d594fSAndroid Build Coastguard Worker XRegister temp = locations->GetTemp(0).AsRegister<XRegister>();
4163*795d594fSAndroid Build Coastguard Worker XRegister receiver = locations->InAt(0).AsRegister<XRegister>();
4164*795d594fSAndroid Build Coastguard Worker int32_t class_offset = mirror::Object::ClassOffset().Int32Value();
4165*795d594fSAndroid Build Coastguard Worker Offset entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kRiscv64PointerSize);
4166*795d594fSAndroid Build Coastguard Worker
4167*795d594fSAndroid Build Coastguard Worker // /* HeapReference<Class> */ temp = receiver->klass_
4168*795d594fSAndroid Build Coastguard Worker __ Loadwu(temp, receiver, class_offset);
4169*795d594fSAndroid Build Coastguard Worker codegen_->MaybeRecordImplicitNullCheck(instruction);
4170*795d594fSAndroid Build Coastguard Worker // Instead of simply (possibly) unpoisoning `temp` here, we should
4171*795d594fSAndroid Build Coastguard Worker // emit a read barrier for the previous class reference load.
4172*795d594fSAndroid Build Coastguard Worker // However this is not required in practice, as this is an
4173*795d594fSAndroid Build Coastguard Worker // intermediate/temporary reference and because the current
4174*795d594fSAndroid Build Coastguard Worker // concurrent copying collector keeps the from-space memory
4175*795d594fSAndroid Build Coastguard Worker // intact/accessible until the end of the marking phase (the
4176*795d594fSAndroid Build Coastguard Worker // concurrent copying collector may not in the future).
4177*795d594fSAndroid Build Coastguard Worker codegen_->MaybeUnpoisonHeapReference(temp);
4178*795d594fSAndroid Build Coastguard Worker
4179*795d594fSAndroid Build Coastguard Worker // If we're compiling baseline, update the inline cache.
4180*795d594fSAndroid Build Coastguard Worker codegen_->MaybeGenerateInlineCacheCheck(instruction, temp);
4181*795d594fSAndroid Build Coastguard Worker
4182*795d594fSAndroid Build Coastguard Worker // The register T0 is required to be used for the hidden argument in
4183*795d594fSAndroid Build Coastguard Worker // `art_quick_imt_conflict_trampoline`.
4184*795d594fSAndroid Build Coastguard Worker if (instruction->GetHiddenArgumentLoadKind() != MethodLoadKind::kRecursive &&
4185*795d594fSAndroid Build Coastguard Worker instruction->GetHiddenArgumentLoadKind() != MethodLoadKind::kRuntimeCall) {
4186*795d594fSAndroid Build Coastguard Worker Location hidden_reg = instruction->GetLocations()->GetTemp(1);
4187*795d594fSAndroid Build Coastguard Worker // Load the resolved interface method in the hidden argument register T0.
4188*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(T0, hidden_reg.AsRegister<XRegister>());
4189*795d594fSAndroid Build Coastguard Worker codegen_->LoadMethod(instruction->GetHiddenArgumentLoadKind(), hidden_reg, instruction);
4190*795d594fSAndroid Build Coastguard Worker }
4191*795d594fSAndroid Build Coastguard Worker
4192*795d594fSAndroid Build Coastguard Worker __ Loadd(temp, temp, mirror::Class::ImtPtrOffset(kRiscv64PointerSize).Uint32Value());
4193*795d594fSAndroid Build Coastguard Worker uint32_t method_offset = static_cast<uint32_t>(ImTable::OffsetOfElement(
4194*795d594fSAndroid Build Coastguard Worker instruction->GetImtIndex(), kRiscv64PointerSize));
4195*795d594fSAndroid Build Coastguard Worker // temp = temp->GetImtEntryAt(method_offset);
4196*795d594fSAndroid Build Coastguard Worker __ Loadd(temp, temp, method_offset);
4197*795d594fSAndroid Build Coastguard Worker if (instruction->GetHiddenArgumentLoadKind() == MethodLoadKind::kRuntimeCall) {
4198*795d594fSAndroid Build Coastguard Worker // We pass the method from the IMT in case of a conflict. This will ensure
4199*795d594fSAndroid Build Coastguard Worker // we go into the runtime to resolve the actual method.
4200*795d594fSAndroid Build Coastguard Worker Location hidden_reg = instruction->GetLocations()->GetTemp(1);
4201*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(T0, hidden_reg.AsRegister<XRegister>());
4202*795d594fSAndroid Build Coastguard Worker __ Mv(hidden_reg.AsRegister<XRegister>(), temp);
4203*795d594fSAndroid Build Coastguard Worker }
4204*795d594fSAndroid Build Coastguard Worker // RA = temp->GetEntryPoint();
4205*795d594fSAndroid Build Coastguard Worker __ Loadd(RA, temp, entry_point.Int32Value());
4206*795d594fSAndroid Build Coastguard Worker
4207*795d594fSAndroid Build Coastguard Worker // RA();
4208*795d594fSAndroid Build Coastguard Worker __ Jalr(RA);
4209*795d594fSAndroid Build Coastguard Worker DCHECK(!codegen_->IsLeafMethod());
4210*795d594fSAndroid Build Coastguard Worker codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
4211*795d594fSAndroid Build Coastguard Worker }
4212*795d594fSAndroid Build Coastguard Worker
VisitInvokeStaticOrDirect(HInvokeStaticOrDirect * instruction)4213*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* instruction) {
4214*795d594fSAndroid Build Coastguard Worker // Explicit clinit checks triggered by static invokes must have been pruned by
4215*795d594fSAndroid Build Coastguard Worker // art::PrepareForRegisterAllocation.
4216*795d594fSAndroid Build Coastguard Worker DCHECK(!instruction->IsStaticWithExplicitClinitCheck());
4217*795d594fSAndroid Build Coastguard Worker
4218*795d594fSAndroid Build Coastguard Worker IntrinsicLocationsBuilderRISCV64 intrinsic(GetGraph()->GetAllocator(), codegen_);
4219*795d594fSAndroid Build Coastguard Worker if (intrinsic.TryDispatch(instruction)) {
4220*795d594fSAndroid Build Coastguard Worker return;
4221*795d594fSAndroid Build Coastguard Worker }
4222*795d594fSAndroid Build Coastguard Worker
4223*795d594fSAndroid Build Coastguard Worker if (instruction->GetCodePtrLocation() == CodePtrLocation::kCallCriticalNative) {
4224*795d594fSAndroid Build Coastguard Worker CriticalNativeCallingConventionVisitorRiscv64 calling_convention_visitor(
4225*795d594fSAndroid Build Coastguard Worker /*for_register_allocation=*/ true);
4226*795d594fSAndroid Build Coastguard Worker CodeGenerator::CreateCommonInvokeLocationSummary(instruction, &calling_convention_visitor);
4227*795d594fSAndroid Build Coastguard Worker } else {
4228*795d594fSAndroid Build Coastguard Worker HandleInvoke(instruction);
4229*795d594fSAndroid Build Coastguard Worker }
4230*795d594fSAndroid Build Coastguard Worker }
4231*795d594fSAndroid Build Coastguard Worker
TryGenerateIntrinsicCode(HInvoke * invoke,CodeGeneratorRISCV64 * codegen)4232*795d594fSAndroid Build Coastguard Worker static bool TryGenerateIntrinsicCode(HInvoke* invoke, CodeGeneratorRISCV64* codegen) {
4233*795d594fSAndroid Build Coastguard Worker if (invoke->GetLocations()->Intrinsified()) {
4234*795d594fSAndroid Build Coastguard Worker IntrinsicCodeGeneratorRISCV64 intrinsic(codegen);
4235*795d594fSAndroid Build Coastguard Worker intrinsic.Dispatch(invoke);
4236*795d594fSAndroid Build Coastguard Worker return true;
4237*795d594fSAndroid Build Coastguard Worker }
4238*795d594fSAndroid Build Coastguard Worker return false;
4239*795d594fSAndroid Build Coastguard Worker }
4240*795d594fSAndroid Build Coastguard Worker
VisitInvokeStaticOrDirect(HInvokeStaticOrDirect * instruction)4241*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitInvokeStaticOrDirect(
4242*795d594fSAndroid Build Coastguard Worker HInvokeStaticOrDirect* instruction) {
4243*795d594fSAndroid Build Coastguard Worker // Explicit clinit checks triggered by static invokes must have been pruned by
4244*795d594fSAndroid Build Coastguard Worker // art::PrepareForRegisterAllocation.
4245*795d594fSAndroid Build Coastguard Worker DCHECK(!instruction->IsStaticWithExplicitClinitCheck());
4246*795d594fSAndroid Build Coastguard Worker
4247*795d594fSAndroid Build Coastguard Worker if (TryGenerateIntrinsicCode(instruction, codegen_)) {
4248*795d594fSAndroid Build Coastguard Worker return;
4249*795d594fSAndroid Build Coastguard Worker }
4250*795d594fSAndroid Build Coastguard Worker
4251*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
4252*795d594fSAndroid Build Coastguard Worker codegen_->GenerateStaticOrDirectCall(
4253*795d594fSAndroid Build Coastguard Worker instruction, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
4254*795d594fSAndroid Build Coastguard Worker }
4255*795d594fSAndroid Build Coastguard Worker
VisitInvokeVirtual(HInvokeVirtual * instruction)4256*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitInvokeVirtual(HInvokeVirtual* instruction) {
4257*795d594fSAndroid Build Coastguard Worker IntrinsicLocationsBuilderRISCV64 intrinsic(GetGraph()->GetAllocator(), codegen_);
4258*795d594fSAndroid Build Coastguard Worker if (intrinsic.TryDispatch(instruction)) {
4259*795d594fSAndroid Build Coastguard Worker return;
4260*795d594fSAndroid Build Coastguard Worker }
4261*795d594fSAndroid Build Coastguard Worker
4262*795d594fSAndroid Build Coastguard Worker HandleInvoke(instruction);
4263*795d594fSAndroid Build Coastguard Worker }
4264*795d594fSAndroid Build Coastguard Worker
VisitInvokeVirtual(HInvokeVirtual * instruction)4265*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitInvokeVirtual(HInvokeVirtual* instruction) {
4266*795d594fSAndroid Build Coastguard Worker if (TryGenerateIntrinsicCode(instruction, codegen_)) {
4267*795d594fSAndroid Build Coastguard Worker return;
4268*795d594fSAndroid Build Coastguard Worker }
4269*795d594fSAndroid Build Coastguard Worker
4270*795d594fSAndroid Build Coastguard Worker codegen_->GenerateVirtualCall(instruction, instruction->GetLocations()->GetTemp(0));
4271*795d594fSAndroid Build Coastguard Worker DCHECK(!codegen_->IsLeafMethod());
4272*795d594fSAndroid Build Coastguard Worker }
4273*795d594fSAndroid Build Coastguard Worker
VisitInvokePolymorphic(HInvokePolymorphic * instruction)4274*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitInvokePolymorphic(HInvokePolymorphic* instruction) {
4275*795d594fSAndroid Build Coastguard Worker IntrinsicLocationsBuilderRISCV64 intrinsic(GetGraph()->GetAllocator(), codegen_);
4276*795d594fSAndroid Build Coastguard Worker if (intrinsic.TryDispatch(instruction)) {
4277*795d594fSAndroid Build Coastguard Worker return;
4278*795d594fSAndroid Build Coastguard Worker }
4279*795d594fSAndroid Build Coastguard Worker HandleInvoke(instruction);
4280*795d594fSAndroid Build Coastguard Worker }
4281*795d594fSAndroid Build Coastguard Worker
VisitInvokePolymorphic(HInvokePolymorphic * instruction)4282*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitInvokePolymorphic(HInvokePolymorphic* instruction) {
4283*795d594fSAndroid Build Coastguard Worker if (TryGenerateIntrinsicCode(instruction, codegen_)) {
4284*795d594fSAndroid Build Coastguard Worker return;
4285*795d594fSAndroid Build Coastguard Worker }
4286*795d594fSAndroid Build Coastguard Worker codegen_->GenerateInvokePolymorphicCall(instruction);
4287*795d594fSAndroid Build Coastguard Worker }
4288*795d594fSAndroid Build Coastguard Worker
VisitInvokeCustom(HInvokeCustom * instruction)4289*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitInvokeCustom(HInvokeCustom* instruction) {
4290*795d594fSAndroid Build Coastguard Worker HandleInvoke(instruction);
4291*795d594fSAndroid Build Coastguard Worker }
4292*795d594fSAndroid Build Coastguard Worker
VisitInvokeCustom(HInvokeCustom * instruction)4293*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitInvokeCustom(HInvokeCustom* instruction) {
4294*795d594fSAndroid Build Coastguard Worker codegen_->GenerateInvokeCustomCall(instruction);
4295*795d594fSAndroid Build Coastguard Worker }
4296*795d594fSAndroid Build Coastguard Worker
VisitLessThan(HLessThan * instruction)4297*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitLessThan(HLessThan* instruction) {
4298*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
4299*795d594fSAndroid Build Coastguard Worker }
4300*795d594fSAndroid Build Coastguard Worker
VisitLessThan(HLessThan * instruction)4301*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitLessThan(HLessThan* instruction) {
4302*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
4303*795d594fSAndroid Build Coastguard Worker }
4304*795d594fSAndroid Build Coastguard Worker
VisitLessThanOrEqual(HLessThanOrEqual * instruction)4305*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitLessThanOrEqual(HLessThanOrEqual* instruction) {
4306*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
4307*795d594fSAndroid Build Coastguard Worker }
4308*795d594fSAndroid Build Coastguard Worker
VisitLessThanOrEqual(HLessThanOrEqual * instruction)4309*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitLessThanOrEqual(HLessThanOrEqual* instruction) {
4310*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
4311*795d594fSAndroid Build Coastguard Worker }
4312*795d594fSAndroid Build Coastguard Worker
VisitLoadClass(HLoadClass * instruction)4313*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitLoadClass(HLoadClass* instruction) {
4314*795d594fSAndroid Build Coastguard Worker HLoadClass::LoadKind load_kind = instruction->GetLoadKind();
4315*795d594fSAndroid Build Coastguard Worker if (load_kind == HLoadClass::LoadKind::kRuntimeCall) {
4316*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
4317*795d594fSAndroid Build Coastguard Worker Location loc = Location::RegisterLocation(calling_convention.GetRegisterAt(0));
4318*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(DataType::Type::kReference, instruction->GetType());
4319*795d594fSAndroid Build Coastguard Worker DCHECK(loc.Equals(calling_convention.GetReturnLocation(DataType::Type::kReference)));
4320*795d594fSAndroid Build Coastguard Worker CodeGenerator::CreateLoadClassRuntimeCallLocationSummary(instruction, loc, loc);
4321*795d594fSAndroid Build Coastguard Worker return;
4322*795d594fSAndroid Build Coastguard Worker }
4323*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(instruction->NeedsAccessCheck(),
4324*795d594fSAndroid Build Coastguard Worker load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
4325*795d594fSAndroid Build Coastguard Worker load_kind == HLoadClass::LoadKind::kBssEntryPackage);
4326*795d594fSAndroid Build Coastguard Worker
4327*795d594fSAndroid Build Coastguard Worker const bool requires_read_barrier = !instruction->IsInImage() && codegen_->EmitReadBarrier();
4328*795d594fSAndroid Build Coastguard Worker LocationSummary::CallKind call_kind = (instruction->NeedsEnvironment() || requires_read_barrier)
4329*795d594fSAndroid Build Coastguard Worker ? LocationSummary::kCallOnSlowPath
4330*795d594fSAndroid Build Coastguard Worker : LocationSummary::kNoCall;
4331*795d594fSAndroid Build Coastguard Worker LocationSummary* locations =
4332*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, call_kind);
4333*795d594fSAndroid Build Coastguard Worker if (kUseBakerReadBarrier && requires_read_barrier && !instruction->NeedsEnvironment()) {
4334*795d594fSAndroid Build Coastguard Worker locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
4335*795d594fSAndroid Build Coastguard Worker }
4336*795d594fSAndroid Build Coastguard Worker if (load_kind == HLoadClass::LoadKind::kReferrersClass) {
4337*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
4338*795d594fSAndroid Build Coastguard Worker }
4339*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister());
4340*795d594fSAndroid Build Coastguard Worker if (load_kind == HLoadClass::LoadKind::kBssEntry ||
4341*795d594fSAndroid Build Coastguard Worker load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
4342*795d594fSAndroid Build Coastguard Worker load_kind == HLoadClass::LoadKind::kBssEntryPackage) {
4343*795d594fSAndroid Build Coastguard Worker if (codegen_->EmitNonBakerReadBarrier()) {
4344*795d594fSAndroid Build Coastguard Worker // For non-Baker read barriers we have a temp-clobbering call.
4345*795d594fSAndroid Build Coastguard Worker } else {
4346*795d594fSAndroid Build Coastguard Worker // Rely on the type resolution or initialization and marking to save everything we need.
4347*795d594fSAndroid Build Coastguard Worker locations->SetCustomSlowPathCallerSaves(OneRegInReferenceOutSaveEverythingCallerSaves());
4348*795d594fSAndroid Build Coastguard Worker }
4349*795d594fSAndroid Build Coastguard Worker }
4350*795d594fSAndroid Build Coastguard Worker }
4351*795d594fSAndroid Build Coastguard Worker
4352*795d594fSAndroid Build Coastguard Worker // NO_THREAD_SAFETY_ANALYSIS as we manipulate handles whose internal object we know does not
4353*795d594fSAndroid Build Coastguard Worker // move.
VisitLoadClass(HLoadClass * instruction)4354*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitLoadClass(HLoadClass* instruction)
4355*795d594fSAndroid Build Coastguard Worker NO_THREAD_SAFETY_ANALYSIS {
4356*795d594fSAndroid Build Coastguard Worker HLoadClass::LoadKind load_kind = instruction->GetLoadKind();
4357*795d594fSAndroid Build Coastguard Worker if (load_kind == HLoadClass::LoadKind::kRuntimeCall) {
4358*795d594fSAndroid Build Coastguard Worker codegen_->GenerateLoadClassRuntimeCall(instruction);
4359*795d594fSAndroid Build Coastguard Worker return;
4360*795d594fSAndroid Build Coastguard Worker }
4361*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(instruction->NeedsAccessCheck(),
4362*795d594fSAndroid Build Coastguard Worker load_kind == HLoadClass::LoadKind::kBssEntryPublic ||
4363*795d594fSAndroid Build Coastguard Worker load_kind == HLoadClass::LoadKind::kBssEntryPackage);
4364*795d594fSAndroid Build Coastguard Worker
4365*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
4366*795d594fSAndroid Build Coastguard Worker Location out_loc = locations->Out();
4367*795d594fSAndroid Build Coastguard Worker XRegister out = out_loc.AsRegister<XRegister>();
4368*795d594fSAndroid Build Coastguard Worker const ReadBarrierOption read_barrier_option =
4369*795d594fSAndroid Build Coastguard Worker instruction->IsInImage() ? kWithoutReadBarrier : codegen_->GetCompilerReadBarrierOption();
4370*795d594fSAndroid Build Coastguard Worker bool generate_null_check = false;
4371*795d594fSAndroid Build Coastguard Worker switch (load_kind) {
4372*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kReferrersClass: {
4373*795d594fSAndroid Build Coastguard Worker DCHECK(!instruction->CanCallRuntime());
4374*795d594fSAndroid Build Coastguard Worker DCHECK(!instruction->MustGenerateClinitCheck());
4375*795d594fSAndroid Build Coastguard Worker // /* GcRoot<mirror::Class> */ out = current_method->declaring_class_
4376*795d594fSAndroid Build Coastguard Worker XRegister current_method = locations->InAt(0).AsRegister<XRegister>();
4377*795d594fSAndroid Build Coastguard Worker codegen_->GenerateGcRootFieldLoad(instruction,
4378*795d594fSAndroid Build Coastguard Worker out_loc,
4379*795d594fSAndroid Build Coastguard Worker current_method,
4380*795d594fSAndroid Build Coastguard Worker ArtMethod::DeclaringClassOffset().Int32Value(),
4381*795d594fSAndroid Build Coastguard Worker read_barrier_option);
4382*795d594fSAndroid Build Coastguard Worker break;
4383*795d594fSAndroid Build Coastguard Worker }
4384*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: {
4385*795d594fSAndroid Build Coastguard Worker DCHECK(codegen_->GetCompilerOptions().IsBootImage() ||
4386*795d594fSAndroid Build Coastguard Worker codegen_->GetCompilerOptions().IsBootImageExtension());
4387*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
4388*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* info_high =
4389*795d594fSAndroid Build Coastguard Worker codegen_->NewBootImageTypePatch(instruction->GetDexFile(), instruction->GetTypeIndex());
4390*795d594fSAndroid Build Coastguard Worker codegen_->EmitPcRelativeAuipcPlaceholder(info_high, out);
4391*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* info_low =
4392*795d594fSAndroid Build Coastguard Worker codegen_->NewBootImageTypePatch(
4393*795d594fSAndroid Build Coastguard Worker instruction->GetDexFile(), instruction->GetTypeIndex(), info_high);
4394*795d594fSAndroid Build Coastguard Worker codegen_->EmitPcRelativeAddiPlaceholder(info_low, out, out);
4395*795d594fSAndroid Build Coastguard Worker break;
4396*795d594fSAndroid Build Coastguard Worker }
4397*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kBootImageRelRo: {
4398*795d594fSAndroid Build Coastguard Worker DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
4399*795d594fSAndroid Build Coastguard Worker uint32_t boot_image_offset = codegen_->GetBootImageOffset(instruction);
4400*795d594fSAndroid Build Coastguard Worker codegen_->LoadBootImageRelRoEntry(out, boot_image_offset);
4401*795d594fSAndroid Build Coastguard Worker break;
4402*795d594fSAndroid Build Coastguard Worker }
4403*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kAppImageRelRo: {
4404*795d594fSAndroid Build Coastguard Worker DCHECK(codegen_->GetCompilerOptions().IsAppImage());
4405*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
4406*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* info_high =
4407*795d594fSAndroid Build Coastguard Worker codegen_->NewAppImageTypePatch(instruction->GetDexFile(), instruction->GetTypeIndex());
4408*795d594fSAndroid Build Coastguard Worker codegen_->EmitPcRelativeAuipcPlaceholder(info_high, out);
4409*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* info_low =
4410*795d594fSAndroid Build Coastguard Worker codegen_->NewAppImageTypePatch(
4411*795d594fSAndroid Build Coastguard Worker instruction->GetDexFile(), instruction->GetTypeIndex(), info_high);
4412*795d594fSAndroid Build Coastguard Worker codegen_->EmitPcRelativeLwuPlaceholder(info_low, out, out);
4413*795d594fSAndroid Build Coastguard Worker break;
4414*795d594fSAndroid Build Coastguard Worker }
4415*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kBssEntry:
4416*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kBssEntryPublic:
4417*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kBssEntryPackage: {
4418*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* bss_info_high =
4419*795d594fSAndroid Build Coastguard Worker codegen_->NewTypeBssEntryPatch(instruction);
4420*795d594fSAndroid Build Coastguard Worker codegen_->EmitPcRelativeAuipcPlaceholder(bss_info_high, out);
4421*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* info_low = codegen_->NewTypeBssEntryPatch(
4422*795d594fSAndroid Build Coastguard Worker instruction, bss_info_high);
4423*795d594fSAndroid Build Coastguard Worker codegen_->GenerateGcRootFieldLoad(instruction,
4424*795d594fSAndroid Build Coastguard Worker out_loc,
4425*795d594fSAndroid Build Coastguard Worker out,
4426*795d594fSAndroid Build Coastguard Worker /* offset= */ kLinkTimeOffsetPlaceholderLow,
4427*795d594fSAndroid Build Coastguard Worker read_barrier_option,
4428*795d594fSAndroid Build Coastguard Worker &info_low->label);
4429*795d594fSAndroid Build Coastguard Worker generate_null_check = true;
4430*795d594fSAndroid Build Coastguard Worker break;
4431*795d594fSAndroid Build Coastguard Worker }
4432*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kJitBootImageAddress: {
4433*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
4434*795d594fSAndroid Build Coastguard Worker uint32_t address = reinterpret_cast32<uint32_t>(instruction->GetClass().Get());
4435*795d594fSAndroid Build Coastguard Worker DCHECK_NE(address, 0u);
4436*795d594fSAndroid Build Coastguard Worker __ Loadwu(out, codegen_->DeduplicateBootImageAddressLiteral(address));
4437*795d594fSAndroid Build Coastguard Worker break;
4438*795d594fSAndroid Build Coastguard Worker }
4439*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kJitTableAddress:
4440*795d594fSAndroid Build Coastguard Worker __ Loadwu(out, codegen_->DeduplicateJitClassLiteral(instruction->GetDexFile(),
4441*795d594fSAndroid Build Coastguard Worker instruction->GetTypeIndex(),
4442*795d594fSAndroid Build Coastguard Worker instruction->GetClass()));
4443*795d594fSAndroid Build Coastguard Worker codegen_->GenerateGcRootFieldLoad(
4444*795d594fSAndroid Build Coastguard Worker instruction, out_loc, out, /* offset= */ 0, read_barrier_option);
4445*795d594fSAndroid Build Coastguard Worker break;
4446*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kRuntimeCall:
4447*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kInvalid:
4448*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "UNREACHABLE";
4449*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
4450*795d594fSAndroid Build Coastguard Worker }
4451*795d594fSAndroid Build Coastguard Worker
4452*795d594fSAndroid Build Coastguard Worker if (generate_null_check || instruction->MustGenerateClinitCheck()) {
4453*795d594fSAndroid Build Coastguard Worker DCHECK(instruction->CanCallRuntime());
4454*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path =
4455*795d594fSAndroid Build Coastguard Worker new (codegen_->GetScopedAllocator()) LoadClassSlowPathRISCV64(instruction, instruction);
4456*795d594fSAndroid Build Coastguard Worker codegen_->AddSlowPath(slow_path);
4457*795d594fSAndroid Build Coastguard Worker if (generate_null_check) {
4458*795d594fSAndroid Build Coastguard Worker __ Beqz(out, slow_path->GetEntryLabel());
4459*795d594fSAndroid Build Coastguard Worker }
4460*795d594fSAndroid Build Coastguard Worker if (instruction->MustGenerateClinitCheck()) {
4461*795d594fSAndroid Build Coastguard Worker GenerateClassInitializationCheck(slow_path, out);
4462*795d594fSAndroid Build Coastguard Worker } else {
4463*795d594fSAndroid Build Coastguard Worker __ Bind(slow_path->GetExitLabel());
4464*795d594fSAndroid Build Coastguard Worker }
4465*795d594fSAndroid Build Coastguard Worker }
4466*795d594fSAndroid Build Coastguard Worker }
4467*795d594fSAndroid Build Coastguard Worker
VisitLoadException(HLoadException * instruction)4468*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitLoadException(HLoadException* instruction) {
4469*795d594fSAndroid Build Coastguard Worker LocationSummary* locations =
4470*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, LocationSummary::kNoCall);
4471*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister());
4472*795d594fSAndroid Build Coastguard Worker }
4473*795d594fSAndroid Build Coastguard Worker
VisitLoadException(HLoadException * instruction)4474*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitLoadException(HLoadException* instruction) {
4475*795d594fSAndroid Build Coastguard Worker XRegister out = instruction->GetLocations()->Out().AsRegister<XRegister>();
4476*795d594fSAndroid Build Coastguard Worker __ Loadwu(out, TR, GetExceptionTlsOffset());
4477*795d594fSAndroid Build Coastguard Worker }
4478*795d594fSAndroid Build Coastguard Worker
VisitLoadMethodHandle(HLoadMethodHandle * instruction)4479*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitLoadMethodHandle(HLoadMethodHandle* instruction) {
4480*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
4481*795d594fSAndroid Build Coastguard Worker Location loc = Location::RegisterLocation(calling_convention.GetRegisterAt(0));
4482*795d594fSAndroid Build Coastguard Worker CodeGenerator::CreateLoadMethodHandleRuntimeCallLocationSummary(instruction, loc, loc);
4483*795d594fSAndroid Build Coastguard Worker }
4484*795d594fSAndroid Build Coastguard Worker
VisitLoadMethodHandle(HLoadMethodHandle * instruction)4485*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitLoadMethodHandle(HLoadMethodHandle* instruction) {
4486*795d594fSAndroid Build Coastguard Worker codegen_->GenerateLoadMethodHandleRuntimeCall(instruction);
4487*795d594fSAndroid Build Coastguard Worker }
4488*795d594fSAndroid Build Coastguard Worker
VisitLoadMethodType(HLoadMethodType * instruction)4489*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitLoadMethodType(HLoadMethodType* instruction) {
4490*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
4491*795d594fSAndroid Build Coastguard Worker Location loc = Location::RegisterLocation(calling_convention.GetRegisterAt(0));
4492*795d594fSAndroid Build Coastguard Worker CodeGenerator::CreateLoadMethodTypeRuntimeCallLocationSummary(instruction, loc, loc);
4493*795d594fSAndroid Build Coastguard Worker }
4494*795d594fSAndroid Build Coastguard Worker
VisitLoadMethodType(HLoadMethodType * instruction)4495*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitLoadMethodType(HLoadMethodType* instruction) {
4496*795d594fSAndroid Build Coastguard Worker codegen_->GenerateLoadMethodTypeRuntimeCall(instruction);
4497*795d594fSAndroid Build Coastguard Worker }
4498*795d594fSAndroid Build Coastguard Worker
VisitLoadString(HLoadString * instruction)4499*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitLoadString(HLoadString* instruction) {
4500*795d594fSAndroid Build Coastguard Worker HLoadString::LoadKind load_kind = instruction->GetLoadKind();
4501*795d594fSAndroid Build Coastguard Worker LocationSummary::CallKind call_kind = codegen_->GetLoadStringCallKind(instruction);
4502*795d594fSAndroid Build Coastguard Worker LocationSummary* locations =
4503*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, call_kind);
4504*795d594fSAndroid Build Coastguard Worker if (load_kind == HLoadString::LoadKind::kRuntimeCall) {
4505*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
4506*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(DataType::Type::kReference, instruction->GetType());
4507*795d594fSAndroid Build Coastguard Worker locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kReference));
4508*795d594fSAndroid Build Coastguard Worker } else {
4509*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister());
4510*795d594fSAndroid Build Coastguard Worker if (load_kind == HLoadString::LoadKind::kBssEntry) {
4511*795d594fSAndroid Build Coastguard Worker if (codegen_->EmitNonBakerReadBarrier()) {
4512*795d594fSAndroid Build Coastguard Worker // For non-Baker read barriers we have a temp-clobbering call.
4513*795d594fSAndroid Build Coastguard Worker } else {
4514*795d594fSAndroid Build Coastguard Worker // Rely on the pResolveString and marking to save everything we need.
4515*795d594fSAndroid Build Coastguard Worker locations->SetCustomSlowPathCallerSaves(OneRegInReferenceOutSaveEverythingCallerSaves());
4516*795d594fSAndroid Build Coastguard Worker }
4517*795d594fSAndroid Build Coastguard Worker }
4518*795d594fSAndroid Build Coastguard Worker }
4519*795d594fSAndroid Build Coastguard Worker }
4520*795d594fSAndroid Build Coastguard Worker
4521*795d594fSAndroid Build Coastguard Worker // NO_THREAD_SAFETY_ANALYSIS as we manipulate handles whose internal object we know does not
4522*795d594fSAndroid Build Coastguard Worker // move.
VisitLoadString(HLoadString * instruction)4523*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitLoadString(HLoadString* instruction)
4524*795d594fSAndroid Build Coastguard Worker NO_THREAD_SAFETY_ANALYSIS {
4525*795d594fSAndroid Build Coastguard Worker HLoadString::LoadKind load_kind = instruction->GetLoadKind();
4526*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
4527*795d594fSAndroid Build Coastguard Worker Location out_loc = locations->Out();
4528*795d594fSAndroid Build Coastguard Worker XRegister out = out_loc.AsRegister<XRegister>();
4529*795d594fSAndroid Build Coastguard Worker
4530*795d594fSAndroid Build Coastguard Worker switch (load_kind) {
4531*795d594fSAndroid Build Coastguard Worker case HLoadString::LoadKind::kBootImageLinkTimePcRelative: {
4532*795d594fSAndroid Build Coastguard Worker DCHECK(codegen_->GetCompilerOptions().IsBootImage() ||
4533*795d594fSAndroid Build Coastguard Worker codegen_->GetCompilerOptions().IsBootImageExtension());
4534*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* info_high = codegen_->NewBootImageStringPatch(
4535*795d594fSAndroid Build Coastguard Worker instruction->GetDexFile(), instruction->GetStringIndex());
4536*795d594fSAndroid Build Coastguard Worker codegen_->EmitPcRelativeAuipcPlaceholder(info_high, out);
4537*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* info_low = codegen_->NewBootImageStringPatch(
4538*795d594fSAndroid Build Coastguard Worker instruction->GetDexFile(), instruction->GetStringIndex(), info_high);
4539*795d594fSAndroid Build Coastguard Worker codegen_->EmitPcRelativeAddiPlaceholder(info_low, out, out);
4540*795d594fSAndroid Build Coastguard Worker return;
4541*795d594fSAndroid Build Coastguard Worker }
4542*795d594fSAndroid Build Coastguard Worker case HLoadString::LoadKind::kBootImageRelRo: {
4543*795d594fSAndroid Build Coastguard Worker DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
4544*795d594fSAndroid Build Coastguard Worker uint32_t boot_image_offset = codegen_->GetBootImageOffset(instruction);
4545*795d594fSAndroid Build Coastguard Worker codegen_->LoadBootImageRelRoEntry(out, boot_image_offset);
4546*795d594fSAndroid Build Coastguard Worker return;
4547*795d594fSAndroid Build Coastguard Worker }
4548*795d594fSAndroid Build Coastguard Worker case HLoadString::LoadKind::kBssEntry: {
4549*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* info_high = codegen_->NewStringBssEntryPatch(
4550*795d594fSAndroid Build Coastguard Worker instruction->GetDexFile(), instruction->GetStringIndex());
4551*795d594fSAndroid Build Coastguard Worker codegen_->EmitPcRelativeAuipcPlaceholder(info_high, out);
4552*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* info_low = codegen_->NewStringBssEntryPatch(
4553*795d594fSAndroid Build Coastguard Worker instruction->GetDexFile(), instruction->GetStringIndex(), info_high);
4554*795d594fSAndroid Build Coastguard Worker codegen_->GenerateGcRootFieldLoad(instruction,
4555*795d594fSAndroid Build Coastguard Worker out_loc,
4556*795d594fSAndroid Build Coastguard Worker out,
4557*795d594fSAndroid Build Coastguard Worker /* offset= */ kLinkTimeOffsetPlaceholderLow,
4558*795d594fSAndroid Build Coastguard Worker codegen_->GetCompilerReadBarrierOption(),
4559*795d594fSAndroid Build Coastguard Worker &info_low->label);
4560*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path =
4561*795d594fSAndroid Build Coastguard Worker new (codegen_->GetScopedAllocator()) LoadStringSlowPathRISCV64(instruction);
4562*795d594fSAndroid Build Coastguard Worker codegen_->AddSlowPath(slow_path);
4563*795d594fSAndroid Build Coastguard Worker __ Beqz(out, slow_path->GetEntryLabel());
4564*795d594fSAndroid Build Coastguard Worker __ Bind(slow_path->GetExitLabel());
4565*795d594fSAndroid Build Coastguard Worker return;
4566*795d594fSAndroid Build Coastguard Worker }
4567*795d594fSAndroid Build Coastguard Worker case HLoadString::LoadKind::kJitBootImageAddress: {
4568*795d594fSAndroid Build Coastguard Worker uint32_t address = reinterpret_cast32<uint32_t>(instruction->GetString().Get());
4569*795d594fSAndroid Build Coastguard Worker DCHECK_NE(address, 0u);
4570*795d594fSAndroid Build Coastguard Worker __ Loadwu(out, codegen_->DeduplicateBootImageAddressLiteral(address));
4571*795d594fSAndroid Build Coastguard Worker return;
4572*795d594fSAndroid Build Coastguard Worker }
4573*795d594fSAndroid Build Coastguard Worker case HLoadString::LoadKind::kJitTableAddress:
4574*795d594fSAndroid Build Coastguard Worker __ Loadwu(
4575*795d594fSAndroid Build Coastguard Worker out,
4576*795d594fSAndroid Build Coastguard Worker codegen_->DeduplicateJitStringLiteral(
4577*795d594fSAndroid Build Coastguard Worker instruction->GetDexFile(), instruction->GetStringIndex(), instruction->GetString()));
4578*795d594fSAndroid Build Coastguard Worker codegen_->GenerateGcRootFieldLoad(
4579*795d594fSAndroid Build Coastguard Worker instruction, out_loc, out, 0, codegen_->GetCompilerReadBarrierOption());
4580*795d594fSAndroid Build Coastguard Worker return;
4581*795d594fSAndroid Build Coastguard Worker default:
4582*795d594fSAndroid Build Coastguard Worker break;
4583*795d594fSAndroid Build Coastguard Worker }
4584*795d594fSAndroid Build Coastguard Worker
4585*795d594fSAndroid Build Coastguard Worker DCHECK(load_kind == HLoadString::LoadKind::kRuntimeCall);
4586*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
4587*795d594fSAndroid Build Coastguard Worker DCHECK(calling_convention.GetReturnLocation(DataType::Type::kReference).Equals(out_loc));
4588*795d594fSAndroid Build Coastguard Worker __ LoadConst32(calling_convention.GetRegisterAt(0), instruction->GetStringIndex().index_);
4589*795d594fSAndroid Build Coastguard Worker codegen_->InvokeRuntime(kQuickResolveString, instruction, instruction->GetDexPc());
4590*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
4591*795d594fSAndroid Build Coastguard Worker }
4592*795d594fSAndroid Build Coastguard Worker
VisitLongConstant(HLongConstant * instruction)4593*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitLongConstant(HLongConstant* instruction) {
4594*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
4595*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::ConstantLocation(instruction));
4596*795d594fSAndroid Build Coastguard Worker }
4597*795d594fSAndroid Build Coastguard Worker
VisitLongConstant(HLongConstant * instruction)4598*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitLongConstant(
4599*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] HLongConstant* instruction) {
4600*795d594fSAndroid Build Coastguard Worker // Will be generated at use site.
4601*795d594fSAndroid Build Coastguard Worker }
4602*795d594fSAndroid Build Coastguard Worker
VisitMax(HMax * instruction)4603*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitMax(HMax* instruction) {
4604*795d594fSAndroid Build Coastguard Worker HandleBinaryOp(instruction);
4605*795d594fSAndroid Build Coastguard Worker }
4606*795d594fSAndroid Build Coastguard Worker
VisitMax(HMax * instruction)4607*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitMax(HMax* instruction) {
4608*795d594fSAndroid Build Coastguard Worker HandleBinaryOp(instruction);
4609*795d594fSAndroid Build Coastguard Worker }
4610*795d594fSAndroid Build Coastguard Worker
VisitMemoryBarrier(HMemoryBarrier * instruction)4611*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitMemoryBarrier(HMemoryBarrier* instruction) {
4612*795d594fSAndroid Build Coastguard Worker instruction->SetLocations(nullptr);
4613*795d594fSAndroid Build Coastguard Worker }
4614*795d594fSAndroid Build Coastguard Worker
VisitMemoryBarrier(HMemoryBarrier * instruction)4615*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitMemoryBarrier(HMemoryBarrier* instruction) {
4616*795d594fSAndroid Build Coastguard Worker codegen_->GenerateMemoryBarrier(instruction->GetBarrierKind());
4617*795d594fSAndroid Build Coastguard Worker }
4618*795d594fSAndroid Build Coastguard Worker
VisitMethodEntryHook(HMethodEntryHook * instruction)4619*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitMethodEntryHook(HMethodEntryHook* instruction) {
4620*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, LocationSummary::kCallOnSlowPath);
4621*795d594fSAndroid Build Coastguard Worker }
4622*795d594fSAndroid Build Coastguard Worker
VisitMethodEntryHook(HMethodEntryHook * instruction)4623*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitMethodEntryHook(HMethodEntryHook* instruction) {
4624*795d594fSAndroid Build Coastguard Worker DCHECK(codegen_->GetCompilerOptions().IsJitCompiler() && GetGraph()->IsDebuggable());
4625*795d594fSAndroid Build Coastguard Worker DCHECK(codegen_->RequiresCurrentMethod());
4626*795d594fSAndroid Build Coastguard Worker GenerateMethodEntryExitHook(instruction);
4627*795d594fSAndroid Build Coastguard Worker }
4628*795d594fSAndroid Build Coastguard Worker
VisitMethodExitHook(HMethodExitHook * instruction)4629*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitMethodExitHook(HMethodExitHook* instruction) {
4630*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator())
4631*795d594fSAndroid Build Coastguard Worker LocationSummary(instruction, LocationSummary::kCallOnSlowPath);
4632*795d594fSAndroid Build Coastguard Worker DataType::Type return_type = instruction->InputAt(0)->GetType();
4633*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Riscv64ReturnLocation(return_type));
4634*795d594fSAndroid Build Coastguard Worker }
4635*795d594fSAndroid Build Coastguard Worker
VisitMethodExitHook(HMethodExitHook * instruction)4636*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitMethodExitHook(HMethodExitHook* instruction) {
4637*795d594fSAndroid Build Coastguard Worker DCHECK(codegen_->GetCompilerOptions().IsJitCompiler() && GetGraph()->IsDebuggable());
4638*795d594fSAndroid Build Coastguard Worker DCHECK(codegen_->RequiresCurrentMethod());
4639*795d594fSAndroid Build Coastguard Worker GenerateMethodEntryExitHook(instruction);
4640*795d594fSAndroid Build Coastguard Worker }
4641*795d594fSAndroid Build Coastguard Worker
VisitMin(HMin * instruction)4642*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitMin(HMin* instruction) {
4643*795d594fSAndroid Build Coastguard Worker HandleBinaryOp(instruction);
4644*795d594fSAndroid Build Coastguard Worker }
4645*795d594fSAndroid Build Coastguard Worker
VisitMin(HMin * instruction)4646*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitMin(HMin* instruction) {
4647*795d594fSAndroid Build Coastguard Worker HandleBinaryOp(instruction);
4648*795d594fSAndroid Build Coastguard Worker }
4649*795d594fSAndroid Build Coastguard Worker
VisitMonitorOperation(HMonitorOperation * instruction)4650*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitMonitorOperation(HMonitorOperation* instruction) {
4651*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(
4652*795d594fSAndroid Build Coastguard Worker instruction, LocationSummary::kCallOnMainOnly);
4653*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
4654*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
4655*795d594fSAndroid Build Coastguard Worker }
4656*795d594fSAndroid Build Coastguard Worker
VisitMonitorOperation(HMonitorOperation * instruction)4657*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitMonitorOperation(HMonitorOperation* instruction) {
4658*795d594fSAndroid Build Coastguard Worker codegen_->InvokeRuntime(instruction->IsEnter() ? kQuickLockObject : kQuickUnlockObject,
4659*795d594fSAndroid Build Coastguard Worker instruction,
4660*795d594fSAndroid Build Coastguard Worker instruction->GetDexPc());
4661*795d594fSAndroid Build Coastguard Worker if (instruction->IsEnter()) {
4662*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickLockObject, void, mirror::Object*>();
4663*795d594fSAndroid Build Coastguard Worker } else {
4664*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickUnlockObject, void, mirror::Object*>();
4665*795d594fSAndroid Build Coastguard Worker }
4666*795d594fSAndroid Build Coastguard Worker }
4667*795d594fSAndroid Build Coastguard Worker
VisitMul(HMul * instruction)4668*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitMul(HMul* instruction) {
4669*795d594fSAndroid Build Coastguard Worker LocationSummary* locations =
4670*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, LocationSummary::kNoCall);
4671*795d594fSAndroid Build Coastguard Worker switch (instruction->GetResultType()) {
4672*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
4673*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
4674*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
4675*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RequiresRegister());
4676*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
4677*795d594fSAndroid Build Coastguard Worker break;
4678*795d594fSAndroid Build Coastguard Worker
4679*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
4680*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
4681*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresFpuRegister());
4682*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RequiresFpuRegister());
4683*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
4684*795d594fSAndroid Build Coastguard Worker break;
4685*795d594fSAndroid Build Coastguard Worker
4686*795d594fSAndroid Build Coastguard Worker default:
4687*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected mul type " << instruction->GetResultType();
4688*795d594fSAndroid Build Coastguard Worker }
4689*795d594fSAndroid Build Coastguard Worker }
4690*795d594fSAndroid Build Coastguard Worker
VisitMul(HMul * instruction)4691*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitMul(HMul* instruction) {
4692*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
4693*795d594fSAndroid Build Coastguard Worker switch (instruction->GetResultType()) {
4694*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
4695*795d594fSAndroid Build Coastguard Worker __ Mulw(locations->Out().AsRegister<XRegister>(),
4696*795d594fSAndroid Build Coastguard Worker locations->InAt(0).AsRegister<XRegister>(),
4697*795d594fSAndroid Build Coastguard Worker locations->InAt(1).AsRegister<XRegister>());
4698*795d594fSAndroid Build Coastguard Worker break;
4699*795d594fSAndroid Build Coastguard Worker
4700*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
4701*795d594fSAndroid Build Coastguard Worker __ Mul(locations->Out().AsRegister<XRegister>(),
4702*795d594fSAndroid Build Coastguard Worker locations->InAt(0).AsRegister<XRegister>(),
4703*795d594fSAndroid Build Coastguard Worker locations->InAt(1).AsRegister<XRegister>());
4704*795d594fSAndroid Build Coastguard Worker break;
4705*795d594fSAndroid Build Coastguard Worker
4706*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
4707*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
4708*795d594fSAndroid Build Coastguard Worker FMul(locations->Out().AsFpuRegister<FRegister>(),
4709*795d594fSAndroid Build Coastguard Worker locations->InAt(0).AsFpuRegister<FRegister>(),
4710*795d594fSAndroid Build Coastguard Worker locations->InAt(1).AsFpuRegister<FRegister>(),
4711*795d594fSAndroid Build Coastguard Worker instruction->GetResultType());
4712*795d594fSAndroid Build Coastguard Worker break;
4713*795d594fSAndroid Build Coastguard Worker
4714*795d594fSAndroid Build Coastguard Worker default:
4715*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected mul type " << instruction->GetResultType();
4716*795d594fSAndroid Build Coastguard Worker }
4717*795d594fSAndroid Build Coastguard Worker }
4718*795d594fSAndroid Build Coastguard Worker
VisitNeg(HNeg * instruction)4719*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitNeg(HNeg* instruction) {
4720*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
4721*795d594fSAndroid Build Coastguard Worker switch (instruction->GetResultType()) {
4722*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
4723*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
4724*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
4725*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
4726*795d594fSAndroid Build Coastguard Worker break;
4727*795d594fSAndroid Build Coastguard Worker
4728*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
4729*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
4730*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresFpuRegister());
4731*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
4732*795d594fSAndroid Build Coastguard Worker break;
4733*795d594fSAndroid Build Coastguard Worker
4734*795d594fSAndroid Build Coastguard Worker default:
4735*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected neg type " << instruction->GetResultType();
4736*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
4737*795d594fSAndroid Build Coastguard Worker }
4738*795d594fSAndroid Build Coastguard Worker }
4739*795d594fSAndroid Build Coastguard Worker
VisitNeg(HNeg * instruction)4740*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitNeg(HNeg* instruction) {
4741*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
4742*795d594fSAndroid Build Coastguard Worker switch (instruction->GetResultType()) {
4743*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
4744*795d594fSAndroid Build Coastguard Worker __ NegW(locations->Out().AsRegister<XRegister>(), locations->InAt(0).AsRegister<XRegister>());
4745*795d594fSAndroid Build Coastguard Worker break;
4746*795d594fSAndroid Build Coastguard Worker
4747*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
4748*795d594fSAndroid Build Coastguard Worker __ Neg(locations->Out().AsRegister<XRegister>(), locations->InAt(0).AsRegister<XRegister>());
4749*795d594fSAndroid Build Coastguard Worker break;
4750*795d594fSAndroid Build Coastguard Worker
4751*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
4752*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64:
4753*795d594fSAndroid Build Coastguard Worker FNeg(locations->Out().AsFpuRegister<FRegister>(),
4754*795d594fSAndroid Build Coastguard Worker locations->InAt(0).AsFpuRegister<FRegister>(),
4755*795d594fSAndroid Build Coastguard Worker instruction->GetResultType());
4756*795d594fSAndroid Build Coastguard Worker break;
4757*795d594fSAndroid Build Coastguard Worker
4758*795d594fSAndroid Build Coastguard Worker default:
4759*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected neg type " << instruction->GetResultType();
4760*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
4761*795d594fSAndroid Build Coastguard Worker }
4762*795d594fSAndroid Build Coastguard Worker }
4763*795d594fSAndroid Build Coastguard Worker
VisitNewArray(HNewArray * instruction)4764*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitNewArray(HNewArray* instruction) {
4765*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator())
4766*795d594fSAndroid Build Coastguard Worker LocationSummary(instruction, LocationSummary::kCallOnMainOnly);
4767*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
4768*795d594fSAndroid Build Coastguard Worker locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kReference));
4769*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
4770*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
4771*795d594fSAndroid Build Coastguard Worker }
4772*795d594fSAndroid Build Coastguard Worker
VisitNewArray(HNewArray * instruction)4773*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitNewArray(HNewArray* instruction) {
4774*795d594fSAndroid Build Coastguard Worker QuickEntrypointEnum entrypoint = CodeGenerator::GetArrayAllocationEntrypoint(instruction);
4775*795d594fSAndroid Build Coastguard Worker codegen_->InvokeRuntime(entrypoint, instruction, instruction->GetDexPc());
4776*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickAllocArrayResolved, void*, mirror::Class*, int32_t>();
4777*795d594fSAndroid Build Coastguard Worker DCHECK(!codegen_->IsLeafMethod());
4778*795d594fSAndroid Build Coastguard Worker }
4779*795d594fSAndroid Build Coastguard Worker
VisitNewInstance(HNewInstance * instruction)4780*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitNewInstance(HNewInstance* instruction) {
4781*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(
4782*795d594fSAndroid Build Coastguard Worker instruction, LocationSummary::kCallOnMainOnly);
4783*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
4784*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
4785*795d594fSAndroid Build Coastguard Worker locations->SetOut(calling_convention.GetReturnLocation(DataType::Type::kReference));
4786*795d594fSAndroid Build Coastguard Worker }
4787*795d594fSAndroid Build Coastguard Worker
VisitNewInstance(HNewInstance * instruction)4788*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitNewInstance(HNewInstance* instruction) {
4789*795d594fSAndroid Build Coastguard Worker codegen_->InvokeRuntime(instruction->GetEntrypoint(), instruction, instruction->GetDexPc());
4790*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
4791*795d594fSAndroid Build Coastguard Worker }
4792*795d594fSAndroid Build Coastguard Worker
VisitNop(HNop * instruction)4793*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitNop(HNop* instruction) {
4794*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction);
4795*795d594fSAndroid Build Coastguard Worker }
4796*795d594fSAndroid Build Coastguard Worker
VisitNop(HNop * instruction)4797*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitNop([[maybe_unused]] HNop* instruction) {
4798*795d594fSAndroid Build Coastguard Worker // The environment recording already happened in CodeGenerator::Compile.
4799*795d594fSAndroid Build Coastguard Worker }
4800*795d594fSAndroid Build Coastguard Worker
VisitNot(HNot * instruction)4801*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitNot(HNot* instruction) {
4802*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
4803*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
4804*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
4805*795d594fSAndroid Build Coastguard Worker }
4806*795d594fSAndroid Build Coastguard Worker
VisitNot(HNot * instruction)4807*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitNot(HNot* instruction) {
4808*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
4809*795d594fSAndroid Build Coastguard Worker switch (instruction->GetResultType()) {
4810*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
4811*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
4812*795d594fSAndroid Build Coastguard Worker __ Not(locations->Out().AsRegister<XRegister>(), locations->InAt(0).AsRegister<XRegister>());
4813*795d594fSAndroid Build Coastguard Worker break;
4814*795d594fSAndroid Build Coastguard Worker
4815*795d594fSAndroid Build Coastguard Worker default:
4816*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected type for not operation " << instruction->GetResultType();
4817*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
4818*795d594fSAndroid Build Coastguard Worker }
4819*795d594fSAndroid Build Coastguard Worker }
4820*795d594fSAndroid Build Coastguard Worker
VisitNotEqual(HNotEqual * instruction)4821*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitNotEqual(HNotEqual* instruction) {
4822*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
4823*795d594fSAndroid Build Coastguard Worker }
4824*795d594fSAndroid Build Coastguard Worker
VisitNotEqual(HNotEqual * instruction)4825*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitNotEqual(HNotEqual* instruction) {
4826*795d594fSAndroid Build Coastguard Worker HandleCondition(instruction);
4827*795d594fSAndroid Build Coastguard Worker }
4828*795d594fSAndroid Build Coastguard Worker
VisitNullConstant(HNullConstant * instruction)4829*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitNullConstant(HNullConstant* instruction) {
4830*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
4831*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::ConstantLocation(instruction));
4832*795d594fSAndroid Build Coastguard Worker }
4833*795d594fSAndroid Build Coastguard Worker
VisitNullConstant(HNullConstant * instruction)4834*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitNullConstant(
4835*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] HNullConstant* instruction) {
4836*795d594fSAndroid Build Coastguard Worker // Will be generated at use site.
4837*795d594fSAndroid Build Coastguard Worker }
4838*795d594fSAndroid Build Coastguard Worker
VisitNullCheck(HNullCheck * instruction)4839*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitNullCheck(HNullCheck* instruction) {
4840*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction);
4841*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
4842*795d594fSAndroid Build Coastguard Worker }
4843*795d594fSAndroid Build Coastguard Worker
VisitNullCheck(HNullCheck * instruction)4844*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitNullCheck(HNullCheck* instruction) {
4845*795d594fSAndroid Build Coastguard Worker codegen_->GenerateNullCheck(instruction);
4846*795d594fSAndroid Build Coastguard Worker }
4847*795d594fSAndroid Build Coastguard Worker
VisitOr(HOr * instruction)4848*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitOr(HOr* instruction) {
4849*795d594fSAndroid Build Coastguard Worker HandleBinaryOp(instruction);
4850*795d594fSAndroid Build Coastguard Worker }
4851*795d594fSAndroid Build Coastguard Worker
VisitOr(HOr * instruction)4852*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitOr(HOr* instruction) {
4853*795d594fSAndroid Build Coastguard Worker HandleBinaryOp(instruction);
4854*795d594fSAndroid Build Coastguard Worker }
4855*795d594fSAndroid Build Coastguard Worker
VisitPackedSwitch(HPackedSwitch * instruction)4856*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitPackedSwitch(HPackedSwitch* instruction) {
4857*795d594fSAndroid Build Coastguard Worker LocationSummary* locations =
4858*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, LocationSummary::kNoCall);
4859*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
4860*795d594fSAndroid Build Coastguard Worker }
4861*795d594fSAndroid Build Coastguard Worker
VisitPackedSwitch(HPackedSwitch * instruction)4862*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitPackedSwitch(HPackedSwitch* instruction) {
4863*795d594fSAndroid Build Coastguard Worker int32_t lower_bound = instruction->GetStartValue();
4864*795d594fSAndroid Build Coastguard Worker uint32_t num_entries = instruction->GetNumEntries();
4865*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
4866*795d594fSAndroid Build Coastguard Worker XRegister value = locations->InAt(0).AsRegister<XRegister>();
4867*795d594fSAndroid Build Coastguard Worker HBasicBlock* switch_block = instruction->GetBlock();
4868*795d594fSAndroid Build Coastguard Worker HBasicBlock* default_block = instruction->GetDefaultBlock();
4869*795d594fSAndroid Build Coastguard Worker
4870*795d594fSAndroid Build Coastguard Worker // Prepare a temporary register and an adjusted zero-based value.
4871*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
4872*795d594fSAndroid Build Coastguard Worker XRegister temp = srs.AllocateXRegister();
4873*795d594fSAndroid Build Coastguard Worker XRegister adjusted = value;
4874*795d594fSAndroid Build Coastguard Worker if (lower_bound != 0) {
4875*795d594fSAndroid Build Coastguard Worker adjusted = temp;
4876*795d594fSAndroid Build Coastguard Worker __ AddConst32(temp, value, -lower_bound);
4877*795d594fSAndroid Build Coastguard Worker }
4878*795d594fSAndroid Build Coastguard Worker
4879*795d594fSAndroid Build Coastguard Worker // Jump to the default block if the index is out of the packed switch value range.
4880*795d594fSAndroid Build Coastguard Worker // Note: We could save one instruction for `num_entries == 1` with BNEZ but the
4881*795d594fSAndroid Build Coastguard Worker // `HInstructionBuilder` transforms that case to an `HIf`, so let's keep the code simple.
4882*795d594fSAndroid Build Coastguard Worker CHECK_NE(num_entries, 0u); // `HInstructionBuilder` creates a `HGoto` for empty packed-switch.
4883*795d594fSAndroid Build Coastguard Worker {
4884*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs2(GetAssembler());
4885*795d594fSAndroid Build Coastguard Worker XRegister temp2 = srs2.AllocateXRegister();
4886*795d594fSAndroid Build Coastguard Worker __ LoadConst32(temp2, num_entries);
4887*795d594fSAndroid Build Coastguard Worker __ Bgeu(adjusted, temp2, codegen_->GetLabelOf(default_block)); // Can clobber `TMP` if taken.
4888*795d594fSAndroid Build Coastguard Worker }
4889*795d594fSAndroid Build Coastguard Worker
4890*795d594fSAndroid Build Coastguard Worker if (num_entries >= kPackedSwitchCompareJumpThreshold) {
4891*795d594fSAndroid Build Coastguard Worker GenTableBasedPackedSwitch(adjusted, temp, num_entries, switch_block);
4892*795d594fSAndroid Build Coastguard Worker } else {
4893*795d594fSAndroid Build Coastguard Worker GenPackedSwitchWithCompares(adjusted, temp, num_entries, switch_block);
4894*795d594fSAndroid Build Coastguard Worker }
4895*795d594fSAndroid Build Coastguard Worker }
4896*795d594fSAndroid Build Coastguard Worker
VisitParallelMove(HParallelMove * instruction)4897*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitParallelMove([[maybe_unused]] HParallelMove* instruction) {
4898*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unreachable";
4899*795d594fSAndroid Build Coastguard Worker }
4900*795d594fSAndroid Build Coastguard Worker
VisitParallelMove(HParallelMove * instruction)4901*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitParallelMove(HParallelMove* instruction) {
4902*795d594fSAndroid Build Coastguard Worker if (instruction->GetNext()->IsSuspendCheck() &&
4903*795d594fSAndroid Build Coastguard Worker instruction->GetBlock()->GetLoopInformation() != nullptr) {
4904*795d594fSAndroid Build Coastguard Worker HSuspendCheck* suspend_check = instruction->GetNext()->AsSuspendCheck();
4905*795d594fSAndroid Build Coastguard Worker // The back edge will generate the suspend check.
4906*795d594fSAndroid Build Coastguard Worker codegen_->ClearSpillSlotsFromLoopPhisInStackMap(suspend_check, instruction);
4907*795d594fSAndroid Build Coastguard Worker }
4908*795d594fSAndroid Build Coastguard Worker
4909*795d594fSAndroid Build Coastguard Worker codegen_->GetMoveResolver()->EmitNativeCode(instruction);
4910*795d594fSAndroid Build Coastguard Worker }
4911*795d594fSAndroid Build Coastguard Worker
VisitParameterValue(HParameterValue * instruction)4912*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitParameterValue(HParameterValue* instruction) {
4913*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
4914*795d594fSAndroid Build Coastguard Worker Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
4915*795d594fSAndroid Build Coastguard Worker if (location.IsStackSlot()) {
4916*795d594fSAndroid Build Coastguard Worker location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
4917*795d594fSAndroid Build Coastguard Worker } else if (location.IsDoubleStackSlot()) {
4918*795d594fSAndroid Build Coastguard Worker location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
4919*795d594fSAndroid Build Coastguard Worker }
4920*795d594fSAndroid Build Coastguard Worker locations->SetOut(location);
4921*795d594fSAndroid Build Coastguard Worker }
4922*795d594fSAndroid Build Coastguard Worker
VisitParameterValue(HParameterValue * instruction)4923*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitParameterValue(
4924*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] HParameterValue* instruction) {
4925*795d594fSAndroid Build Coastguard Worker // Nothing to do, the parameter is already at its location.
4926*795d594fSAndroid Build Coastguard Worker }
4927*795d594fSAndroid Build Coastguard Worker
VisitPhi(HPhi * instruction)4928*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitPhi(HPhi* instruction) {
4929*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
4930*795d594fSAndroid Build Coastguard Worker for (size_t i = 0, e = locations->GetInputCount(); i < e; ++i) {
4931*795d594fSAndroid Build Coastguard Worker locations->SetInAt(i, Location::Any());
4932*795d594fSAndroid Build Coastguard Worker }
4933*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::Any());
4934*795d594fSAndroid Build Coastguard Worker }
4935*795d594fSAndroid Build Coastguard Worker
VisitPhi(HPhi * instruction)4936*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitPhi([[maybe_unused]] HPhi* instruction) {
4937*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unreachable";
4938*795d594fSAndroid Build Coastguard Worker }
4939*795d594fSAndroid Build Coastguard Worker
VisitRem(HRem * instruction)4940*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitRem(HRem* instruction) {
4941*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetResultType();
4942*795d594fSAndroid Build Coastguard Worker LocationSummary::CallKind call_kind =
4943*795d594fSAndroid Build Coastguard Worker DataType::IsFloatingPointType(type) ? LocationSummary::kCallOnMainOnly
4944*795d594fSAndroid Build Coastguard Worker : LocationSummary::kNoCall;
4945*795d594fSAndroid Build Coastguard Worker LocationSummary* locations =
4946*795d594fSAndroid Build Coastguard Worker new (GetGraph()->GetAllocator()) LocationSummary(instruction, call_kind);
4947*795d594fSAndroid Build Coastguard Worker
4948*795d594fSAndroid Build Coastguard Worker switch (type) {
4949*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
4950*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
4951*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
4952*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
4953*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
4954*795d594fSAndroid Build Coastguard Worker break;
4955*795d594fSAndroid Build Coastguard Worker
4956*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
4957*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64: {
4958*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
4959*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0)));
4960*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(1)));
4961*795d594fSAndroid Build Coastguard Worker locations->SetOut(calling_convention.GetReturnLocation(type));
4962*795d594fSAndroid Build Coastguard Worker break;
4963*795d594fSAndroid Build Coastguard Worker }
4964*795d594fSAndroid Build Coastguard Worker
4965*795d594fSAndroid Build Coastguard Worker default:
4966*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected rem type " << type;
4967*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
4968*795d594fSAndroid Build Coastguard Worker }
4969*795d594fSAndroid Build Coastguard Worker }
4970*795d594fSAndroid Build Coastguard Worker
VisitRem(HRem * instruction)4971*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitRem(HRem* instruction) {
4972*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetType();
4973*795d594fSAndroid Build Coastguard Worker
4974*795d594fSAndroid Build Coastguard Worker switch (type) {
4975*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
4976*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
4977*795d594fSAndroid Build Coastguard Worker GenerateDivRemIntegral(instruction);
4978*795d594fSAndroid Build Coastguard Worker break;
4979*795d594fSAndroid Build Coastguard Worker
4980*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat32:
4981*795d594fSAndroid Build Coastguard Worker case DataType::Type::kFloat64: {
4982*795d594fSAndroid Build Coastguard Worker QuickEntrypointEnum entrypoint =
4983*795d594fSAndroid Build Coastguard Worker (type == DataType::Type::kFloat32) ? kQuickFmodf : kQuickFmod;
4984*795d594fSAndroid Build Coastguard Worker codegen_->InvokeRuntime(entrypoint, instruction, instruction->GetDexPc());
4985*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kFloat32) {
4986*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickFmodf, float, float, float>();
4987*795d594fSAndroid Build Coastguard Worker } else {
4988*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickFmod, double, double, double>();
4989*795d594fSAndroid Build Coastguard Worker }
4990*795d594fSAndroid Build Coastguard Worker break;
4991*795d594fSAndroid Build Coastguard Worker }
4992*795d594fSAndroid Build Coastguard Worker default:
4993*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected rem type " << type;
4994*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
4995*795d594fSAndroid Build Coastguard Worker }
4996*795d594fSAndroid Build Coastguard Worker }
4997*795d594fSAndroid Build Coastguard Worker
VisitReturn(HReturn * instruction)4998*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitReturn(HReturn* instruction) {
4999*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
5000*795d594fSAndroid Build Coastguard Worker DataType::Type return_type = instruction->InputAt(0)->GetType();
5001*795d594fSAndroid Build Coastguard Worker DCHECK_NE(return_type, DataType::Type::kVoid);
5002*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Riscv64ReturnLocation(return_type));
5003*795d594fSAndroid Build Coastguard Worker }
5004*795d594fSAndroid Build Coastguard Worker
VisitReturn(HReturn * instruction)5005*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitReturn(HReturn* instruction) {
5006*795d594fSAndroid Build Coastguard Worker if (GetGraph()->IsCompilingOsr()) {
5007*795d594fSAndroid Build Coastguard Worker // To simplify callers of an OSR method, we put a floating point return value
5008*795d594fSAndroid Build Coastguard Worker // in both floating point and core return registers.
5009*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->InputAt(0)->GetType();
5010*795d594fSAndroid Build Coastguard Worker if (DataType::IsFloatingPointType(type)) {
5011*795d594fSAndroid Build Coastguard Worker FMvX(A0, FA0, type);
5012*795d594fSAndroid Build Coastguard Worker }
5013*795d594fSAndroid Build Coastguard Worker }
5014*795d594fSAndroid Build Coastguard Worker codegen_->GenerateFrameExit();
5015*795d594fSAndroid Build Coastguard Worker }
5016*795d594fSAndroid Build Coastguard Worker
VisitReturnVoid(HReturnVoid * instruction)5017*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitReturnVoid(HReturnVoid* instruction) {
5018*795d594fSAndroid Build Coastguard Worker instruction->SetLocations(nullptr);
5019*795d594fSAndroid Build Coastguard Worker }
5020*795d594fSAndroid Build Coastguard Worker
VisitReturnVoid(HReturnVoid * instruction)5021*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitReturnVoid([[maybe_unused]] HReturnVoid* instruction) {
5022*795d594fSAndroid Build Coastguard Worker codegen_->GenerateFrameExit();
5023*795d594fSAndroid Build Coastguard Worker }
5024*795d594fSAndroid Build Coastguard Worker
VisitRol(HRol * instruction)5025*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitRol(HRol* instruction) {
5026*795d594fSAndroid Build Coastguard Worker HandleShift(instruction);
5027*795d594fSAndroid Build Coastguard Worker }
5028*795d594fSAndroid Build Coastguard Worker
VisitRol(HRol * instruction)5029*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitRol(HRol* instruction) {
5030*795d594fSAndroid Build Coastguard Worker HandleShift(instruction);
5031*795d594fSAndroid Build Coastguard Worker }
5032*795d594fSAndroid Build Coastguard Worker
VisitRor(HRor * instruction)5033*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitRor(HRor* instruction) {
5034*795d594fSAndroid Build Coastguard Worker HandleShift(instruction);
5035*795d594fSAndroid Build Coastguard Worker }
5036*795d594fSAndroid Build Coastguard Worker
VisitRor(HRor * instruction)5037*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitRor(HRor* instruction) {
5038*795d594fSAndroid Build Coastguard Worker HandleShift(instruction);
5039*795d594fSAndroid Build Coastguard Worker }
5040*795d594fSAndroid Build Coastguard Worker
VisitShl(HShl * instruction)5041*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitShl(HShl* instruction) {
5042*795d594fSAndroid Build Coastguard Worker HandleShift(instruction);
5043*795d594fSAndroid Build Coastguard Worker }
5044*795d594fSAndroid Build Coastguard Worker
VisitShl(HShl * instruction)5045*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitShl(HShl* instruction) {
5046*795d594fSAndroid Build Coastguard Worker HandleShift(instruction);
5047*795d594fSAndroid Build Coastguard Worker }
5048*795d594fSAndroid Build Coastguard Worker
VisitShr(HShr * instruction)5049*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitShr(HShr* instruction) {
5050*795d594fSAndroid Build Coastguard Worker HandleShift(instruction);
5051*795d594fSAndroid Build Coastguard Worker }
5052*795d594fSAndroid Build Coastguard Worker
VisitShr(HShr * instruction)5053*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitShr(HShr* instruction) {
5054*795d594fSAndroid Build Coastguard Worker HandleShift(instruction);
5055*795d594fSAndroid Build Coastguard Worker }
5056*795d594fSAndroid Build Coastguard Worker
VisitStaticFieldGet(HStaticFieldGet * instruction)5057*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitStaticFieldGet(HStaticFieldGet* instruction) {
5058*795d594fSAndroid Build Coastguard Worker HandleFieldGet(instruction);
5059*795d594fSAndroid Build Coastguard Worker }
5060*795d594fSAndroid Build Coastguard Worker
VisitStaticFieldGet(HStaticFieldGet * instruction)5061*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitStaticFieldGet(HStaticFieldGet* instruction) {
5062*795d594fSAndroid Build Coastguard Worker HandleFieldGet(instruction, instruction->GetFieldInfo());
5063*795d594fSAndroid Build Coastguard Worker }
5064*795d594fSAndroid Build Coastguard Worker
VisitStaticFieldSet(HStaticFieldSet * instruction)5065*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitStaticFieldSet(HStaticFieldSet* instruction) {
5066*795d594fSAndroid Build Coastguard Worker HandleFieldSet(instruction);
5067*795d594fSAndroid Build Coastguard Worker }
5068*795d594fSAndroid Build Coastguard Worker
VisitStaticFieldSet(HStaticFieldSet * instruction)5069*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitStaticFieldSet(HStaticFieldSet* instruction) {
5070*795d594fSAndroid Build Coastguard Worker HandleFieldSet(instruction,
5071*795d594fSAndroid Build Coastguard Worker instruction->GetFieldInfo(),
5072*795d594fSAndroid Build Coastguard Worker instruction->GetValueCanBeNull(),
5073*795d594fSAndroid Build Coastguard Worker instruction->GetWriteBarrierKind());
5074*795d594fSAndroid Build Coastguard Worker }
5075*795d594fSAndroid Build Coastguard Worker
VisitStringBuilderAppend(HStringBuilderAppend * instruction)5076*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitStringBuilderAppend(HStringBuilderAppend* instruction) {
5077*795d594fSAndroid Build Coastguard Worker codegen_->CreateStringBuilderAppendLocations(instruction, Location::RegisterLocation(A0));
5078*795d594fSAndroid Build Coastguard Worker }
5079*795d594fSAndroid Build Coastguard Worker
VisitStringBuilderAppend(HStringBuilderAppend * instruction)5080*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitStringBuilderAppend(HStringBuilderAppend* instruction) {
5081*795d594fSAndroid Build Coastguard Worker __ LoadConst32(A0, instruction->GetFormat()->GetValue());
5082*795d594fSAndroid Build Coastguard Worker codegen_->InvokeRuntime(kQuickStringBuilderAppend, instruction, instruction->GetDexPc());
5083*795d594fSAndroid Build Coastguard Worker }
5084*795d594fSAndroid Build Coastguard Worker
VisitUnresolvedInstanceFieldGet(HUnresolvedInstanceFieldGet * instruction)5085*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitUnresolvedInstanceFieldGet(
5086*795d594fSAndroid Build Coastguard Worker HUnresolvedInstanceFieldGet* instruction) {
5087*795d594fSAndroid Build Coastguard Worker FieldAccessCallingConventionRISCV64 calling_convention;
5088*795d594fSAndroid Build Coastguard Worker codegen_->CreateUnresolvedFieldLocationSummary(
5089*795d594fSAndroid Build Coastguard Worker instruction, instruction->GetFieldType(), calling_convention);
5090*795d594fSAndroid Build Coastguard Worker }
5091*795d594fSAndroid Build Coastguard Worker
VisitUnresolvedInstanceFieldGet(HUnresolvedInstanceFieldGet * instruction)5092*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitUnresolvedInstanceFieldGet(
5093*795d594fSAndroid Build Coastguard Worker HUnresolvedInstanceFieldGet* instruction) {
5094*795d594fSAndroid Build Coastguard Worker FieldAccessCallingConventionRISCV64 calling_convention;
5095*795d594fSAndroid Build Coastguard Worker codegen_->GenerateUnresolvedFieldAccess(instruction,
5096*795d594fSAndroid Build Coastguard Worker instruction->GetFieldType(),
5097*795d594fSAndroid Build Coastguard Worker instruction->GetFieldIndex(),
5098*795d594fSAndroid Build Coastguard Worker instruction->GetDexPc(),
5099*795d594fSAndroid Build Coastguard Worker calling_convention);
5100*795d594fSAndroid Build Coastguard Worker }
5101*795d594fSAndroid Build Coastguard Worker
VisitUnresolvedInstanceFieldSet(HUnresolvedInstanceFieldSet * instruction)5102*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitUnresolvedInstanceFieldSet(
5103*795d594fSAndroid Build Coastguard Worker HUnresolvedInstanceFieldSet* instruction) {
5104*795d594fSAndroid Build Coastguard Worker FieldAccessCallingConventionRISCV64 calling_convention;
5105*795d594fSAndroid Build Coastguard Worker codegen_->CreateUnresolvedFieldLocationSummary(
5106*795d594fSAndroid Build Coastguard Worker instruction, instruction->GetFieldType(), calling_convention);
5107*795d594fSAndroid Build Coastguard Worker }
5108*795d594fSAndroid Build Coastguard Worker
VisitUnresolvedInstanceFieldSet(HUnresolvedInstanceFieldSet * instruction)5109*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitUnresolvedInstanceFieldSet(
5110*795d594fSAndroid Build Coastguard Worker HUnresolvedInstanceFieldSet* instruction) {
5111*795d594fSAndroid Build Coastguard Worker FieldAccessCallingConventionRISCV64 calling_convention;
5112*795d594fSAndroid Build Coastguard Worker codegen_->GenerateUnresolvedFieldAccess(instruction,
5113*795d594fSAndroid Build Coastguard Worker instruction->GetFieldType(),
5114*795d594fSAndroid Build Coastguard Worker instruction->GetFieldIndex(),
5115*795d594fSAndroid Build Coastguard Worker instruction->GetDexPc(),
5116*795d594fSAndroid Build Coastguard Worker calling_convention);
5117*795d594fSAndroid Build Coastguard Worker }
5118*795d594fSAndroid Build Coastguard Worker
VisitUnresolvedStaticFieldGet(HUnresolvedStaticFieldGet * instruction)5119*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitUnresolvedStaticFieldGet(
5120*795d594fSAndroid Build Coastguard Worker HUnresolvedStaticFieldGet* instruction) {
5121*795d594fSAndroid Build Coastguard Worker FieldAccessCallingConventionRISCV64 calling_convention;
5122*795d594fSAndroid Build Coastguard Worker codegen_->CreateUnresolvedFieldLocationSummary(
5123*795d594fSAndroid Build Coastguard Worker instruction, instruction->GetFieldType(), calling_convention);
5124*795d594fSAndroid Build Coastguard Worker }
5125*795d594fSAndroid Build Coastguard Worker
VisitUnresolvedStaticFieldGet(HUnresolvedStaticFieldGet * instruction)5126*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitUnresolvedStaticFieldGet(
5127*795d594fSAndroid Build Coastguard Worker HUnresolvedStaticFieldGet* instruction) {
5128*795d594fSAndroid Build Coastguard Worker FieldAccessCallingConventionRISCV64 calling_convention;
5129*795d594fSAndroid Build Coastguard Worker codegen_->GenerateUnresolvedFieldAccess(instruction,
5130*795d594fSAndroid Build Coastguard Worker instruction->GetFieldType(),
5131*795d594fSAndroid Build Coastguard Worker instruction->GetFieldIndex(),
5132*795d594fSAndroid Build Coastguard Worker instruction->GetDexPc(),
5133*795d594fSAndroid Build Coastguard Worker calling_convention);
5134*795d594fSAndroid Build Coastguard Worker }
5135*795d594fSAndroid Build Coastguard Worker
VisitUnresolvedStaticFieldSet(HUnresolvedStaticFieldSet * instruction)5136*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitUnresolvedStaticFieldSet(
5137*795d594fSAndroid Build Coastguard Worker HUnresolvedStaticFieldSet* instruction) {
5138*795d594fSAndroid Build Coastguard Worker FieldAccessCallingConventionRISCV64 calling_convention;
5139*795d594fSAndroid Build Coastguard Worker codegen_->CreateUnresolvedFieldLocationSummary(
5140*795d594fSAndroid Build Coastguard Worker instruction, instruction->GetFieldType(), calling_convention);
5141*795d594fSAndroid Build Coastguard Worker }
5142*795d594fSAndroid Build Coastguard Worker
VisitUnresolvedStaticFieldSet(HUnresolvedStaticFieldSet * instruction)5143*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitUnresolvedStaticFieldSet(
5144*795d594fSAndroid Build Coastguard Worker HUnresolvedStaticFieldSet* instruction) {
5145*795d594fSAndroid Build Coastguard Worker FieldAccessCallingConventionRISCV64 calling_convention;
5146*795d594fSAndroid Build Coastguard Worker codegen_->GenerateUnresolvedFieldAccess(instruction,
5147*795d594fSAndroid Build Coastguard Worker instruction->GetFieldType(),
5148*795d594fSAndroid Build Coastguard Worker instruction->GetFieldIndex(),
5149*795d594fSAndroid Build Coastguard Worker instruction->GetDexPc(),
5150*795d594fSAndroid Build Coastguard Worker calling_convention);
5151*795d594fSAndroid Build Coastguard Worker }
5152*795d594fSAndroid Build Coastguard Worker
VisitSelect(HSelect * instruction)5153*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitSelect(HSelect* instruction) {
5154*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
5155*795d594fSAndroid Build Coastguard Worker if (DataType::IsFloatingPointType(instruction->GetType())) {
5156*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, FpuRegisterOrZeroBitPatternLocation(instruction->GetFalseValue()));
5157*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, FpuRegisterOrZeroBitPatternLocation(instruction->GetTrueValue()));
5158*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
5159*795d594fSAndroid Build Coastguard Worker if (!locations->InAt(0).IsConstant() && !locations->InAt(1).IsConstant()) {
5160*795d594fSAndroid Build Coastguard Worker locations->AddTemp(Location::RequiresRegister());
5161*795d594fSAndroid Build Coastguard Worker }
5162*795d594fSAndroid Build Coastguard Worker } else {
5163*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, RegisterOrZeroBitPatternLocation(instruction->GetFalseValue()));
5164*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, RegisterOrZeroBitPatternLocation(instruction->GetTrueValue()));
5165*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap);
5166*795d594fSAndroid Build Coastguard Worker }
5167*795d594fSAndroid Build Coastguard Worker
5168*795d594fSAndroid Build Coastguard Worker if (IsBooleanValueOrMaterializedCondition(instruction->GetCondition())) {
5169*795d594fSAndroid Build Coastguard Worker locations->SetInAt(2, Location::RequiresRegister());
5170*795d594fSAndroid Build Coastguard Worker }
5171*795d594fSAndroid Build Coastguard Worker }
5172*795d594fSAndroid Build Coastguard Worker
VisitSelect(HSelect * instruction)5173*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitSelect(HSelect* instruction) {
5174*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
5175*795d594fSAndroid Build Coastguard Worker HInstruction* cond = instruction->GetCondition();
5176*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
5177*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
5178*795d594fSAndroid Build Coastguard Worker if (!IsBooleanValueOrMaterializedCondition(cond)) {
5179*795d594fSAndroid Build Coastguard Worker DataType::Type cond_type = cond->InputAt(0)->GetType();
5180*795d594fSAndroid Build Coastguard Worker IfCondition if_cond = cond->AsCondition()->GetCondition();
5181*795d594fSAndroid Build Coastguard Worker if (DataType::IsFloatingPointType(cond_type)) {
5182*795d594fSAndroid Build Coastguard Worker GenerateFpCondition(if_cond,
5183*795d594fSAndroid Build Coastguard Worker cond->AsCondition()->IsGtBias(),
5184*795d594fSAndroid Build Coastguard Worker cond_type,
5185*795d594fSAndroid Build Coastguard Worker cond->GetLocations(),
5186*795d594fSAndroid Build Coastguard Worker /*label=*/ nullptr,
5187*795d594fSAndroid Build Coastguard Worker tmp,
5188*795d594fSAndroid Build Coastguard Worker /*to_all_bits=*/ true);
5189*795d594fSAndroid Build Coastguard Worker } else {
5190*795d594fSAndroid Build Coastguard Worker GenerateIntLongCondition(if_cond, cond->GetLocations(), tmp, /*to_all_bits=*/ true);
5191*795d594fSAndroid Build Coastguard Worker }
5192*795d594fSAndroid Build Coastguard Worker } else {
5193*795d594fSAndroid Build Coastguard Worker // TODO(riscv64): Remove the normalizing SNEZ when we can ensure that booleans
5194*795d594fSAndroid Build Coastguard Worker // have only values 0 and 1. b/279302742
5195*795d594fSAndroid Build Coastguard Worker __ Snez(tmp, locations->InAt(2).AsRegister<XRegister>());
5196*795d594fSAndroid Build Coastguard Worker __ Neg(tmp, tmp);
5197*795d594fSAndroid Build Coastguard Worker }
5198*795d594fSAndroid Build Coastguard Worker
5199*795d594fSAndroid Build Coastguard Worker XRegister true_reg, false_reg, xor_reg, out_reg;
5200*795d594fSAndroid Build Coastguard Worker DataType::Type type = instruction->GetType();
5201*795d594fSAndroid Build Coastguard Worker if (DataType::IsFloatingPointType(type)) {
5202*795d594fSAndroid Build Coastguard Worker if (locations->InAt(0).IsConstant()) {
5203*795d594fSAndroid Build Coastguard Worker DCHECK(locations->InAt(0).GetConstant()->IsZeroBitPattern());
5204*795d594fSAndroid Build Coastguard Worker false_reg = Zero;
5205*795d594fSAndroid Build Coastguard Worker } else {
5206*795d594fSAndroid Build Coastguard Worker false_reg = srs.AllocateXRegister();
5207*795d594fSAndroid Build Coastguard Worker FMvX(false_reg, locations->InAt(0).AsFpuRegister<FRegister>(), type);
5208*795d594fSAndroid Build Coastguard Worker }
5209*795d594fSAndroid Build Coastguard Worker if (locations->InAt(1).IsConstant()) {
5210*795d594fSAndroid Build Coastguard Worker DCHECK(locations->InAt(1).GetConstant()->IsZeroBitPattern());
5211*795d594fSAndroid Build Coastguard Worker true_reg = Zero;
5212*795d594fSAndroid Build Coastguard Worker } else {
5213*795d594fSAndroid Build Coastguard Worker true_reg = (false_reg == Zero) ? srs.AllocateXRegister()
5214*795d594fSAndroid Build Coastguard Worker : locations->GetTemp(0).AsRegister<XRegister>();
5215*795d594fSAndroid Build Coastguard Worker FMvX(true_reg, locations->InAt(1).AsFpuRegister<FRegister>(), type);
5216*795d594fSAndroid Build Coastguard Worker }
5217*795d594fSAndroid Build Coastguard Worker // We can clobber the "true value" with the XOR result.
5218*795d594fSAndroid Build Coastguard Worker // Note: The XOR is not emitted if `true_reg == Zero`, see below.
5219*795d594fSAndroid Build Coastguard Worker xor_reg = true_reg;
5220*795d594fSAndroid Build Coastguard Worker out_reg = tmp;
5221*795d594fSAndroid Build Coastguard Worker } else {
5222*795d594fSAndroid Build Coastguard Worker false_reg = InputXRegisterOrZero(locations->InAt(0));
5223*795d594fSAndroid Build Coastguard Worker true_reg = InputXRegisterOrZero(locations->InAt(1));
5224*795d594fSAndroid Build Coastguard Worker xor_reg = srs.AllocateXRegister();
5225*795d594fSAndroid Build Coastguard Worker out_reg = locations->Out().AsRegister<XRegister>();
5226*795d594fSAndroid Build Coastguard Worker }
5227*795d594fSAndroid Build Coastguard Worker
5228*795d594fSAndroid Build Coastguard Worker // We use a branch-free implementation of `HSelect`.
5229*795d594fSAndroid Build Coastguard Worker // With `tmp` initialized to 0 for `false` and -1 for `true`:
5230*795d594fSAndroid Build Coastguard Worker // xor xor_reg, false_reg, true_reg
5231*795d594fSAndroid Build Coastguard Worker // and tmp, tmp, xor_reg
5232*795d594fSAndroid Build Coastguard Worker // xor out_reg, tmp, false_reg
5233*795d594fSAndroid Build Coastguard Worker if (false_reg == Zero) {
5234*795d594fSAndroid Build Coastguard Worker xor_reg = true_reg;
5235*795d594fSAndroid Build Coastguard Worker } else if (true_reg == Zero) {
5236*795d594fSAndroid Build Coastguard Worker xor_reg = false_reg;
5237*795d594fSAndroid Build Coastguard Worker } else {
5238*795d594fSAndroid Build Coastguard Worker DCHECK_NE(xor_reg, Zero);
5239*795d594fSAndroid Build Coastguard Worker __ Xor(xor_reg, false_reg, true_reg);
5240*795d594fSAndroid Build Coastguard Worker }
5241*795d594fSAndroid Build Coastguard Worker __ And(tmp, tmp, xor_reg);
5242*795d594fSAndroid Build Coastguard Worker __ Xor(out_reg, tmp, false_reg);
5243*795d594fSAndroid Build Coastguard Worker
5244*795d594fSAndroid Build Coastguard Worker if (type == DataType::Type::kFloat64) {
5245*795d594fSAndroid Build Coastguard Worker __ FMvDX(locations->Out().AsFpuRegister<FRegister>(), out_reg);
5246*795d594fSAndroid Build Coastguard Worker } else if (type == DataType::Type::kFloat32) {
5247*795d594fSAndroid Build Coastguard Worker __ FMvWX(locations->Out().AsFpuRegister<FRegister>(), out_reg);
5248*795d594fSAndroid Build Coastguard Worker }
5249*795d594fSAndroid Build Coastguard Worker }
5250*795d594fSAndroid Build Coastguard Worker
VisitSub(HSub * instruction)5251*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitSub(HSub* instruction) {
5252*795d594fSAndroid Build Coastguard Worker HandleBinaryOp(instruction);
5253*795d594fSAndroid Build Coastguard Worker }
5254*795d594fSAndroid Build Coastguard Worker
VisitSub(HSub * instruction)5255*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitSub(HSub* instruction) {
5256*795d594fSAndroid Build Coastguard Worker HandleBinaryOp(instruction);
5257*795d594fSAndroid Build Coastguard Worker }
5258*795d594fSAndroid Build Coastguard Worker
VisitSuspendCheck(HSuspendCheck * instruction)5259*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitSuspendCheck(HSuspendCheck* instruction) {
5260*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator())
5261*795d594fSAndroid Build Coastguard Worker LocationSummary(instruction, LocationSummary::kCallOnSlowPath);
5262*795d594fSAndroid Build Coastguard Worker // In suspend check slow path, usually there are no caller-save registers at all.
5263*795d594fSAndroid Build Coastguard Worker // If SIMD instructions are present, however, we force spilling all live SIMD
5264*795d594fSAndroid Build Coastguard Worker // registers in full width (since the runtime only saves/restores lower part).
5265*795d594fSAndroid Build Coastguard Worker locations->SetCustomSlowPathCallerSaves(GetGraph()->HasSIMD() ? RegisterSet::AllFpu() :
5266*795d594fSAndroid Build Coastguard Worker RegisterSet::Empty());
5267*795d594fSAndroid Build Coastguard Worker }
5268*795d594fSAndroid Build Coastguard Worker
VisitSuspendCheck(HSuspendCheck * instruction)5269*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitSuspendCheck(HSuspendCheck* instruction) {
5270*795d594fSAndroid Build Coastguard Worker HBasicBlock* block = instruction->GetBlock();
5271*795d594fSAndroid Build Coastguard Worker if (block->GetLoopInformation() != nullptr) {
5272*795d594fSAndroid Build Coastguard Worker DCHECK(block->GetLoopInformation()->GetSuspendCheck() == instruction);
5273*795d594fSAndroid Build Coastguard Worker // The back edge will generate the suspend check.
5274*795d594fSAndroid Build Coastguard Worker return;
5275*795d594fSAndroid Build Coastguard Worker }
5276*795d594fSAndroid Build Coastguard Worker if (block->IsEntryBlock() && instruction->GetNext()->IsGoto()) {
5277*795d594fSAndroid Build Coastguard Worker // The goto will generate the suspend check.
5278*795d594fSAndroid Build Coastguard Worker return;
5279*795d594fSAndroid Build Coastguard Worker }
5280*795d594fSAndroid Build Coastguard Worker GenerateSuspendCheck(instruction, nullptr);
5281*795d594fSAndroid Build Coastguard Worker }
5282*795d594fSAndroid Build Coastguard Worker
VisitThrow(HThrow * instruction)5283*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitThrow(HThrow* instruction) {
5284*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator())
5285*795d594fSAndroid Build Coastguard Worker LocationSummary(instruction, LocationSummary::kCallOnMainOnly);
5286*795d594fSAndroid Build Coastguard Worker InvokeRuntimeCallingConvention calling_convention;
5287*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
5288*795d594fSAndroid Build Coastguard Worker }
5289*795d594fSAndroid Build Coastguard Worker
VisitThrow(HThrow * instruction)5290*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitThrow(HThrow* instruction) {
5291*795d594fSAndroid Build Coastguard Worker codegen_->InvokeRuntime(kQuickDeliverException, instruction, instruction->GetDexPc());
5292*795d594fSAndroid Build Coastguard Worker CheckEntrypointTypes<kQuickDeliverException, void, mirror::Object*>();
5293*795d594fSAndroid Build Coastguard Worker }
5294*795d594fSAndroid Build Coastguard Worker
VisitTryBoundary(HTryBoundary * instruction)5295*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitTryBoundary(HTryBoundary* instruction) {
5296*795d594fSAndroid Build Coastguard Worker instruction->SetLocations(nullptr);
5297*795d594fSAndroid Build Coastguard Worker }
5298*795d594fSAndroid Build Coastguard Worker
VisitTryBoundary(HTryBoundary * instruction)5299*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitTryBoundary(HTryBoundary* instruction) {
5300*795d594fSAndroid Build Coastguard Worker HBasicBlock* successor = instruction->GetNormalFlowSuccessor();
5301*795d594fSAndroid Build Coastguard Worker if (!successor->IsExitBlock()) {
5302*795d594fSAndroid Build Coastguard Worker HandleGoto(instruction, successor);
5303*795d594fSAndroid Build Coastguard Worker }
5304*795d594fSAndroid Build Coastguard Worker }
5305*795d594fSAndroid Build Coastguard Worker
VisitTypeConversion(HTypeConversion * instruction)5306*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitTypeConversion(HTypeConversion* instruction) {
5307*795d594fSAndroid Build Coastguard Worker DataType::Type input_type = instruction->GetInputType();
5308*795d594fSAndroid Build Coastguard Worker DataType::Type result_type = instruction->GetResultType();
5309*795d594fSAndroid Build Coastguard Worker DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
5310*795d594fSAndroid Build Coastguard Worker << input_type << " -> " << result_type;
5311*795d594fSAndroid Build Coastguard Worker
5312*795d594fSAndroid Build Coastguard Worker if ((input_type == DataType::Type::kReference) || (input_type == DataType::Type::kVoid) ||
5313*795d594fSAndroid Build Coastguard Worker (result_type == DataType::Type::kReference) || (result_type == DataType::Type::kVoid)) {
5314*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected type conversion from " << input_type << " to " << result_type;
5315*795d594fSAndroid Build Coastguard Worker }
5316*795d594fSAndroid Build Coastguard Worker
5317*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
5318*795d594fSAndroid Build Coastguard Worker
5319*795d594fSAndroid Build Coastguard Worker if (DataType::IsFloatingPointType(input_type)) {
5320*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresFpuRegister());
5321*795d594fSAndroid Build Coastguard Worker } else {
5322*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
5323*795d594fSAndroid Build Coastguard Worker }
5324*795d594fSAndroid Build Coastguard Worker
5325*795d594fSAndroid Build Coastguard Worker if (DataType::IsFloatingPointType(result_type)) {
5326*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
5327*795d594fSAndroid Build Coastguard Worker } else {
5328*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
5329*795d594fSAndroid Build Coastguard Worker }
5330*795d594fSAndroid Build Coastguard Worker }
5331*795d594fSAndroid Build Coastguard Worker
VisitTypeConversion(HTypeConversion * instruction)5332*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitTypeConversion(HTypeConversion* instruction) {
5333*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
5334*795d594fSAndroid Build Coastguard Worker DataType::Type result_type = instruction->GetResultType();
5335*795d594fSAndroid Build Coastguard Worker DataType::Type input_type = instruction->GetInputType();
5336*795d594fSAndroid Build Coastguard Worker
5337*795d594fSAndroid Build Coastguard Worker DCHECK(!DataType::IsTypeConversionImplicit(input_type, result_type))
5338*795d594fSAndroid Build Coastguard Worker << input_type << " -> " << result_type;
5339*795d594fSAndroid Build Coastguard Worker
5340*795d594fSAndroid Build Coastguard Worker if (DataType::IsIntegralType(result_type) && DataType::IsIntegralType(input_type)) {
5341*795d594fSAndroid Build Coastguard Worker XRegister dst = locations->Out().AsRegister<XRegister>();
5342*795d594fSAndroid Build Coastguard Worker XRegister src = locations->InAt(0).AsRegister<XRegister>();
5343*795d594fSAndroid Build Coastguard Worker switch (result_type) {
5344*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint8:
5345*795d594fSAndroid Build Coastguard Worker __ ZextB(dst, src);
5346*795d594fSAndroid Build Coastguard Worker break;
5347*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt8:
5348*795d594fSAndroid Build Coastguard Worker __ SextB(dst, src);
5349*795d594fSAndroid Build Coastguard Worker break;
5350*795d594fSAndroid Build Coastguard Worker case DataType::Type::kUint16:
5351*795d594fSAndroid Build Coastguard Worker __ ZextH(dst, src);
5352*795d594fSAndroid Build Coastguard Worker break;
5353*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt16:
5354*795d594fSAndroid Build Coastguard Worker __ SextH(dst, src);
5355*795d594fSAndroid Build Coastguard Worker break;
5356*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt32:
5357*795d594fSAndroid Build Coastguard Worker case DataType::Type::kInt64:
5358*795d594fSAndroid Build Coastguard Worker // Sign-extend 32-bit int into bits 32 through 63 for int-to-long and long-to-int
5359*795d594fSAndroid Build Coastguard Worker // conversions, except when the input and output registers are the same and we are not
5360*795d594fSAndroid Build Coastguard Worker // converting longs to shorter types. In these cases, do nothing.
5361*795d594fSAndroid Build Coastguard Worker if ((input_type == DataType::Type::kInt64) || (dst != src)) {
5362*795d594fSAndroid Build Coastguard Worker __ Addiw(dst, src, 0);
5363*795d594fSAndroid Build Coastguard Worker }
5364*795d594fSAndroid Build Coastguard Worker break;
5365*795d594fSAndroid Build Coastguard Worker
5366*795d594fSAndroid Build Coastguard Worker default:
5367*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected type conversion from " << input_type
5368*795d594fSAndroid Build Coastguard Worker << " to " << result_type;
5369*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
5370*795d594fSAndroid Build Coastguard Worker }
5371*795d594fSAndroid Build Coastguard Worker } else if (DataType::IsFloatingPointType(result_type) && DataType::IsIntegralType(input_type)) {
5372*795d594fSAndroid Build Coastguard Worker FRegister dst = locations->Out().AsFpuRegister<FRegister>();
5373*795d594fSAndroid Build Coastguard Worker XRegister src = locations->InAt(0).AsRegister<XRegister>();
5374*795d594fSAndroid Build Coastguard Worker if (input_type == DataType::Type::kInt64) {
5375*795d594fSAndroid Build Coastguard Worker if (result_type == DataType::Type::kFloat32) {
5376*795d594fSAndroid Build Coastguard Worker __ FCvtSL(dst, src, FPRoundingMode::kRNE);
5377*795d594fSAndroid Build Coastguard Worker } else {
5378*795d594fSAndroid Build Coastguard Worker __ FCvtDL(dst, src, FPRoundingMode::kRNE);
5379*795d594fSAndroid Build Coastguard Worker }
5380*795d594fSAndroid Build Coastguard Worker } else {
5381*795d594fSAndroid Build Coastguard Worker if (result_type == DataType::Type::kFloat32) {
5382*795d594fSAndroid Build Coastguard Worker __ FCvtSW(dst, src, FPRoundingMode::kRNE);
5383*795d594fSAndroid Build Coastguard Worker } else {
5384*795d594fSAndroid Build Coastguard Worker __ FCvtDW(dst, src); // No rounding.
5385*795d594fSAndroid Build Coastguard Worker }
5386*795d594fSAndroid Build Coastguard Worker }
5387*795d594fSAndroid Build Coastguard Worker } else if (DataType::IsIntegralType(result_type) && DataType::IsFloatingPointType(input_type)) {
5388*795d594fSAndroid Build Coastguard Worker CHECK(result_type == DataType::Type::kInt32 || result_type == DataType::Type::kInt64);
5389*795d594fSAndroid Build Coastguard Worker XRegister dst = locations->Out().AsRegister<XRegister>();
5390*795d594fSAndroid Build Coastguard Worker FRegister src = locations->InAt(0).AsFpuRegister<FRegister>();
5391*795d594fSAndroid Build Coastguard Worker if (result_type == DataType::Type::kInt64) {
5392*795d594fSAndroid Build Coastguard Worker if (input_type == DataType::Type::kFloat32) {
5393*795d594fSAndroid Build Coastguard Worker __ FCvtLS(dst, src, FPRoundingMode::kRTZ);
5394*795d594fSAndroid Build Coastguard Worker } else {
5395*795d594fSAndroid Build Coastguard Worker __ FCvtLD(dst, src, FPRoundingMode::kRTZ);
5396*795d594fSAndroid Build Coastguard Worker }
5397*795d594fSAndroid Build Coastguard Worker } else {
5398*795d594fSAndroid Build Coastguard Worker if (input_type == DataType::Type::kFloat32) {
5399*795d594fSAndroid Build Coastguard Worker __ FCvtWS(dst, src, FPRoundingMode::kRTZ);
5400*795d594fSAndroid Build Coastguard Worker } else {
5401*795d594fSAndroid Build Coastguard Worker __ FCvtWD(dst, src, FPRoundingMode::kRTZ);
5402*795d594fSAndroid Build Coastguard Worker }
5403*795d594fSAndroid Build Coastguard Worker }
5404*795d594fSAndroid Build Coastguard Worker // For NaN inputs we need to return 0.
5405*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
5406*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
5407*795d594fSAndroid Build Coastguard Worker FClass(tmp, src, input_type);
5408*795d594fSAndroid Build Coastguard Worker __ Sltiu(tmp, tmp, kFClassNaNMinValue); // 0 for NaN, 1 otherwise.
5409*795d594fSAndroid Build Coastguard Worker __ Neg(tmp, tmp); // 0 for NaN, -1 otherwise.
5410*795d594fSAndroid Build Coastguard Worker __ And(dst, dst, tmp); // Cleared for NaN.
5411*795d594fSAndroid Build Coastguard Worker } else if (DataType::IsFloatingPointType(result_type) &&
5412*795d594fSAndroid Build Coastguard Worker DataType::IsFloatingPointType(input_type)) {
5413*795d594fSAndroid Build Coastguard Worker FRegister dst = locations->Out().AsFpuRegister<FRegister>();
5414*795d594fSAndroid Build Coastguard Worker FRegister src = locations->InAt(0).AsFpuRegister<FRegister>();
5415*795d594fSAndroid Build Coastguard Worker if (result_type == DataType::Type::kFloat32) {
5416*795d594fSAndroid Build Coastguard Worker __ FCvtSD(dst, src);
5417*795d594fSAndroid Build Coastguard Worker } else {
5418*795d594fSAndroid Build Coastguard Worker __ FCvtDS(dst, src);
5419*795d594fSAndroid Build Coastguard Worker }
5420*795d594fSAndroid Build Coastguard Worker } else {
5421*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected or unimplemented type conversion from " << input_type
5422*795d594fSAndroid Build Coastguard Worker << " to " << result_type;
5423*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
5424*795d594fSAndroid Build Coastguard Worker }
5425*795d594fSAndroid Build Coastguard Worker }
5426*795d594fSAndroid Build Coastguard Worker
VisitUShr(HUShr * instruction)5427*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitUShr(HUShr* instruction) {
5428*795d594fSAndroid Build Coastguard Worker HandleShift(instruction);
5429*795d594fSAndroid Build Coastguard Worker }
5430*795d594fSAndroid Build Coastguard Worker
VisitUShr(HUShr * instruction)5431*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitUShr(HUShr* instruction) {
5432*795d594fSAndroid Build Coastguard Worker HandleShift(instruction);
5433*795d594fSAndroid Build Coastguard Worker }
5434*795d594fSAndroid Build Coastguard Worker
VisitXor(HXor * instruction)5435*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitXor(HXor* instruction) {
5436*795d594fSAndroid Build Coastguard Worker HandleBinaryOp(instruction);
5437*795d594fSAndroid Build Coastguard Worker }
5438*795d594fSAndroid Build Coastguard Worker
VisitXor(HXor * instruction)5439*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitXor(HXor* instruction) {
5440*795d594fSAndroid Build Coastguard Worker HandleBinaryOp(instruction);
5441*795d594fSAndroid Build Coastguard Worker }
5442*795d594fSAndroid Build Coastguard Worker
VisitRiscv64ShiftAdd(HRiscv64ShiftAdd * instruction)5443*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitRiscv64ShiftAdd(HRiscv64ShiftAdd* instruction) {
5444*795d594fSAndroid Build Coastguard Worker DCHECK(codegen_->GetInstructionSetFeatures().HasZba());
5445*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64)
5446*795d594fSAndroid Build Coastguard Worker << "Unexpected ShiftAdd type: " << instruction->GetType();
5447*795d594fSAndroid Build Coastguard Worker
5448*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
5449*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
5450*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RequiresRegister());
5451*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
5452*795d594fSAndroid Build Coastguard Worker }
5453*795d594fSAndroid Build Coastguard Worker
VisitRiscv64ShiftAdd(HRiscv64ShiftAdd * instruction)5454*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitRiscv64ShiftAdd(HRiscv64ShiftAdd* instruction) {
5455*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64)
5456*795d594fSAndroid Build Coastguard Worker << "Unexpected ShiftAdd type: " << instruction->GetType();
5457*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
5458*795d594fSAndroid Build Coastguard Worker XRegister first = locations->InAt(0).AsRegister<XRegister>();
5459*795d594fSAndroid Build Coastguard Worker XRegister second = locations->InAt(1).AsRegister<XRegister>();
5460*795d594fSAndroid Build Coastguard Worker XRegister dest = locations->Out().AsRegister<XRegister>();
5461*795d594fSAndroid Build Coastguard Worker
5462*795d594fSAndroid Build Coastguard Worker switch (instruction->GetDistance()) {
5463*795d594fSAndroid Build Coastguard Worker case 1:
5464*795d594fSAndroid Build Coastguard Worker __ Sh1Add(dest, first, second);
5465*795d594fSAndroid Build Coastguard Worker break;
5466*795d594fSAndroid Build Coastguard Worker case 2:
5467*795d594fSAndroid Build Coastguard Worker __ Sh2Add(dest, first, second);
5468*795d594fSAndroid Build Coastguard Worker break;
5469*795d594fSAndroid Build Coastguard Worker case 3:
5470*795d594fSAndroid Build Coastguard Worker __ Sh3Add(dest, first, second);
5471*795d594fSAndroid Build Coastguard Worker break;
5472*795d594fSAndroid Build Coastguard Worker default:
5473*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected distance of ShiftAdd: " << instruction->GetDistance();
5474*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
5475*795d594fSAndroid Build Coastguard Worker }
5476*795d594fSAndroid Build Coastguard Worker }
5477*795d594fSAndroid Build Coastguard Worker
VisitBitwiseNegatedRight(HBitwiseNegatedRight * instruction)5478*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitBitwiseNegatedRight(HBitwiseNegatedRight* instruction) {
5479*795d594fSAndroid Build Coastguard Worker DCHECK(codegen_->GetInstructionSetFeatures().HasZbb());
5480*795d594fSAndroid Build Coastguard Worker DCHECK(DataType::IsIntegralType(instruction->GetType())) << instruction->GetType();
5481*795d594fSAndroid Build Coastguard Worker
5482*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = new (GetGraph()->GetAllocator()) LocationSummary(instruction);
5483*795d594fSAndroid Build Coastguard Worker locations->SetInAt(0, Location::RequiresRegister());
5484*795d594fSAndroid Build Coastguard Worker locations->SetInAt(1, Location::RequiresRegister());
5485*795d594fSAndroid Build Coastguard Worker locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
5486*795d594fSAndroid Build Coastguard Worker }
5487*795d594fSAndroid Build Coastguard Worker
VisitBitwiseNegatedRight(HBitwiseNegatedRight * instruction)5488*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitBitwiseNegatedRight(HBitwiseNegatedRight* instruction) {
5489*795d594fSAndroid Build Coastguard Worker LocationSummary* locations = instruction->GetLocations();
5490*795d594fSAndroid Build Coastguard Worker XRegister lhs = locations->InAt(0).AsRegister<XRegister>();
5491*795d594fSAndroid Build Coastguard Worker XRegister rhs = locations->InAt(1).AsRegister<XRegister>();
5492*795d594fSAndroid Build Coastguard Worker XRegister dst = locations->Out().AsRegister<XRegister>();
5493*795d594fSAndroid Build Coastguard Worker
5494*795d594fSAndroid Build Coastguard Worker switch (instruction->GetOpKind()) {
5495*795d594fSAndroid Build Coastguard Worker case HInstruction::kAnd:
5496*795d594fSAndroid Build Coastguard Worker __ Andn(dst, lhs, rhs);
5497*795d594fSAndroid Build Coastguard Worker break;
5498*795d594fSAndroid Build Coastguard Worker case HInstruction::kOr:
5499*795d594fSAndroid Build Coastguard Worker __ Orn(dst, lhs, rhs);
5500*795d594fSAndroid Build Coastguard Worker break;
5501*795d594fSAndroid Build Coastguard Worker case HInstruction::kXor:
5502*795d594fSAndroid Build Coastguard Worker __ Xnor(dst, lhs, rhs);
5503*795d594fSAndroid Build Coastguard Worker break;
5504*795d594fSAndroid Build Coastguard Worker default:
5505*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unreachable";
5506*795d594fSAndroid Build Coastguard Worker }
5507*795d594fSAndroid Build Coastguard Worker }
5508*795d594fSAndroid Build Coastguard Worker
VisitVecReplicateScalar(HVecReplicateScalar * instruction)5509*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
5510*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5511*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5512*795d594fSAndroid Build Coastguard Worker }
5513*795d594fSAndroid Build Coastguard Worker
VisitVecReplicateScalar(HVecReplicateScalar * instruction)5514*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
5515*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5516*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5517*795d594fSAndroid Build Coastguard Worker }
5518*795d594fSAndroid Build Coastguard Worker
VisitVecExtractScalar(HVecExtractScalar * instruction)5519*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
5520*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5521*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5522*795d594fSAndroid Build Coastguard Worker }
5523*795d594fSAndroid Build Coastguard Worker
VisitVecExtractScalar(HVecExtractScalar * instruction)5524*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
5525*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5526*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5527*795d594fSAndroid Build Coastguard Worker }
5528*795d594fSAndroid Build Coastguard Worker
VisitVecReduce(HVecReduce * instruction)5529*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecReduce(HVecReduce* instruction) {
5530*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5531*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5532*795d594fSAndroid Build Coastguard Worker }
5533*795d594fSAndroid Build Coastguard Worker
VisitVecReduce(HVecReduce * instruction)5534*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecReduce(HVecReduce* instruction) {
5535*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5536*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5537*795d594fSAndroid Build Coastguard Worker }
5538*795d594fSAndroid Build Coastguard Worker
VisitVecCnv(HVecCnv * instruction)5539*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecCnv(HVecCnv* instruction) {
5540*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5541*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5542*795d594fSAndroid Build Coastguard Worker }
5543*795d594fSAndroid Build Coastguard Worker
VisitVecCnv(HVecCnv * instruction)5544*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecCnv(HVecCnv* instruction) {
5545*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5546*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5547*795d594fSAndroid Build Coastguard Worker }
5548*795d594fSAndroid Build Coastguard Worker
VisitVecNeg(HVecNeg * instruction)5549*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecNeg(HVecNeg* instruction) {
5550*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5551*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5552*795d594fSAndroid Build Coastguard Worker }
5553*795d594fSAndroid Build Coastguard Worker
VisitVecNeg(HVecNeg * instruction)5554*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecNeg(HVecNeg* instruction) {
5555*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5556*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5557*795d594fSAndroid Build Coastguard Worker }
5558*795d594fSAndroid Build Coastguard Worker
VisitVecAbs(HVecAbs * instruction)5559*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecAbs(HVecAbs* instruction) {
5560*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5561*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5562*795d594fSAndroid Build Coastguard Worker }
5563*795d594fSAndroid Build Coastguard Worker
VisitVecAbs(HVecAbs * instruction)5564*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecAbs(HVecAbs* instruction) {
5565*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5566*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5567*795d594fSAndroid Build Coastguard Worker }
5568*795d594fSAndroid Build Coastguard Worker
VisitVecNot(HVecNot * instruction)5569*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecNot(HVecNot* instruction) {
5570*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5571*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5572*795d594fSAndroid Build Coastguard Worker }
5573*795d594fSAndroid Build Coastguard Worker
VisitVecNot(HVecNot * instruction)5574*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecNot(HVecNot* instruction) {
5575*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5576*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5577*795d594fSAndroid Build Coastguard Worker }
5578*795d594fSAndroid Build Coastguard Worker
VisitVecAdd(HVecAdd * instruction)5579*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecAdd(HVecAdd* instruction) {
5580*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5581*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5582*795d594fSAndroid Build Coastguard Worker }
5583*795d594fSAndroid Build Coastguard Worker
VisitVecAdd(HVecAdd * instruction)5584*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecAdd(HVecAdd* instruction) {
5585*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5586*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5587*795d594fSAndroid Build Coastguard Worker }
5588*795d594fSAndroid Build Coastguard Worker
VisitVecHalvingAdd(HVecHalvingAdd * instruction)5589*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
5590*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5591*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5592*795d594fSAndroid Build Coastguard Worker }
5593*795d594fSAndroid Build Coastguard Worker
VisitVecHalvingAdd(HVecHalvingAdd * instruction)5594*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecHalvingAdd(HVecHalvingAdd* instruction) {
5595*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5596*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5597*795d594fSAndroid Build Coastguard Worker }
5598*795d594fSAndroid Build Coastguard Worker
VisitVecSub(HVecSub * instruction)5599*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecSub(HVecSub* instruction) {
5600*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5601*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5602*795d594fSAndroid Build Coastguard Worker }
5603*795d594fSAndroid Build Coastguard Worker
VisitVecSub(HVecSub * instruction)5604*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecSub(HVecSub* instruction) {
5605*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5606*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5607*795d594fSAndroid Build Coastguard Worker }
5608*795d594fSAndroid Build Coastguard Worker
VisitVecMul(HVecMul * instruction)5609*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecMul(HVecMul* instruction) {
5610*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5611*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5612*795d594fSAndroid Build Coastguard Worker }
5613*795d594fSAndroid Build Coastguard Worker
VisitVecMul(HVecMul * instruction)5614*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecMul(HVecMul* instruction) {
5615*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5616*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5617*795d594fSAndroid Build Coastguard Worker }
5618*795d594fSAndroid Build Coastguard Worker
VisitVecDiv(HVecDiv * instruction)5619*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecDiv(HVecDiv* instruction) {
5620*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5621*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5622*795d594fSAndroid Build Coastguard Worker }
5623*795d594fSAndroid Build Coastguard Worker
VisitVecDiv(HVecDiv * instruction)5624*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecDiv(HVecDiv* instruction) {
5625*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5626*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5627*795d594fSAndroid Build Coastguard Worker }
5628*795d594fSAndroid Build Coastguard Worker
VisitVecMin(HVecMin * instruction)5629*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecMin(HVecMin* instruction) {
5630*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5631*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5632*795d594fSAndroid Build Coastguard Worker }
5633*795d594fSAndroid Build Coastguard Worker
VisitVecMin(HVecMin * instruction)5634*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecMin(HVecMin* instruction) {
5635*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5636*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5637*795d594fSAndroid Build Coastguard Worker }
5638*795d594fSAndroid Build Coastguard Worker
VisitVecMax(HVecMax * instruction)5639*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecMax(HVecMax* instruction) {
5640*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5641*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5642*795d594fSAndroid Build Coastguard Worker }
5643*795d594fSAndroid Build Coastguard Worker
VisitVecMax(HVecMax * instruction)5644*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecMax(HVecMax* instruction) {
5645*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5646*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5647*795d594fSAndroid Build Coastguard Worker }
5648*795d594fSAndroid Build Coastguard Worker
VisitVecAnd(HVecAnd * instruction)5649*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecAnd(HVecAnd* instruction) {
5650*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5651*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5652*795d594fSAndroid Build Coastguard Worker }
5653*795d594fSAndroid Build Coastguard Worker
VisitVecAnd(HVecAnd * instruction)5654*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecAnd(HVecAnd* instruction) {
5655*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5656*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5657*795d594fSAndroid Build Coastguard Worker }
5658*795d594fSAndroid Build Coastguard Worker
VisitVecAndNot(HVecAndNot * instruction)5659*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecAndNot(HVecAndNot* instruction) {
5660*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5661*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5662*795d594fSAndroid Build Coastguard Worker }
5663*795d594fSAndroid Build Coastguard Worker
VisitVecAndNot(HVecAndNot * instruction)5664*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecAndNot(HVecAndNot* instruction) {
5665*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5666*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5667*795d594fSAndroid Build Coastguard Worker }
5668*795d594fSAndroid Build Coastguard Worker
VisitVecOr(HVecOr * instruction)5669*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecOr(HVecOr* instruction) {
5670*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5671*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5672*795d594fSAndroid Build Coastguard Worker }
5673*795d594fSAndroid Build Coastguard Worker
VisitVecOr(HVecOr * instruction)5674*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecOr(HVecOr* instruction) {
5675*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5676*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5677*795d594fSAndroid Build Coastguard Worker }
5678*795d594fSAndroid Build Coastguard Worker
VisitVecXor(HVecXor * instruction)5679*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecXor(HVecXor* instruction) {
5680*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5681*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5682*795d594fSAndroid Build Coastguard Worker }
5683*795d594fSAndroid Build Coastguard Worker
VisitVecXor(HVecXor * instruction)5684*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecXor(HVecXor* instruction) {
5685*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5686*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5687*795d594fSAndroid Build Coastguard Worker }
5688*795d594fSAndroid Build Coastguard Worker
VisitVecSaturationAdd(HVecSaturationAdd * instruction)5689*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
5690*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5691*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5692*795d594fSAndroid Build Coastguard Worker }
5693*795d594fSAndroid Build Coastguard Worker
VisitVecSaturationAdd(HVecSaturationAdd * instruction)5694*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecSaturationAdd(HVecSaturationAdd* instruction) {
5695*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5696*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5697*795d594fSAndroid Build Coastguard Worker }
5698*795d594fSAndroid Build Coastguard Worker
VisitVecSaturationSub(HVecSaturationSub * instruction)5699*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecSaturationSub(HVecSaturationSub* instruction) {
5700*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5701*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5702*795d594fSAndroid Build Coastguard Worker }
5703*795d594fSAndroid Build Coastguard Worker
VisitVecSaturationSub(HVecSaturationSub * instruction)5704*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecSaturationSub(HVecSaturationSub* instruction) {
5705*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5706*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5707*795d594fSAndroid Build Coastguard Worker }
5708*795d594fSAndroid Build Coastguard Worker
VisitVecShl(HVecShl * instruction)5709*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecShl(HVecShl* instruction) {
5710*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5711*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5712*795d594fSAndroid Build Coastguard Worker }
5713*795d594fSAndroid Build Coastguard Worker
VisitVecShl(HVecShl * instruction)5714*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecShl(HVecShl* instruction) {
5715*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5716*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5717*795d594fSAndroid Build Coastguard Worker }
5718*795d594fSAndroid Build Coastguard Worker
VisitVecShr(HVecShr * instruction)5719*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecShr(HVecShr* instruction) {
5720*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5721*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5722*795d594fSAndroid Build Coastguard Worker }
5723*795d594fSAndroid Build Coastguard Worker
VisitVecShr(HVecShr * instruction)5724*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecShr(HVecShr* instruction) {
5725*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5726*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5727*795d594fSAndroid Build Coastguard Worker }
5728*795d594fSAndroid Build Coastguard Worker
VisitVecUShr(HVecUShr * instruction)5729*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecUShr(HVecUShr* instruction) {
5730*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5731*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5732*795d594fSAndroid Build Coastguard Worker }
5733*795d594fSAndroid Build Coastguard Worker
VisitVecUShr(HVecUShr * instruction)5734*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecUShr(HVecUShr* instruction) {
5735*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5736*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5737*795d594fSAndroid Build Coastguard Worker }
5738*795d594fSAndroid Build Coastguard Worker
VisitVecSetScalars(HVecSetScalars * instruction)5739*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecSetScalars(HVecSetScalars* instruction) {
5740*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5741*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5742*795d594fSAndroid Build Coastguard Worker }
5743*795d594fSAndroid Build Coastguard Worker
VisitVecSetScalars(HVecSetScalars * instruction)5744*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecSetScalars(HVecSetScalars* instruction) {
5745*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5746*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5747*795d594fSAndroid Build Coastguard Worker }
5748*795d594fSAndroid Build Coastguard Worker
VisitVecMultiplyAccumulate(HVecMultiplyAccumulate * instruction)5749*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) {
5750*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5751*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5752*795d594fSAndroid Build Coastguard Worker }
5753*795d594fSAndroid Build Coastguard Worker
VisitVecMultiplyAccumulate(HVecMultiplyAccumulate * instruction)5754*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecMultiplyAccumulate(
5755*795d594fSAndroid Build Coastguard Worker HVecMultiplyAccumulate* instruction) {
5756*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5757*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5758*795d594fSAndroid Build Coastguard Worker }
5759*795d594fSAndroid Build Coastguard Worker
VisitVecSADAccumulate(HVecSADAccumulate * instruction)5760*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
5761*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5762*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5763*795d594fSAndroid Build Coastguard Worker }
5764*795d594fSAndroid Build Coastguard Worker
VisitVecSADAccumulate(HVecSADAccumulate * instruction)5765*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecSADAccumulate(HVecSADAccumulate* instruction) {
5766*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5767*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5768*795d594fSAndroid Build Coastguard Worker }
5769*795d594fSAndroid Build Coastguard Worker
VisitVecDotProd(HVecDotProd * instruction)5770*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecDotProd(HVecDotProd* instruction) {
5771*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5772*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5773*795d594fSAndroid Build Coastguard Worker }
5774*795d594fSAndroid Build Coastguard Worker
VisitVecDotProd(HVecDotProd * instruction)5775*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecDotProd(HVecDotProd* instruction) {
5776*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5777*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5778*795d594fSAndroid Build Coastguard Worker }
5779*795d594fSAndroid Build Coastguard Worker
VisitVecLoad(HVecLoad * instruction)5780*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecLoad(HVecLoad* instruction) {
5781*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5782*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5783*795d594fSAndroid Build Coastguard Worker }
5784*795d594fSAndroid Build Coastguard Worker
VisitVecLoad(HVecLoad * instruction)5785*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecLoad(HVecLoad* instruction) {
5786*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5787*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5788*795d594fSAndroid Build Coastguard Worker }
5789*795d594fSAndroid Build Coastguard Worker
VisitVecStore(HVecStore * instruction)5790*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecStore(HVecStore* instruction) {
5791*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5792*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5793*795d594fSAndroid Build Coastguard Worker }
5794*795d594fSAndroid Build Coastguard Worker
VisitVecStore(HVecStore * instruction)5795*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecStore(HVecStore* instruction) {
5796*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5797*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5798*795d594fSAndroid Build Coastguard Worker }
5799*795d594fSAndroid Build Coastguard Worker
VisitVecPredSetAll(HVecPredSetAll * instruction)5800*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecPredSetAll(HVecPredSetAll* instruction) {
5801*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5802*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5803*795d594fSAndroid Build Coastguard Worker }
5804*795d594fSAndroid Build Coastguard Worker
VisitVecPredSetAll(HVecPredSetAll * instruction)5805*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecPredSetAll(HVecPredSetAll* instruction) {
5806*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5807*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5808*795d594fSAndroid Build Coastguard Worker }
5809*795d594fSAndroid Build Coastguard Worker
VisitVecPredWhile(HVecPredWhile * instruction)5810*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecPredWhile(HVecPredWhile* instruction) {
5811*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5812*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5813*795d594fSAndroid Build Coastguard Worker }
5814*795d594fSAndroid Build Coastguard Worker
VisitVecPredWhile(HVecPredWhile * instruction)5815*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecPredWhile(HVecPredWhile* instruction) {
5816*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5817*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5818*795d594fSAndroid Build Coastguard Worker }
5819*795d594fSAndroid Build Coastguard Worker
VisitVecPredToBoolean(HVecPredToBoolean * instruction)5820*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecPredToBoolean(HVecPredToBoolean* instruction) {
5821*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5822*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5823*795d594fSAndroid Build Coastguard Worker }
5824*795d594fSAndroid Build Coastguard Worker
VisitVecPredToBoolean(HVecPredToBoolean * instruction)5825*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecPredToBoolean(HVecPredToBoolean* instruction) {
5826*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5827*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5828*795d594fSAndroid Build Coastguard Worker }
5829*795d594fSAndroid Build Coastguard Worker
VisitVecEqual(HVecEqual * instruction)5830*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecEqual(HVecEqual* instruction) {
5831*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5832*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5833*795d594fSAndroid Build Coastguard Worker }
5834*795d594fSAndroid Build Coastguard Worker
VisitVecEqual(HVecEqual * instruction)5835*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecEqual(HVecEqual* instruction) {
5836*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5837*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5838*795d594fSAndroid Build Coastguard Worker }
5839*795d594fSAndroid Build Coastguard Worker
VisitVecNotEqual(HVecNotEqual * instruction)5840*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecNotEqual(HVecNotEqual* instruction) {
5841*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5842*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5843*795d594fSAndroid Build Coastguard Worker }
5844*795d594fSAndroid Build Coastguard Worker
VisitVecNotEqual(HVecNotEqual * instruction)5845*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecNotEqual(HVecNotEqual* instruction) {
5846*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5847*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5848*795d594fSAndroid Build Coastguard Worker }
5849*795d594fSAndroid Build Coastguard Worker
VisitVecLessThan(HVecLessThan * instruction)5850*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecLessThan(HVecLessThan* instruction) {
5851*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5852*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5853*795d594fSAndroid Build Coastguard Worker }
5854*795d594fSAndroid Build Coastguard Worker
VisitVecLessThan(HVecLessThan * instruction)5855*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecLessThan(HVecLessThan* instruction) {
5856*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5857*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5858*795d594fSAndroid Build Coastguard Worker }
5859*795d594fSAndroid Build Coastguard Worker
VisitVecLessThanOrEqual(HVecLessThanOrEqual * instruction)5860*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecLessThanOrEqual(HVecLessThanOrEqual* instruction) {
5861*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5862*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5863*795d594fSAndroid Build Coastguard Worker }
5864*795d594fSAndroid Build Coastguard Worker
VisitVecLessThanOrEqual(HVecLessThanOrEqual * instruction)5865*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecLessThanOrEqual(HVecLessThanOrEqual* instruction) {
5866*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5867*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5868*795d594fSAndroid Build Coastguard Worker }
5869*795d594fSAndroid Build Coastguard Worker
VisitVecGreaterThan(HVecGreaterThan * instruction)5870*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecGreaterThan(HVecGreaterThan* instruction) {
5871*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5872*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5873*795d594fSAndroid Build Coastguard Worker }
5874*795d594fSAndroid Build Coastguard Worker
VisitVecGreaterThan(HVecGreaterThan * instruction)5875*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecGreaterThan(HVecGreaterThan* instruction) {
5876*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5877*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5878*795d594fSAndroid Build Coastguard Worker }
5879*795d594fSAndroid Build Coastguard Worker
VisitVecGreaterThanOrEqual(HVecGreaterThanOrEqual * instruction)5880*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecGreaterThanOrEqual(HVecGreaterThanOrEqual* instruction) {
5881*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5882*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5883*795d594fSAndroid Build Coastguard Worker }
5884*795d594fSAndroid Build Coastguard Worker
VisitVecGreaterThanOrEqual(HVecGreaterThanOrEqual * instruction)5885*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecGreaterThanOrEqual(
5886*795d594fSAndroid Build Coastguard Worker HVecGreaterThanOrEqual* instruction) {
5887*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5888*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5889*795d594fSAndroid Build Coastguard Worker }
5890*795d594fSAndroid Build Coastguard Worker
VisitVecBelow(HVecBelow * instruction)5891*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecBelow(HVecBelow* instruction) {
5892*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5893*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5894*795d594fSAndroid Build Coastguard Worker }
5895*795d594fSAndroid Build Coastguard Worker
VisitVecBelow(HVecBelow * instruction)5896*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecBelow(HVecBelow* instruction) {
5897*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5898*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5899*795d594fSAndroid Build Coastguard Worker }
5900*795d594fSAndroid Build Coastguard Worker
VisitVecBelowOrEqual(HVecBelowOrEqual * instruction)5901*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecBelowOrEqual(HVecBelowOrEqual* instruction) {
5902*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5903*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5904*795d594fSAndroid Build Coastguard Worker }
5905*795d594fSAndroid Build Coastguard Worker
VisitVecBelowOrEqual(HVecBelowOrEqual * instruction)5906*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecBelowOrEqual(HVecBelowOrEqual* instruction) {
5907*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5908*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5909*795d594fSAndroid Build Coastguard Worker }
5910*795d594fSAndroid Build Coastguard Worker
VisitVecAbove(HVecAbove * instruction)5911*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecAbove(HVecAbove* instruction) {
5912*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5913*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5914*795d594fSAndroid Build Coastguard Worker }
5915*795d594fSAndroid Build Coastguard Worker
VisitVecAbove(HVecAbove * instruction)5916*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecAbove(HVecAbove* instruction) {
5917*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5918*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5919*795d594fSAndroid Build Coastguard Worker }
5920*795d594fSAndroid Build Coastguard Worker
VisitVecAboveOrEqual(HVecAboveOrEqual * instruction)5921*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecAboveOrEqual(HVecAboveOrEqual* instruction) {
5922*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5923*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5924*795d594fSAndroid Build Coastguard Worker }
5925*795d594fSAndroid Build Coastguard Worker
VisitVecAboveOrEqual(HVecAboveOrEqual * instruction)5926*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecAboveOrEqual(HVecAboveOrEqual* instruction) {
5927*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5928*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5929*795d594fSAndroid Build Coastguard Worker }
5930*795d594fSAndroid Build Coastguard Worker
VisitVecPredNot(HVecPredNot * instruction)5931*795d594fSAndroid Build Coastguard Worker void LocationsBuilderRISCV64::VisitVecPredNot(HVecPredNot* instruction) {
5932*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5933*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5934*795d594fSAndroid Build Coastguard Worker }
5935*795d594fSAndroid Build Coastguard Worker
VisitVecPredNot(HVecPredNot * instruction)5936*795d594fSAndroid Build Coastguard Worker void InstructionCodeGeneratorRISCV64::VisitVecPredNot(HVecPredNot* instruction) {
5937*795d594fSAndroid Build Coastguard Worker UNUSED(instruction);
5938*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented";
5939*795d594fSAndroid Build Coastguard Worker }
5940*795d594fSAndroid Build Coastguard Worker
5941*795d594fSAndroid Build Coastguard Worker namespace detail {
5942*795d594fSAndroid Build Coastguard Worker
5943*795d594fSAndroid Build Coastguard Worker // Mark which intrinsics we don't have handcrafted code for.
5944*795d594fSAndroid Build Coastguard Worker template <Intrinsics T>
5945*795d594fSAndroid Build Coastguard Worker struct IsUnimplemented {
5946*795d594fSAndroid Build Coastguard Worker bool is_unimplemented = false;
5947*795d594fSAndroid Build Coastguard Worker };
5948*795d594fSAndroid Build Coastguard Worker
5949*795d594fSAndroid Build Coastguard Worker #define TRUE_OVERRIDE(Name) \
5950*795d594fSAndroid Build Coastguard Worker template <> \
5951*795d594fSAndroid Build Coastguard Worker struct IsUnimplemented<Intrinsics::k##Name> { \
5952*795d594fSAndroid Build Coastguard Worker bool is_unimplemented = true; \
5953*795d594fSAndroid Build Coastguard Worker };
5954*795d594fSAndroid Build Coastguard Worker UNIMPLEMENTED_INTRINSIC_LIST_RISCV64(TRUE_OVERRIDE)
5955*795d594fSAndroid Build Coastguard Worker #undef TRUE_OVERRIDE
5956*795d594fSAndroid Build Coastguard Worker
5957*795d594fSAndroid Build Coastguard Worker static constexpr bool kIsIntrinsicUnimplemented[] = {
5958*795d594fSAndroid Build Coastguard Worker false, // kNone
5959*795d594fSAndroid Build Coastguard Worker #define IS_UNIMPLEMENTED(Intrinsic, ...) \
5960*795d594fSAndroid Build Coastguard Worker IsUnimplemented<Intrinsics::k##Intrinsic>().is_unimplemented,
5961*795d594fSAndroid Build Coastguard Worker ART_INTRINSICS_LIST(IS_UNIMPLEMENTED)
5962*795d594fSAndroid Build Coastguard Worker #undef IS_UNIMPLEMENTED
5963*795d594fSAndroid Build Coastguard Worker };
5964*795d594fSAndroid Build Coastguard Worker
5965*795d594fSAndroid Build Coastguard Worker } // namespace detail
5966*795d594fSAndroid Build Coastguard Worker
CodeGeneratorRISCV64(HGraph * graph,const CompilerOptions & compiler_options,OptimizingCompilerStats * stats)5967*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::CodeGeneratorRISCV64(HGraph* graph,
5968*795d594fSAndroid Build Coastguard Worker const CompilerOptions& compiler_options,
5969*795d594fSAndroid Build Coastguard Worker OptimizingCompilerStats* stats)
5970*795d594fSAndroid Build Coastguard Worker : CodeGenerator(graph,
5971*795d594fSAndroid Build Coastguard Worker kNumberOfXRegisters,
5972*795d594fSAndroid Build Coastguard Worker kNumberOfFRegisters,
5973*795d594fSAndroid Build Coastguard Worker /*number_of_register_pairs=*/ 0u,
5974*795d594fSAndroid Build Coastguard Worker ComputeRegisterMask(kCoreCalleeSaves, arraysize(kCoreCalleeSaves)),
5975*795d594fSAndroid Build Coastguard Worker ComputeRegisterMask(kFpuCalleeSaves, arraysize(kFpuCalleeSaves)),
5976*795d594fSAndroid Build Coastguard Worker compiler_options,
5977*795d594fSAndroid Build Coastguard Worker stats,
5978*795d594fSAndroid Build Coastguard Worker ArrayRef<const bool>(detail::kIsIntrinsicUnimplemented)),
5979*795d594fSAndroid Build Coastguard Worker assembler_(graph->GetAllocator(),
5980*795d594fSAndroid Build Coastguard Worker compiler_options.GetInstructionSetFeatures()->AsRiscv64InstructionSetFeatures()),
5981*795d594fSAndroid Build Coastguard Worker location_builder_(graph, this),
5982*795d594fSAndroid Build Coastguard Worker instruction_visitor_(graph, this),
5983*795d594fSAndroid Build Coastguard Worker block_labels_(nullptr),
5984*795d594fSAndroid Build Coastguard Worker move_resolver_(graph->GetAllocator(), this),
5985*795d594fSAndroid Build Coastguard Worker uint32_literals_(std::less<uint32_t>(),
5986*795d594fSAndroid Build Coastguard Worker graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
5987*795d594fSAndroid Build Coastguard Worker uint64_literals_(std::less<uint64_t>(),
5988*795d594fSAndroid Build Coastguard Worker graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
5989*795d594fSAndroid Build Coastguard Worker boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
5990*795d594fSAndroid Build Coastguard Worker app_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
5991*795d594fSAndroid Build Coastguard Worker method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
5992*795d594fSAndroid Build Coastguard Worker boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
5993*795d594fSAndroid Build Coastguard Worker app_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
5994*795d594fSAndroid Build Coastguard Worker type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
5995*795d594fSAndroid Build Coastguard Worker public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
5996*795d594fSAndroid Build Coastguard Worker package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
5997*795d594fSAndroid Build Coastguard Worker boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
5998*795d594fSAndroid Build Coastguard Worker string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
5999*795d594fSAndroid Build Coastguard Worker boot_image_jni_entrypoint_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
6000*795d594fSAndroid Build Coastguard Worker boot_image_other_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
6001*795d594fSAndroid Build Coastguard Worker jit_string_patches_(StringReferenceValueComparator(),
6002*795d594fSAndroid Build Coastguard Worker graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
6003*795d594fSAndroid Build Coastguard Worker jit_class_patches_(TypeReferenceValueComparator(),
6004*795d594fSAndroid Build Coastguard Worker graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)) {
6005*795d594fSAndroid Build Coastguard Worker // Always mark the RA register to be saved.
6006*795d594fSAndroid Build Coastguard Worker AddAllocatedRegister(Location::RegisterLocation(RA));
6007*795d594fSAndroid Build Coastguard Worker }
6008*795d594fSAndroid Build Coastguard Worker
MaybeIncrementHotness(HSuspendCheck * suspend_check,bool is_frame_entry)6009*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::MaybeIncrementHotness(HSuspendCheck* suspend_check,
6010*795d594fSAndroid Build Coastguard Worker bool is_frame_entry) {
6011*795d594fSAndroid Build Coastguard Worker if (GetCompilerOptions().CountHotnessInCompiledCode()) {
6012*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
6013*795d594fSAndroid Build Coastguard Worker XRegister method = is_frame_entry ? kArtMethodRegister : srs.AllocateXRegister();
6014*795d594fSAndroid Build Coastguard Worker if (!is_frame_entry) {
6015*795d594fSAndroid Build Coastguard Worker __ Loadd(method, SP, 0);
6016*795d594fSAndroid Build Coastguard Worker }
6017*795d594fSAndroid Build Coastguard Worker XRegister counter = srs.AllocateXRegister();
6018*795d594fSAndroid Build Coastguard Worker __ Loadhu(counter, method, ArtMethod::HotnessCountOffset().Int32Value());
6019*795d594fSAndroid Build Coastguard Worker Riscv64Label done;
6020*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(0u, interpreter::kNterpHotnessValue);
6021*795d594fSAndroid Build Coastguard Worker __ Beqz(counter, &done); // Can clobber `TMP` if taken.
6022*795d594fSAndroid Build Coastguard Worker __ Addi(counter, counter, -1);
6023*795d594fSAndroid Build Coastguard Worker // We may not have another scratch register available for `Storeh`()`,
6024*795d594fSAndroid Build Coastguard Worker // so we must use the `Sh()` function directly.
6025*795d594fSAndroid Build Coastguard Worker static_assert(IsInt<12>(ArtMethod::HotnessCountOffset().Int32Value()));
6026*795d594fSAndroid Build Coastguard Worker __ Sh(counter, method, ArtMethod::HotnessCountOffset().Int32Value());
6027*795d594fSAndroid Build Coastguard Worker __ Bind(&done);
6028*795d594fSAndroid Build Coastguard Worker }
6029*795d594fSAndroid Build Coastguard Worker
6030*795d594fSAndroid Build Coastguard Worker if (GetGraph()->IsCompilingBaseline() &&
6031*795d594fSAndroid Build Coastguard Worker GetGraph()->IsUsefulOptimizing() &&
6032*795d594fSAndroid Build Coastguard Worker !Runtime::Current()->IsAotCompiler()) {
6033*795d594fSAndroid Build Coastguard Worker ProfilingInfo* info = GetGraph()->GetProfilingInfo();
6034*795d594fSAndroid Build Coastguard Worker DCHECK(info != nullptr);
6035*795d594fSAndroid Build Coastguard Worker DCHECK(!HasEmptyFrame());
6036*795d594fSAndroid Build Coastguard Worker uint64_t address = reinterpret_cast64<uint64_t>(info) +
6037*795d594fSAndroid Build Coastguard Worker ProfilingInfo::BaselineHotnessCountOffset().SizeValue();
6038*795d594fSAndroid Build Coastguard Worker auto [base_address, imm12] = SplitJitAddress(address);
6039*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
6040*795d594fSAndroid Build Coastguard Worker XRegister counter = srs.AllocateXRegister();
6041*795d594fSAndroid Build Coastguard Worker XRegister tmp = RA;
6042*795d594fSAndroid Build Coastguard Worker __ LoadConst64(tmp, base_address);
6043*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path =
6044*795d594fSAndroid Build Coastguard Worker new (GetScopedAllocator()) CompileOptimizedSlowPathRISCV64(suspend_check, tmp, imm12);
6045*795d594fSAndroid Build Coastguard Worker AddSlowPath(slow_path);
6046*795d594fSAndroid Build Coastguard Worker __ Lhu(counter, tmp, imm12);
6047*795d594fSAndroid Build Coastguard Worker __ Beqz(counter, slow_path->GetEntryLabel()); // Can clobber `TMP` if taken.
6048*795d594fSAndroid Build Coastguard Worker __ Addi(counter, counter, -1);
6049*795d594fSAndroid Build Coastguard Worker __ Sh(counter, tmp, imm12);
6050*795d594fSAndroid Build Coastguard Worker __ Bind(slow_path->GetExitLabel());
6051*795d594fSAndroid Build Coastguard Worker }
6052*795d594fSAndroid Build Coastguard Worker }
6053*795d594fSAndroid Build Coastguard Worker
CanUseImplicitSuspendCheck() const6054*795d594fSAndroid Build Coastguard Worker bool CodeGeneratorRISCV64::CanUseImplicitSuspendCheck() const {
6055*795d594fSAndroid Build Coastguard Worker // TODO(riscv64): Implement implicit suspend checks to reduce code size.
6056*795d594fSAndroid Build Coastguard Worker return false;
6057*795d594fSAndroid Build Coastguard Worker }
6058*795d594fSAndroid Build Coastguard Worker
GenerateMemoryBarrier(MemBarrierKind kind)6059*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::GenerateMemoryBarrier(MemBarrierKind kind) {
6060*795d594fSAndroid Build Coastguard Worker switch (kind) {
6061*795d594fSAndroid Build Coastguard Worker case MemBarrierKind::kAnyAny:
6062*795d594fSAndroid Build Coastguard Worker __ Fence(/*pred=*/ kFenceRead | kFenceWrite, /*succ=*/ kFenceRead | kFenceWrite);
6063*795d594fSAndroid Build Coastguard Worker break;
6064*795d594fSAndroid Build Coastguard Worker case MemBarrierKind::kAnyStore:
6065*795d594fSAndroid Build Coastguard Worker __ Fence(/*pred=*/ kFenceRead | kFenceWrite, /*succ=*/ kFenceWrite);
6066*795d594fSAndroid Build Coastguard Worker break;
6067*795d594fSAndroid Build Coastguard Worker case MemBarrierKind::kLoadAny:
6068*795d594fSAndroid Build Coastguard Worker __ Fence(/*pred=*/ kFenceRead, /*succ=*/ kFenceRead | kFenceWrite);
6069*795d594fSAndroid Build Coastguard Worker break;
6070*795d594fSAndroid Build Coastguard Worker case MemBarrierKind::kStoreStore:
6071*795d594fSAndroid Build Coastguard Worker __ Fence(/*pred=*/ kFenceWrite, /*succ=*/ kFenceWrite);
6072*795d594fSAndroid Build Coastguard Worker break;
6073*795d594fSAndroid Build Coastguard Worker
6074*795d594fSAndroid Build Coastguard Worker default:
6075*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected memory barrier " << kind;
6076*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
6077*795d594fSAndroid Build Coastguard Worker }
6078*795d594fSAndroid Build Coastguard Worker }
6079*795d594fSAndroid Build Coastguard Worker
GenerateFrameEntry()6080*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::GenerateFrameEntry() {
6081*795d594fSAndroid Build Coastguard Worker // Check if we need to generate the clinit check. We will jump to the
6082*795d594fSAndroid Build Coastguard Worker // resolution stub if the class is not initialized and the executing thread is
6083*795d594fSAndroid Build Coastguard Worker // not the thread initializing it.
6084*795d594fSAndroid Build Coastguard Worker // We do this before constructing the frame to get the correct stack trace if
6085*795d594fSAndroid Build Coastguard Worker // an exception is thrown.
6086*795d594fSAndroid Build Coastguard Worker if (GetCompilerOptions().ShouldCompileWithClinitCheck(GetGraph()->GetArtMethod())) {
6087*795d594fSAndroid Build Coastguard Worker Riscv64Label resolution;
6088*795d594fSAndroid Build Coastguard Worker Riscv64Label memory_barrier;
6089*795d594fSAndroid Build Coastguard Worker
6090*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
6091*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
6092*795d594fSAndroid Build Coastguard Worker XRegister tmp2 = srs.AllocateXRegister();
6093*795d594fSAndroid Build Coastguard Worker
6094*795d594fSAndroid Build Coastguard Worker // We don't emit a read barrier here to save on code size. We rely on the
6095*795d594fSAndroid Build Coastguard Worker // resolution trampoline to do a clinit check before re-entering this code.
6096*795d594fSAndroid Build Coastguard Worker __ Loadwu(tmp2, kArtMethodRegister, ArtMethod::DeclaringClassOffset().Int32Value());
6097*795d594fSAndroid Build Coastguard Worker
6098*795d594fSAndroid Build Coastguard Worker // We shall load the full 32-bit status word with sign-extension and compare as unsigned
6099*795d594fSAndroid Build Coastguard Worker // to sign-extended shifted status values. This yields the same comparison as loading and
6100*795d594fSAndroid Build Coastguard Worker // materializing unsigned but the constant is materialized with a single LUI instruction.
6101*795d594fSAndroid Build Coastguard Worker __ Loadw(tmp, tmp2, mirror::Class::StatusOffset().SizeValue()); // Sign-extended.
6102*795d594fSAndroid Build Coastguard Worker
6103*795d594fSAndroid Build Coastguard Worker // Check if we're visibly initialized.
6104*795d594fSAndroid Build Coastguard Worker __ Li(tmp2, ShiftedSignExtendedClassStatusValue<ClassStatus::kVisiblyInitialized>());
6105*795d594fSAndroid Build Coastguard Worker __ Bgeu(tmp, tmp2, &frame_entry_label_); // Can clobber `TMP` if taken.
6106*795d594fSAndroid Build Coastguard Worker
6107*795d594fSAndroid Build Coastguard Worker // Check if we're initialized and jump to code that does a memory barrier if so.
6108*795d594fSAndroid Build Coastguard Worker __ Li(tmp2, ShiftedSignExtendedClassStatusValue<ClassStatus::kInitialized>());
6109*795d594fSAndroid Build Coastguard Worker __ Bgeu(tmp, tmp2, &memory_barrier); // Can clobber `TMP` if taken.
6110*795d594fSAndroid Build Coastguard Worker
6111*795d594fSAndroid Build Coastguard Worker // Check if we're initializing and the thread initializing is the one
6112*795d594fSAndroid Build Coastguard Worker // executing the code.
6113*795d594fSAndroid Build Coastguard Worker __ Li(tmp2, ShiftedSignExtendedClassStatusValue<ClassStatus::kInitializing>());
6114*795d594fSAndroid Build Coastguard Worker __ Bltu(tmp, tmp2, &resolution); // Can clobber `TMP` if taken.
6115*795d594fSAndroid Build Coastguard Worker
6116*795d594fSAndroid Build Coastguard Worker __ Loadwu(tmp2, kArtMethodRegister, ArtMethod::DeclaringClassOffset().Int32Value());
6117*795d594fSAndroid Build Coastguard Worker __ Loadw(tmp, tmp2, mirror::Class::ClinitThreadIdOffset().Int32Value());
6118*795d594fSAndroid Build Coastguard Worker __ Loadw(tmp2, TR, Thread::TidOffset<kRiscv64PointerSize>().Int32Value());
6119*795d594fSAndroid Build Coastguard Worker __ Beq(tmp, tmp2, &frame_entry_label_);
6120*795d594fSAndroid Build Coastguard Worker __ Bind(&resolution);
6121*795d594fSAndroid Build Coastguard Worker
6122*795d594fSAndroid Build Coastguard Worker // Jump to the resolution stub.
6123*795d594fSAndroid Build Coastguard Worker ThreadOffset64 entrypoint_offset =
6124*795d594fSAndroid Build Coastguard Worker GetThreadOffset<kRiscv64PointerSize>(kQuickQuickResolutionTrampoline);
6125*795d594fSAndroid Build Coastguard Worker __ Loadd(tmp, TR, entrypoint_offset.Int32Value());
6126*795d594fSAndroid Build Coastguard Worker __ Jr(tmp);
6127*795d594fSAndroid Build Coastguard Worker
6128*795d594fSAndroid Build Coastguard Worker __ Bind(&memory_barrier);
6129*795d594fSAndroid Build Coastguard Worker GenerateMemoryBarrier(MemBarrierKind::kAnyAny);
6130*795d594fSAndroid Build Coastguard Worker }
6131*795d594fSAndroid Build Coastguard Worker __ Bind(&frame_entry_label_);
6132*795d594fSAndroid Build Coastguard Worker
6133*795d594fSAndroid Build Coastguard Worker bool do_overflow_check =
6134*795d594fSAndroid Build Coastguard Worker FrameNeedsStackCheck(GetFrameSize(), InstructionSet::kRiscv64) || !IsLeafMethod();
6135*795d594fSAndroid Build Coastguard Worker
6136*795d594fSAndroid Build Coastguard Worker if (do_overflow_check) {
6137*795d594fSAndroid Build Coastguard Worker DCHECK(GetCompilerOptions().GetImplicitStackOverflowChecks());
6138*795d594fSAndroid Build Coastguard Worker __ Loadw(
6139*795d594fSAndroid Build Coastguard Worker Zero, SP, -static_cast<int32_t>(GetStackOverflowReservedBytes(InstructionSet::kRiscv64)));
6140*795d594fSAndroid Build Coastguard Worker RecordPcInfo(nullptr, 0);
6141*795d594fSAndroid Build Coastguard Worker }
6142*795d594fSAndroid Build Coastguard Worker
6143*795d594fSAndroid Build Coastguard Worker if (!HasEmptyFrame()) {
6144*795d594fSAndroid Build Coastguard Worker // Make sure the frame size isn't unreasonably large.
6145*795d594fSAndroid Build Coastguard Worker DCHECK_LE(GetFrameSize(), GetMaximumFrameSize());
6146*795d594fSAndroid Build Coastguard Worker
6147*795d594fSAndroid Build Coastguard Worker // Spill callee-saved registers.
6148*795d594fSAndroid Build Coastguard Worker
6149*795d594fSAndroid Build Coastguard Worker uint32_t frame_size = GetFrameSize();
6150*795d594fSAndroid Build Coastguard Worker
6151*795d594fSAndroid Build Coastguard Worker IncreaseFrame(frame_size);
6152*795d594fSAndroid Build Coastguard Worker
6153*795d594fSAndroid Build Coastguard Worker uint32_t offset = frame_size;
6154*795d594fSAndroid Build Coastguard Worker for (size_t i = arraysize(kCoreCalleeSaves); i != 0; ) {
6155*795d594fSAndroid Build Coastguard Worker --i;
6156*795d594fSAndroid Build Coastguard Worker XRegister reg = kCoreCalleeSaves[i];
6157*795d594fSAndroid Build Coastguard Worker if (allocated_registers_.ContainsCoreRegister(reg)) {
6158*795d594fSAndroid Build Coastguard Worker offset -= kRiscv64DoublewordSize;
6159*795d594fSAndroid Build Coastguard Worker __ Stored(reg, SP, offset);
6160*795d594fSAndroid Build Coastguard Worker __ cfi().RelOffset(dwarf::Reg::Riscv64Core(reg), offset);
6161*795d594fSAndroid Build Coastguard Worker }
6162*795d594fSAndroid Build Coastguard Worker }
6163*795d594fSAndroid Build Coastguard Worker
6164*795d594fSAndroid Build Coastguard Worker for (size_t i = arraysize(kFpuCalleeSaves); i != 0; ) {
6165*795d594fSAndroid Build Coastguard Worker --i;
6166*795d594fSAndroid Build Coastguard Worker FRegister reg = kFpuCalleeSaves[i];
6167*795d594fSAndroid Build Coastguard Worker if (allocated_registers_.ContainsFloatingPointRegister(reg)) {
6168*795d594fSAndroid Build Coastguard Worker offset -= kRiscv64DoublewordSize;
6169*795d594fSAndroid Build Coastguard Worker __ FStored(reg, SP, offset);
6170*795d594fSAndroid Build Coastguard Worker __ cfi().RelOffset(dwarf::Reg::Riscv64Fp(reg), offset);
6171*795d594fSAndroid Build Coastguard Worker }
6172*795d594fSAndroid Build Coastguard Worker }
6173*795d594fSAndroid Build Coastguard Worker
6174*795d594fSAndroid Build Coastguard Worker // Save the current method if we need it. Note that we do not
6175*795d594fSAndroid Build Coastguard Worker // do this in HCurrentMethod, as the instruction might have been removed
6176*795d594fSAndroid Build Coastguard Worker // in the SSA graph.
6177*795d594fSAndroid Build Coastguard Worker if (RequiresCurrentMethod()) {
6178*795d594fSAndroid Build Coastguard Worker __ Stored(kArtMethodRegister, SP, 0);
6179*795d594fSAndroid Build Coastguard Worker }
6180*795d594fSAndroid Build Coastguard Worker
6181*795d594fSAndroid Build Coastguard Worker if (GetGraph()->HasShouldDeoptimizeFlag()) {
6182*795d594fSAndroid Build Coastguard Worker // Initialize should_deoptimize flag to 0.
6183*795d594fSAndroid Build Coastguard Worker __ Storew(Zero, SP, GetStackOffsetOfShouldDeoptimizeFlag());
6184*795d594fSAndroid Build Coastguard Worker }
6185*795d594fSAndroid Build Coastguard Worker }
6186*795d594fSAndroid Build Coastguard Worker MaybeIncrementHotness(/* suspend_check= */ nullptr, /*is_frame_entry=*/ true);
6187*795d594fSAndroid Build Coastguard Worker }
6188*795d594fSAndroid Build Coastguard Worker
GenerateFrameExit()6189*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::GenerateFrameExit() {
6190*795d594fSAndroid Build Coastguard Worker __ cfi().RememberState();
6191*795d594fSAndroid Build Coastguard Worker
6192*795d594fSAndroid Build Coastguard Worker if (!HasEmptyFrame()) {
6193*795d594fSAndroid Build Coastguard Worker // Restore callee-saved registers.
6194*795d594fSAndroid Build Coastguard Worker
6195*795d594fSAndroid Build Coastguard Worker // For better instruction scheduling restore RA before other registers.
6196*795d594fSAndroid Build Coastguard Worker uint32_t offset = GetFrameSize();
6197*795d594fSAndroid Build Coastguard Worker for (size_t i = arraysize(kCoreCalleeSaves); i != 0; ) {
6198*795d594fSAndroid Build Coastguard Worker --i;
6199*795d594fSAndroid Build Coastguard Worker XRegister reg = kCoreCalleeSaves[i];
6200*795d594fSAndroid Build Coastguard Worker if (allocated_registers_.ContainsCoreRegister(reg)) {
6201*795d594fSAndroid Build Coastguard Worker offset -= kRiscv64DoublewordSize;
6202*795d594fSAndroid Build Coastguard Worker __ Loadd(reg, SP, offset);
6203*795d594fSAndroid Build Coastguard Worker __ cfi().Restore(dwarf::Reg::Riscv64Core(reg));
6204*795d594fSAndroid Build Coastguard Worker }
6205*795d594fSAndroid Build Coastguard Worker }
6206*795d594fSAndroid Build Coastguard Worker
6207*795d594fSAndroid Build Coastguard Worker for (size_t i = arraysize(kFpuCalleeSaves); i != 0; ) {
6208*795d594fSAndroid Build Coastguard Worker --i;
6209*795d594fSAndroid Build Coastguard Worker FRegister reg = kFpuCalleeSaves[i];
6210*795d594fSAndroid Build Coastguard Worker if (allocated_registers_.ContainsFloatingPointRegister(reg)) {
6211*795d594fSAndroid Build Coastguard Worker offset -= kRiscv64DoublewordSize;
6212*795d594fSAndroid Build Coastguard Worker __ FLoadd(reg, SP, offset);
6213*795d594fSAndroid Build Coastguard Worker __ cfi().Restore(dwarf::Reg::Riscv64Fp(reg));
6214*795d594fSAndroid Build Coastguard Worker }
6215*795d594fSAndroid Build Coastguard Worker }
6216*795d594fSAndroid Build Coastguard Worker
6217*795d594fSAndroid Build Coastguard Worker DecreaseFrame(GetFrameSize());
6218*795d594fSAndroid Build Coastguard Worker }
6219*795d594fSAndroid Build Coastguard Worker
6220*795d594fSAndroid Build Coastguard Worker __ Jr(RA);
6221*795d594fSAndroid Build Coastguard Worker
6222*795d594fSAndroid Build Coastguard Worker __ cfi().RestoreState();
6223*795d594fSAndroid Build Coastguard Worker __ cfi().DefCFAOffset(GetFrameSize());
6224*795d594fSAndroid Build Coastguard Worker }
6225*795d594fSAndroid Build Coastguard Worker
Bind(HBasicBlock * block)6226*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::Bind(HBasicBlock* block) { __ Bind(GetLabelOf(block)); }
6227*795d594fSAndroid Build Coastguard Worker
MoveConstant(Location destination,int32_t value)6228*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::MoveConstant(Location destination, int32_t value) {
6229*795d594fSAndroid Build Coastguard Worker DCHECK(destination.IsRegister());
6230*795d594fSAndroid Build Coastguard Worker __ LoadConst32(destination.AsRegister<XRegister>(), value);
6231*795d594fSAndroid Build Coastguard Worker }
6232*795d594fSAndroid Build Coastguard Worker
MoveLocation(Location destination,Location source,DataType::Type dst_type)6233*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::MoveLocation(Location destination,
6234*795d594fSAndroid Build Coastguard Worker Location source,
6235*795d594fSAndroid Build Coastguard Worker DataType::Type dst_type) {
6236*795d594fSAndroid Build Coastguard Worker if (source.Equals(destination)) {
6237*795d594fSAndroid Build Coastguard Worker return;
6238*795d594fSAndroid Build Coastguard Worker }
6239*795d594fSAndroid Build Coastguard Worker
6240*795d594fSAndroid Build Coastguard Worker // A valid move type can always be inferred from the destination and source locations.
6241*795d594fSAndroid Build Coastguard Worker // When moving from and to a register, the `dst_type` can be used to generate 32-bit instead
6242*795d594fSAndroid Build Coastguard Worker // of 64-bit moves but it's generally OK to use 64-bit moves for 32-bit values in registers.
6243*795d594fSAndroid Build Coastguard Worker bool unspecified_type = (dst_type == DataType::Type::kVoid);
6244*795d594fSAndroid Build Coastguard Worker // TODO(riscv64): Is the destination type known in all cases?
6245*795d594fSAndroid Build Coastguard Worker // TODO(riscv64): Can unspecified `dst_type` move 32-bit GPR to FPR without NaN-boxing?
6246*795d594fSAndroid Build Coastguard Worker CHECK(!unspecified_type);
6247*795d594fSAndroid Build Coastguard Worker
6248*795d594fSAndroid Build Coastguard Worker if (destination.IsRegister() || destination.IsFpuRegister()) {
6249*795d594fSAndroid Build Coastguard Worker if (unspecified_type) {
6250*795d594fSAndroid Build Coastguard Worker HConstant* src_cst = source.IsConstant() ? source.GetConstant() : nullptr;
6251*795d594fSAndroid Build Coastguard Worker if (source.IsStackSlot() ||
6252*795d594fSAndroid Build Coastguard Worker (src_cst != nullptr &&
6253*795d594fSAndroid Build Coastguard Worker (src_cst->IsIntConstant() || src_cst->IsFloatConstant() || src_cst->IsNullConstant()))) {
6254*795d594fSAndroid Build Coastguard Worker // For stack slots and 32-bit constants, a 32-bit type is appropriate.
6255*795d594fSAndroid Build Coastguard Worker dst_type = destination.IsRegister() ? DataType::Type::kInt32 : DataType::Type::kFloat32;
6256*795d594fSAndroid Build Coastguard Worker } else {
6257*795d594fSAndroid Build Coastguard Worker // If the source is a double stack slot or a 64-bit constant, a 64-bit type
6258*795d594fSAndroid Build Coastguard Worker // is appropriate. Else the source is a register, and since the type has not
6259*795d594fSAndroid Build Coastguard Worker // been specified, we chose a 64-bit type to force a 64-bit move.
6260*795d594fSAndroid Build Coastguard Worker dst_type = destination.IsRegister() ? DataType::Type::kInt64 : DataType::Type::kFloat64;
6261*795d594fSAndroid Build Coastguard Worker }
6262*795d594fSAndroid Build Coastguard Worker }
6263*795d594fSAndroid Build Coastguard Worker DCHECK((destination.IsFpuRegister() && DataType::IsFloatingPointType(dst_type)) ||
6264*795d594fSAndroid Build Coastguard Worker (destination.IsRegister() && !DataType::IsFloatingPointType(dst_type)));
6265*795d594fSAndroid Build Coastguard Worker
6266*795d594fSAndroid Build Coastguard Worker if (source.IsStackSlot() || source.IsDoubleStackSlot()) {
6267*795d594fSAndroid Build Coastguard Worker // Move to GPR/FPR from stack
6268*795d594fSAndroid Build Coastguard Worker if (DataType::IsFloatingPointType(dst_type)) {
6269*795d594fSAndroid Build Coastguard Worker if (DataType::Is64BitType(dst_type)) {
6270*795d594fSAndroid Build Coastguard Worker __ FLoadd(destination.AsFpuRegister<FRegister>(), SP, source.GetStackIndex());
6271*795d594fSAndroid Build Coastguard Worker } else {
6272*795d594fSAndroid Build Coastguard Worker __ FLoadw(destination.AsFpuRegister<FRegister>(), SP, source.GetStackIndex());
6273*795d594fSAndroid Build Coastguard Worker }
6274*795d594fSAndroid Build Coastguard Worker } else {
6275*795d594fSAndroid Build Coastguard Worker if (DataType::Is64BitType(dst_type)) {
6276*795d594fSAndroid Build Coastguard Worker __ Loadd(destination.AsRegister<XRegister>(), SP, source.GetStackIndex());
6277*795d594fSAndroid Build Coastguard Worker } else if (dst_type == DataType::Type::kReference) {
6278*795d594fSAndroid Build Coastguard Worker __ Loadwu(destination.AsRegister<XRegister>(), SP, source.GetStackIndex());
6279*795d594fSAndroid Build Coastguard Worker } else {
6280*795d594fSAndroid Build Coastguard Worker __ Loadw(destination.AsRegister<XRegister>(), SP, source.GetStackIndex());
6281*795d594fSAndroid Build Coastguard Worker }
6282*795d594fSAndroid Build Coastguard Worker }
6283*795d594fSAndroid Build Coastguard Worker } else if (source.IsConstant()) {
6284*795d594fSAndroid Build Coastguard Worker // Move to GPR/FPR from constant
6285*795d594fSAndroid Build Coastguard Worker // TODO(riscv64): Consider using literals for difficult-to-materialize 64-bit constants.
6286*795d594fSAndroid Build Coastguard Worker int64_t value = GetInt64ValueOf(source.GetConstant()->AsConstant());
6287*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
6288*795d594fSAndroid Build Coastguard Worker XRegister gpr = DataType::IsFloatingPointType(dst_type)
6289*795d594fSAndroid Build Coastguard Worker ? srs.AllocateXRegister()
6290*795d594fSAndroid Build Coastguard Worker : destination.AsRegister<XRegister>();
6291*795d594fSAndroid Build Coastguard Worker if (DataType::IsFloatingPointType(dst_type) && value == 0) {
6292*795d594fSAndroid Build Coastguard Worker gpr = Zero; // Note: The scratch register allocated above shall not be used.
6293*795d594fSAndroid Build Coastguard Worker } else {
6294*795d594fSAndroid Build Coastguard Worker // Note: For `float` we load the sign-extended value here as it can sometimes yield
6295*795d594fSAndroid Build Coastguard Worker // a shorter instruction sequence. The higher 32 bits shall be ignored during the
6296*795d594fSAndroid Build Coastguard Worker // transfer to FP reg and the result shall be correctly NaN-boxed.
6297*795d594fSAndroid Build Coastguard Worker __ LoadConst64(gpr, value);
6298*795d594fSAndroid Build Coastguard Worker }
6299*795d594fSAndroid Build Coastguard Worker if (dst_type == DataType::Type::kFloat32) {
6300*795d594fSAndroid Build Coastguard Worker __ FMvWX(destination.AsFpuRegister<FRegister>(), gpr);
6301*795d594fSAndroid Build Coastguard Worker } else if (dst_type == DataType::Type::kFloat64) {
6302*795d594fSAndroid Build Coastguard Worker __ FMvDX(destination.AsFpuRegister<FRegister>(), gpr);
6303*795d594fSAndroid Build Coastguard Worker }
6304*795d594fSAndroid Build Coastguard Worker } else if (source.IsRegister()) {
6305*795d594fSAndroid Build Coastguard Worker if (destination.IsRegister()) {
6306*795d594fSAndroid Build Coastguard Worker // Move to GPR from GPR
6307*795d594fSAndroid Build Coastguard Worker __ Mv(destination.AsRegister<XRegister>(), source.AsRegister<XRegister>());
6308*795d594fSAndroid Build Coastguard Worker } else {
6309*795d594fSAndroid Build Coastguard Worker DCHECK(destination.IsFpuRegister());
6310*795d594fSAndroid Build Coastguard Worker if (DataType::Is64BitType(dst_type)) {
6311*795d594fSAndroid Build Coastguard Worker __ FMvDX(destination.AsFpuRegister<FRegister>(), source.AsRegister<XRegister>());
6312*795d594fSAndroid Build Coastguard Worker } else {
6313*795d594fSAndroid Build Coastguard Worker __ FMvWX(destination.AsFpuRegister<FRegister>(), source.AsRegister<XRegister>());
6314*795d594fSAndroid Build Coastguard Worker }
6315*795d594fSAndroid Build Coastguard Worker }
6316*795d594fSAndroid Build Coastguard Worker } else if (source.IsFpuRegister()) {
6317*795d594fSAndroid Build Coastguard Worker if (destination.IsFpuRegister()) {
6318*795d594fSAndroid Build Coastguard Worker if (GetGraph()->HasSIMD()) {
6319*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Vector extension is unsupported";
6320*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
6321*795d594fSAndroid Build Coastguard Worker } else {
6322*795d594fSAndroid Build Coastguard Worker // Move to FPR from FPR
6323*795d594fSAndroid Build Coastguard Worker if (dst_type == DataType::Type::kFloat32) {
6324*795d594fSAndroid Build Coastguard Worker __ FMvS(destination.AsFpuRegister<FRegister>(), source.AsFpuRegister<FRegister>());
6325*795d594fSAndroid Build Coastguard Worker } else {
6326*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(dst_type, DataType::Type::kFloat64);
6327*795d594fSAndroid Build Coastguard Worker __ FMvD(destination.AsFpuRegister<FRegister>(), source.AsFpuRegister<FRegister>());
6328*795d594fSAndroid Build Coastguard Worker }
6329*795d594fSAndroid Build Coastguard Worker }
6330*795d594fSAndroid Build Coastguard Worker } else {
6331*795d594fSAndroid Build Coastguard Worker DCHECK(destination.IsRegister());
6332*795d594fSAndroid Build Coastguard Worker if (DataType::Is64BitType(dst_type)) {
6333*795d594fSAndroid Build Coastguard Worker __ FMvXD(destination.AsRegister<XRegister>(), source.AsFpuRegister<FRegister>());
6334*795d594fSAndroid Build Coastguard Worker } else {
6335*795d594fSAndroid Build Coastguard Worker __ FMvXW(destination.AsRegister<XRegister>(), source.AsFpuRegister<FRegister>());
6336*795d594fSAndroid Build Coastguard Worker }
6337*795d594fSAndroid Build Coastguard Worker }
6338*795d594fSAndroid Build Coastguard Worker }
6339*795d594fSAndroid Build Coastguard Worker } else if (destination.IsSIMDStackSlot()) {
6340*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "SIMD is unsupported";
6341*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
6342*795d594fSAndroid Build Coastguard Worker } else { // The destination is not a register. It must be a stack slot.
6343*795d594fSAndroid Build Coastguard Worker DCHECK(destination.IsStackSlot() || destination.IsDoubleStackSlot());
6344*795d594fSAndroid Build Coastguard Worker if (source.IsRegister() || source.IsFpuRegister()) {
6345*795d594fSAndroid Build Coastguard Worker if (unspecified_type) {
6346*795d594fSAndroid Build Coastguard Worker if (source.IsRegister()) {
6347*795d594fSAndroid Build Coastguard Worker dst_type = destination.IsStackSlot() ? DataType::Type::kInt32 : DataType::Type::kInt64;
6348*795d594fSAndroid Build Coastguard Worker } else {
6349*795d594fSAndroid Build Coastguard Worker dst_type =
6350*795d594fSAndroid Build Coastguard Worker destination.IsStackSlot() ? DataType::Type::kFloat32 : DataType::Type::kFloat64;
6351*795d594fSAndroid Build Coastguard Worker }
6352*795d594fSAndroid Build Coastguard Worker }
6353*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(source.IsFpuRegister(), DataType::IsFloatingPointType(dst_type));
6354*795d594fSAndroid Build Coastguard Worker // For direct @CriticalNative calls, we need to sign-extend narrow integral args
6355*795d594fSAndroid Build Coastguard Worker // to 64 bits, so widening integral values is allowed. Narrowing is forbidden.
6356*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(DataType::IsFloatingPointType(dst_type) || destination.IsStackSlot(),
6357*795d594fSAndroid Build Coastguard Worker destination.IsDoubleStackSlot() == DataType::Is64BitType(dst_type));
6358*795d594fSAndroid Build Coastguard Worker // Move to stack from GPR/FPR
6359*795d594fSAndroid Build Coastguard Worker if (destination.IsDoubleStackSlot()) {
6360*795d594fSAndroid Build Coastguard Worker if (source.IsRegister()) {
6361*795d594fSAndroid Build Coastguard Worker __ Stored(source.AsRegister<XRegister>(), SP, destination.GetStackIndex());
6362*795d594fSAndroid Build Coastguard Worker } else {
6363*795d594fSAndroid Build Coastguard Worker __ FStored(source.AsFpuRegister<FRegister>(), SP, destination.GetStackIndex());
6364*795d594fSAndroid Build Coastguard Worker }
6365*795d594fSAndroid Build Coastguard Worker } else {
6366*795d594fSAndroid Build Coastguard Worker if (source.IsRegister()) {
6367*795d594fSAndroid Build Coastguard Worker __ Storew(source.AsRegister<XRegister>(), SP, destination.GetStackIndex());
6368*795d594fSAndroid Build Coastguard Worker } else {
6369*795d594fSAndroid Build Coastguard Worker __ FStorew(source.AsFpuRegister<FRegister>(), SP, destination.GetStackIndex());
6370*795d594fSAndroid Build Coastguard Worker }
6371*795d594fSAndroid Build Coastguard Worker }
6372*795d594fSAndroid Build Coastguard Worker } else if (source.IsConstant()) {
6373*795d594fSAndroid Build Coastguard Worker // Move to stack from constant
6374*795d594fSAndroid Build Coastguard Worker int64_t value = GetInt64ValueOf(source.GetConstant());
6375*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
6376*795d594fSAndroid Build Coastguard Worker XRegister gpr = (value != 0) ? srs.AllocateXRegister() : Zero;
6377*795d594fSAndroid Build Coastguard Worker if (value != 0) {
6378*795d594fSAndroid Build Coastguard Worker __ LoadConst64(gpr, value);
6379*795d594fSAndroid Build Coastguard Worker }
6380*795d594fSAndroid Build Coastguard Worker if (destination.IsStackSlot()) {
6381*795d594fSAndroid Build Coastguard Worker __ Storew(gpr, SP, destination.GetStackIndex());
6382*795d594fSAndroid Build Coastguard Worker } else {
6383*795d594fSAndroid Build Coastguard Worker DCHECK(destination.IsDoubleStackSlot());
6384*795d594fSAndroid Build Coastguard Worker __ Stored(gpr, SP, destination.GetStackIndex());
6385*795d594fSAndroid Build Coastguard Worker }
6386*795d594fSAndroid Build Coastguard Worker } else {
6387*795d594fSAndroid Build Coastguard Worker DCHECK(source.IsStackSlot() || source.IsDoubleStackSlot());
6388*795d594fSAndroid Build Coastguard Worker // For direct @CriticalNative calls, we need to sign-extend narrow integral args
6389*795d594fSAndroid Build Coastguard Worker // to 64 bits, so widening move is allowed. Narrowing move is forbidden.
6390*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(destination.IsStackSlot(), source.IsStackSlot());
6391*795d594fSAndroid Build Coastguard Worker // Move to stack from stack
6392*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
6393*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs.AllocateXRegister();
6394*795d594fSAndroid Build Coastguard Worker if (source.IsStackSlot()) {
6395*795d594fSAndroid Build Coastguard Worker __ Loadw(tmp, SP, source.GetStackIndex());
6396*795d594fSAndroid Build Coastguard Worker } else {
6397*795d594fSAndroid Build Coastguard Worker __ Loadd(tmp, SP, source.GetStackIndex());
6398*795d594fSAndroid Build Coastguard Worker }
6399*795d594fSAndroid Build Coastguard Worker if (destination.IsStackSlot()) {
6400*795d594fSAndroid Build Coastguard Worker __ Storew(tmp, SP, destination.GetStackIndex());
6401*795d594fSAndroid Build Coastguard Worker } else {
6402*795d594fSAndroid Build Coastguard Worker __ Stored(tmp, SP, destination.GetStackIndex());
6403*795d594fSAndroid Build Coastguard Worker }
6404*795d594fSAndroid Build Coastguard Worker }
6405*795d594fSAndroid Build Coastguard Worker }
6406*795d594fSAndroid Build Coastguard Worker }
6407*795d594fSAndroid Build Coastguard Worker
AddLocationAsTemp(Location location,LocationSummary * locations)6408*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::AddLocationAsTemp(Location location, LocationSummary* locations) {
6409*795d594fSAndroid Build Coastguard Worker if (location.IsRegister()) {
6410*795d594fSAndroid Build Coastguard Worker locations->AddTemp(location);
6411*795d594fSAndroid Build Coastguard Worker } else {
6412*795d594fSAndroid Build Coastguard Worker UNIMPLEMENTED(FATAL) << "AddLocationAsTemp not implemented for location " << location;
6413*795d594fSAndroid Build Coastguard Worker }
6414*795d594fSAndroid Build Coastguard Worker }
6415*795d594fSAndroid Build Coastguard Worker
SetupBlockedRegisters() const6416*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::SetupBlockedRegisters() const {
6417*795d594fSAndroid Build Coastguard Worker // ZERO, GP, SP, RA, TP and TR(S1) are reserved and can't be allocated.
6418*795d594fSAndroid Build Coastguard Worker blocked_core_registers_[Zero] = true;
6419*795d594fSAndroid Build Coastguard Worker blocked_core_registers_[GP] = true;
6420*795d594fSAndroid Build Coastguard Worker blocked_core_registers_[SP] = true;
6421*795d594fSAndroid Build Coastguard Worker blocked_core_registers_[RA] = true;
6422*795d594fSAndroid Build Coastguard Worker blocked_core_registers_[TP] = true;
6423*795d594fSAndroid Build Coastguard Worker blocked_core_registers_[TR] = true; // ART Thread register.
6424*795d594fSAndroid Build Coastguard Worker
6425*795d594fSAndroid Build Coastguard Worker // TMP(T6), TMP2(T5) and FTMP(FT11) are used as temporary/scratch registers.
6426*795d594fSAndroid Build Coastguard Worker blocked_core_registers_[TMP] = true;
6427*795d594fSAndroid Build Coastguard Worker blocked_core_registers_[TMP2] = true;
6428*795d594fSAndroid Build Coastguard Worker blocked_fpu_registers_[FTMP] = true;
6429*795d594fSAndroid Build Coastguard Worker
6430*795d594fSAndroid Build Coastguard Worker if (GetGraph()->IsDebuggable()) {
6431*795d594fSAndroid Build Coastguard Worker // Stubs do not save callee-save floating point registers. If the graph
6432*795d594fSAndroid Build Coastguard Worker // is debuggable, we need to deal with these registers differently. For
6433*795d594fSAndroid Build Coastguard Worker // now, just block them.
6434*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < arraysize(kFpuCalleeSaves); ++i) {
6435*795d594fSAndroid Build Coastguard Worker blocked_fpu_registers_[kFpuCalleeSaves[i]] = true;
6436*795d594fSAndroid Build Coastguard Worker }
6437*795d594fSAndroid Build Coastguard Worker }
6438*795d594fSAndroid Build Coastguard Worker }
6439*795d594fSAndroid Build Coastguard Worker
SaveCoreRegister(size_t stack_index,uint32_t reg_id)6440*795d594fSAndroid Build Coastguard Worker size_t CodeGeneratorRISCV64::SaveCoreRegister(size_t stack_index, uint32_t reg_id) {
6441*795d594fSAndroid Build Coastguard Worker __ Stored(XRegister(reg_id), SP, stack_index);
6442*795d594fSAndroid Build Coastguard Worker return kRiscv64DoublewordSize;
6443*795d594fSAndroid Build Coastguard Worker }
6444*795d594fSAndroid Build Coastguard Worker
RestoreCoreRegister(size_t stack_index,uint32_t reg_id)6445*795d594fSAndroid Build Coastguard Worker size_t CodeGeneratorRISCV64::RestoreCoreRegister(size_t stack_index, uint32_t reg_id) {
6446*795d594fSAndroid Build Coastguard Worker __ Loadd(XRegister(reg_id), SP, stack_index);
6447*795d594fSAndroid Build Coastguard Worker return kRiscv64DoublewordSize;
6448*795d594fSAndroid Build Coastguard Worker }
6449*795d594fSAndroid Build Coastguard Worker
SaveFloatingPointRegister(size_t stack_index,uint32_t reg_id)6450*795d594fSAndroid Build Coastguard Worker size_t CodeGeneratorRISCV64::SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
6451*795d594fSAndroid Build Coastguard Worker if (GetGraph()->HasSIMD()) {
6452*795d594fSAndroid Build Coastguard Worker // TODO(riscv64): RISC-V vector extension.
6453*795d594fSAndroid Build Coastguard Worker UNIMPLEMENTED(FATAL) << "Vector extension is unsupported";
6454*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
6455*795d594fSAndroid Build Coastguard Worker }
6456*795d594fSAndroid Build Coastguard Worker __ FStored(FRegister(reg_id), SP, stack_index);
6457*795d594fSAndroid Build Coastguard Worker return kRiscv64FloatRegSizeInBytes;
6458*795d594fSAndroid Build Coastguard Worker }
6459*795d594fSAndroid Build Coastguard Worker
RestoreFloatingPointRegister(size_t stack_index,uint32_t reg_id)6460*795d594fSAndroid Build Coastguard Worker size_t CodeGeneratorRISCV64::RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
6461*795d594fSAndroid Build Coastguard Worker if (GetGraph()->HasSIMD()) {
6462*795d594fSAndroid Build Coastguard Worker // TODO(riscv64): RISC-V vector extension.
6463*795d594fSAndroid Build Coastguard Worker UNIMPLEMENTED(FATAL) << "Vector extension is unsupported";
6464*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
6465*795d594fSAndroid Build Coastguard Worker }
6466*795d594fSAndroid Build Coastguard Worker __ FLoadd(FRegister(reg_id), SP, stack_index);
6467*795d594fSAndroid Build Coastguard Worker return kRiscv64FloatRegSizeInBytes;
6468*795d594fSAndroid Build Coastguard Worker }
6469*795d594fSAndroid Build Coastguard Worker
DumpCoreRegister(std::ostream & stream,int reg) const6470*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::DumpCoreRegister(std::ostream& stream, int reg) const {
6471*795d594fSAndroid Build Coastguard Worker stream << XRegister(reg);
6472*795d594fSAndroid Build Coastguard Worker }
6473*795d594fSAndroid Build Coastguard Worker
DumpFloatingPointRegister(std::ostream & stream,int reg) const6474*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
6475*795d594fSAndroid Build Coastguard Worker stream << FRegister(reg);
6476*795d594fSAndroid Build Coastguard Worker }
6477*795d594fSAndroid Build Coastguard Worker
GetInstructionSetFeatures() const6478*795d594fSAndroid Build Coastguard Worker const Riscv64InstructionSetFeatures& CodeGeneratorRISCV64::GetInstructionSetFeatures() const {
6479*795d594fSAndroid Build Coastguard Worker return *GetCompilerOptions().GetInstructionSetFeatures()->AsRiscv64InstructionSetFeatures();
6480*795d594fSAndroid Build Coastguard Worker }
6481*795d594fSAndroid Build Coastguard Worker
Finalize()6482*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::Finalize() {
6483*795d594fSAndroid Build Coastguard Worker // Ensure that we fix up branches and literal loads and emit the literal pool.
6484*795d594fSAndroid Build Coastguard Worker __ FinalizeCode();
6485*795d594fSAndroid Build Coastguard Worker
6486*795d594fSAndroid Build Coastguard Worker // Adjust native pc offsets in stack maps.
6487*795d594fSAndroid Build Coastguard Worker StackMapStream* stack_map_stream = GetStackMapStream();
6488*795d594fSAndroid Build Coastguard Worker for (size_t i = 0, num = stack_map_stream->GetNumberOfStackMaps(); i != num; ++i) {
6489*795d594fSAndroid Build Coastguard Worker uint32_t old_position = stack_map_stream->GetStackMapNativePcOffset(i);
6490*795d594fSAndroid Build Coastguard Worker uint32_t new_position = __ GetAdjustedPosition(old_position);
6491*795d594fSAndroid Build Coastguard Worker DCHECK_GE(new_position, old_position);
6492*795d594fSAndroid Build Coastguard Worker stack_map_stream->SetStackMapNativePcOffset(i, new_position);
6493*795d594fSAndroid Build Coastguard Worker }
6494*795d594fSAndroid Build Coastguard Worker
6495*795d594fSAndroid Build Coastguard Worker // Adjust pc offsets for the disassembly information.
6496*795d594fSAndroid Build Coastguard Worker if (disasm_info_ != nullptr) {
6497*795d594fSAndroid Build Coastguard Worker GeneratedCodeInterval* frame_entry_interval = disasm_info_->GetFrameEntryInterval();
6498*795d594fSAndroid Build Coastguard Worker frame_entry_interval->start = __ GetAdjustedPosition(frame_entry_interval->start);
6499*795d594fSAndroid Build Coastguard Worker frame_entry_interval->end = __ GetAdjustedPosition(frame_entry_interval->end);
6500*795d594fSAndroid Build Coastguard Worker for (auto& entry : *disasm_info_->GetInstructionIntervals()) {
6501*795d594fSAndroid Build Coastguard Worker entry.second.start = __ GetAdjustedPosition(entry.second.start);
6502*795d594fSAndroid Build Coastguard Worker entry.second.end = __ GetAdjustedPosition(entry.second.end);
6503*795d594fSAndroid Build Coastguard Worker }
6504*795d594fSAndroid Build Coastguard Worker for (auto& entry : *disasm_info_->GetSlowPathIntervals()) {
6505*795d594fSAndroid Build Coastguard Worker entry.code_interval.start = __ GetAdjustedPosition(entry.code_interval.start);
6506*795d594fSAndroid Build Coastguard Worker entry.code_interval.end = __ GetAdjustedPosition(entry.code_interval.end);
6507*795d594fSAndroid Build Coastguard Worker }
6508*795d594fSAndroid Build Coastguard Worker }
6509*795d594fSAndroid Build Coastguard Worker }
6510*795d594fSAndroid Build Coastguard Worker
6511*795d594fSAndroid Build Coastguard Worker // Generate code to invoke a runtime entry point.
InvokeRuntime(QuickEntrypointEnum entrypoint,HInstruction * instruction,uint32_t dex_pc,SlowPathCode * slow_path)6512*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::InvokeRuntime(QuickEntrypointEnum entrypoint,
6513*795d594fSAndroid Build Coastguard Worker HInstruction* instruction,
6514*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc,
6515*795d594fSAndroid Build Coastguard Worker SlowPathCode* slow_path) {
6516*795d594fSAndroid Build Coastguard Worker ValidateInvokeRuntime(entrypoint, instruction, slow_path);
6517*795d594fSAndroid Build Coastguard Worker
6518*795d594fSAndroid Build Coastguard Worker ThreadOffset64 entrypoint_offset = GetThreadOffset<kRiscv64PointerSize>(entrypoint);
6519*795d594fSAndroid Build Coastguard Worker
6520*795d594fSAndroid Build Coastguard Worker // TODO(riscv64): Reduce code size for AOT by using shared trampolines for slow path
6521*795d594fSAndroid Build Coastguard Worker // runtime calls across the entire oat file.
6522*795d594fSAndroid Build Coastguard Worker __ Loadd(RA, TR, entrypoint_offset.Int32Value());
6523*795d594fSAndroid Build Coastguard Worker __ Jalr(RA);
6524*795d594fSAndroid Build Coastguard Worker if (EntrypointRequiresStackMap(entrypoint)) {
6525*795d594fSAndroid Build Coastguard Worker RecordPcInfo(instruction, dex_pc, slow_path);
6526*795d594fSAndroid Build Coastguard Worker }
6527*795d594fSAndroid Build Coastguard Worker }
6528*795d594fSAndroid Build Coastguard Worker
6529*795d594fSAndroid Build Coastguard Worker // Generate code to invoke a runtime entry point, but do not record
6530*795d594fSAndroid Build Coastguard Worker // PC-related information in a stack map.
InvokeRuntimeWithoutRecordingPcInfo(int32_t entry_point_offset,HInstruction * instruction,SlowPathCode * slow_path)6531*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::InvokeRuntimeWithoutRecordingPcInfo(int32_t entry_point_offset,
6532*795d594fSAndroid Build Coastguard Worker HInstruction* instruction,
6533*795d594fSAndroid Build Coastguard Worker SlowPathCode* slow_path) {
6534*795d594fSAndroid Build Coastguard Worker ValidateInvokeRuntimeWithoutRecordingPcInfo(instruction, slow_path);
6535*795d594fSAndroid Build Coastguard Worker __ Loadd(RA, TR, entry_point_offset);
6536*795d594fSAndroid Build Coastguard Worker __ Jalr(RA);
6537*795d594fSAndroid Build Coastguard Worker }
6538*795d594fSAndroid Build Coastguard Worker
IncreaseFrame(size_t adjustment)6539*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::IncreaseFrame(size_t adjustment) {
6540*795d594fSAndroid Build Coastguard Worker int32_t adjustment32 = dchecked_integral_cast<int32_t>(adjustment);
6541*795d594fSAndroid Build Coastguard Worker __ AddConst64(SP, SP, -adjustment32);
6542*795d594fSAndroid Build Coastguard Worker GetAssembler()->cfi().AdjustCFAOffset(adjustment32);
6543*795d594fSAndroid Build Coastguard Worker }
6544*795d594fSAndroid Build Coastguard Worker
DecreaseFrame(size_t adjustment)6545*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::DecreaseFrame(size_t adjustment) {
6546*795d594fSAndroid Build Coastguard Worker int32_t adjustment32 = dchecked_integral_cast<int32_t>(adjustment);
6547*795d594fSAndroid Build Coastguard Worker __ AddConst64(SP, SP, adjustment32);
6548*795d594fSAndroid Build Coastguard Worker GetAssembler()->cfi().AdjustCFAOffset(-adjustment32);
6549*795d594fSAndroid Build Coastguard Worker }
6550*795d594fSAndroid Build Coastguard Worker
GenerateNop()6551*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::GenerateNop() {
6552*795d594fSAndroid Build Coastguard Worker __ Nop();
6553*795d594fSAndroid Build Coastguard Worker }
6554*795d594fSAndroid Build Coastguard Worker
GenerateImplicitNullCheck(HNullCheck * instruction)6555*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::GenerateImplicitNullCheck(HNullCheck* instruction) {
6556*795d594fSAndroid Build Coastguard Worker if (CanMoveNullCheckToUser(instruction)) {
6557*795d594fSAndroid Build Coastguard Worker return;
6558*795d594fSAndroid Build Coastguard Worker }
6559*795d594fSAndroid Build Coastguard Worker Location obj = instruction->GetLocations()->InAt(0);
6560*795d594fSAndroid Build Coastguard Worker
6561*795d594fSAndroid Build Coastguard Worker __ Lw(Zero, obj.AsRegister<XRegister>(), 0);
6562*795d594fSAndroid Build Coastguard Worker RecordPcInfo(instruction, instruction->GetDexPc());
6563*795d594fSAndroid Build Coastguard Worker }
6564*795d594fSAndroid Build Coastguard Worker
GenerateExplicitNullCheck(HNullCheck * instruction)6565*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::GenerateExplicitNullCheck(HNullCheck* instruction) {
6566*795d594fSAndroid Build Coastguard Worker SlowPathCodeRISCV64* slow_path = new (GetScopedAllocator()) NullCheckSlowPathRISCV64(instruction);
6567*795d594fSAndroid Build Coastguard Worker AddSlowPath(slow_path);
6568*795d594fSAndroid Build Coastguard Worker
6569*795d594fSAndroid Build Coastguard Worker Location obj = instruction->GetLocations()->InAt(0);
6570*795d594fSAndroid Build Coastguard Worker
6571*795d594fSAndroid Build Coastguard Worker __ Beqz(obj.AsRegister<XRegister>(), slow_path->GetEntryLabel());
6572*795d594fSAndroid Build Coastguard Worker }
6573*795d594fSAndroid Build Coastguard Worker
GetSupportedLoadStringKind(HLoadString::LoadKind desired_string_load_kind)6574*795d594fSAndroid Build Coastguard Worker HLoadString::LoadKind CodeGeneratorRISCV64::GetSupportedLoadStringKind(
6575*795d594fSAndroid Build Coastguard Worker HLoadString::LoadKind desired_string_load_kind) {
6576*795d594fSAndroid Build Coastguard Worker switch (desired_string_load_kind) {
6577*795d594fSAndroid Build Coastguard Worker case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
6578*795d594fSAndroid Build Coastguard Worker case HLoadString::LoadKind::kBootImageRelRo:
6579*795d594fSAndroid Build Coastguard Worker case HLoadString::LoadKind::kBssEntry:
6580*795d594fSAndroid Build Coastguard Worker DCHECK(!Runtime::Current()->UseJitCompilation());
6581*795d594fSAndroid Build Coastguard Worker break;
6582*795d594fSAndroid Build Coastguard Worker case HLoadString::LoadKind::kJitBootImageAddress:
6583*795d594fSAndroid Build Coastguard Worker case HLoadString::LoadKind::kJitTableAddress:
6584*795d594fSAndroid Build Coastguard Worker DCHECK(Runtime::Current()->UseJitCompilation());
6585*795d594fSAndroid Build Coastguard Worker break;
6586*795d594fSAndroid Build Coastguard Worker case HLoadString::LoadKind::kRuntimeCall:
6587*795d594fSAndroid Build Coastguard Worker break;
6588*795d594fSAndroid Build Coastguard Worker }
6589*795d594fSAndroid Build Coastguard Worker return desired_string_load_kind;
6590*795d594fSAndroid Build Coastguard Worker }
6591*795d594fSAndroid Build Coastguard Worker
GetSupportedLoadClassKind(HLoadClass::LoadKind desired_class_load_kind)6592*795d594fSAndroid Build Coastguard Worker HLoadClass::LoadKind CodeGeneratorRISCV64::GetSupportedLoadClassKind(
6593*795d594fSAndroid Build Coastguard Worker HLoadClass::LoadKind desired_class_load_kind) {
6594*795d594fSAndroid Build Coastguard Worker switch (desired_class_load_kind) {
6595*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kInvalid:
6596*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "UNREACHABLE";
6597*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
6598*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kReferrersClass:
6599*795d594fSAndroid Build Coastguard Worker break;
6600*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
6601*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kBootImageRelRo:
6602*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kAppImageRelRo:
6603*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kBssEntry:
6604*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kBssEntryPublic:
6605*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kBssEntryPackage:
6606*795d594fSAndroid Build Coastguard Worker DCHECK(!Runtime::Current()->UseJitCompilation());
6607*795d594fSAndroid Build Coastguard Worker break;
6608*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kJitBootImageAddress:
6609*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kJitTableAddress:
6610*795d594fSAndroid Build Coastguard Worker DCHECK(Runtime::Current()->UseJitCompilation());
6611*795d594fSAndroid Build Coastguard Worker break;
6612*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kRuntimeCall:
6613*795d594fSAndroid Build Coastguard Worker break;
6614*795d594fSAndroid Build Coastguard Worker }
6615*795d594fSAndroid Build Coastguard Worker return desired_class_load_kind;
6616*795d594fSAndroid Build Coastguard Worker }
6617*795d594fSAndroid Build Coastguard Worker
GetSupportedInvokeStaticOrDirectDispatch(const HInvokeStaticOrDirect::DispatchInfo & desired_dispatch_info,ArtMethod * method)6618*795d594fSAndroid Build Coastguard Worker HInvokeStaticOrDirect::DispatchInfo CodeGeneratorRISCV64::GetSupportedInvokeStaticOrDirectDispatch(
6619*795d594fSAndroid Build Coastguard Worker const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info, ArtMethod* method) {
6620*795d594fSAndroid Build Coastguard Worker UNUSED(method);
6621*795d594fSAndroid Build Coastguard Worker // On RISCV64 we support all dispatch types.
6622*795d594fSAndroid Build Coastguard Worker return desired_dispatch_info;
6623*795d594fSAndroid Build Coastguard Worker }
6624*795d594fSAndroid Build Coastguard Worker
NewBootImageIntrinsicPatch(uint32_t intrinsic_data,const PcRelativePatchInfo * info_high)6625*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewBootImageIntrinsicPatch(
6626*795d594fSAndroid Build Coastguard Worker uint32_t intrinsic_data, const PcRelativePatchInfo* info_high) {
6627*795d594fSAndroid Build Coastguard Worker return NewPcRelativePatch(
6628*795d594fSAndroid Build Coastguard Worker /* dex_file= */ nullptr, intrinsic_data, info_high, &boot_image_other_patches_);
6629*795d594fSAndroid Build Coastguard Worker }
6630*795d594fSAndroid Build Coastguard Worker
NewBootImageRelRoPatch(uint32_t boot_image_offset,const PcRelativePatchInfo * info_high)6631*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewBootImageRelRoPatch(
6632*795d594fSAndroid Build Coastguard Worker uint32_t boot_image_offset, const PcRelativePatchInfo* info_high) {
6633*795d594fSAndroid Build Coastguard Worker return NewPcRelativePatch(
6634*795d594fSAndroid Build Coastguard Worker /* dex_file= */ nullptr, boot_image_offset, info_high, &boot_image_other_patches_);
6635*795d594fSAndroid Build Coastguard Worker }
6636*795d594fSAndroid Build Coastguard Worker
NewBootImageMethodPatch(MethodReference target_method,const PcRelativePatchInfo * info_high)6637*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewBootImageMethodPatch(
6638*795d594fSAndroid Build Coastguard Worker MethodReference target_method, const PcRelativePatchInfo* info_high) {
6639*795d594fSAndroid Build Coastguard Worker return NewPcRelativePatch(
6640*795d594fSAndroid Build Coastguard Worker target_method.dex_file, target_method.index, info_high, &boot_image_method_patches_);
6641*795d594fSAndroid Build Coastguard Worker }
6642*795d594fSAndroid Build Coastguard Worker
NewAppImageMethodPatch(MethodReference target_method,const PcRelativePatchInfo * info_high)6643*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewAppImageMethodPatch(
6644*795d594fSAndroid Build Coastguard Worker MethodReference target_method, const PcRelativePatchInfo* info_high) {
6645*795d594fSAndroid Build Coastguard Worker return NewPcRelativePatch(
6646*795d594fSAndroid Build Coastguard Worker target_method.dex_file, target_method.index, info_high, &app_image_method_patches_);
6647*795d594fSAndroid Build Coastguard Worker }
6648*795d594fSAndroid Build Coastguard Worker
NewMethodBssEntryPatch(MethodReference target_method,const PcRelativePatchInfo * info_high)6649*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewMethodBssEntryPatch(
6650*795d594fSAndroid Build Coastguard Worker MethodReference target_method, const PcRelativePatchInfo* info_high) {
6651*795d594fSAndroid Build Coastguard Worker return NewPcRelativePatch(
6652*795d594fSAndroid Build Coastguard Worker target_method.dex_file, target_method.index, info_high, &method_bss_entry_patches_);
6653*795d594fSAndroid Build Coastguard Worker }
6654*795d594fSAndroid Build Coastguard Worker
NewBootImageTypePatch(const DexFile & dex_file,dex::TypeIndex type_index,const PcRelativePatchInfo * info_high)6655*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewBootImageTypePatch(
6656*795d594fSAndroid Build Coastguard Worker const DexFile& dex_file, dex::TypeIndex type_index, const PcRelativePatchInfo* info_high) {
6657*795d594fSAndroid Build Coastguard Worker return NewPcRelativePatch(&dex_file, type_index.index_, info_high, &boot_image_type_patches_);
6658*795d594fSAndroid Build Coastguard Worker }
6659*795d594fSAndroid Build Coastguard Worker
NewAppImageTypePatch(const DexFile & dex_file,dex::TypeIndex type_index,const PcRelativePatchInfo * info_high)6660*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewAppImageTypePatch(
6661*795d594fSAndroid Build Coastguard Worker const DexFile& dex_file, dex::TypeIndex type_index, const PcRelativePatchInfo* info_high) {
6662*795d594fSAndroid Build Coastguard Worker return NewPcRelativePatch(&dex_file, type_index.index_, info_high, &app_image_type_patches_);
6663*795d594fSAndroid Build Coastguard Worker }
6664*795d594fSAndroid Build Coastguard Worker
NewBootImageJniEntrypointPatch(MethodReference target_method,const PcRelativePatchInfo * info_high)6665*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewBootImageJniEntrypointPatch(
6666*795d594fSAndroid Build Coastguard Worker MethodReference target_method, const PcRelativePatchInfo* info_high) {
6667*795d594fSAndroid Build Coastguard Worker return NewPcRelativePatch(
6668*795d594fSAndroid Build Coastguard Worker target_method.dex_file, target_method.index, info_high, &boot_image_jni_entrypoint_patches_);
6669*795d594fSAndroid Build Coastguard Worker }
6670*795d594fSAndroid Build Coastguard Worker
NewTypeBssEntryPatch(HLoadClass * load_class,const PcRelativePatchInfo * info_high)6671*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewTypeBssEntryPatch(
6672*795d594fSAndroid Build Coastguard Worker HLoadClass* load_class,
6673*795d594fSAndroid Build Coastguard Worker const PcRelativePatchInfo* info_high) {
6674*795d594fSAndroid Build Coastguard Worker const DexFile& dex_file = load_class->GetDexFile();
6675*795d594fSAndroid Build Coastguard Worker dex::TypeIndex type_index = load_class->GetTypeIndex();
6676*795d594fSAndroid Build Coastguard Worker ArenaDeque<PcRelativePatchInfo>* patches = nullptr;
6677*795d594fSAndroid Build Coastguard Worker switch (load_class->GetLoadKind()) {
6678*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kBssEntry:
6679*795d594fSAndroid Build Coastguard Worker patches = &type_bss_entry_patches_;
6680*795d594fSAndroid Build Coastguard Worker break;
6681*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kBssEntryPublic:
6682*795d594fSAndroid Build Coastguard Worker patches = &public_type_bss_entry_patches_;
6683*795d594fSAndroid Build Coastguard Worker break;
6684*795d594fSAndroid Build Coastguard Worker case HLoadClass::LoadKind::kBssEntryPackage:
6685*795d594fSAndroid Build Coastguard Worker patches = &package_type_bss_entry_patches_;
6686*795d594fSAndroid Build Coastguard Worker break;
6687*795d594fSAndroid Build Coastguard Worker default:
6688*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected load kind: " << load_class->GetLoadKind();
6689*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
6690*795d594fSAndroid Build Coastguard Worker }
6691*795d594fSAndroid Build Coastguard Worker return NewPcRelativePatch(&dex_file, type_index.index_, info_high, patches);
6692*795d594fSAndroid Build Coastguard Worker }
6693*795d594fSAndroid Build Coastguard Worker
NewBootImageStringPatch(const DexFile & dex_file,dex::StringIndex string_index,const PcRelativePatchInfo * info_high)6694*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewBootImageStringPatch(
6695*795d594fSAndroid Build Coastguard Worker const DexFile& dex_file, dex::StringIndex string_index, const PcRelativePatchInfo* info_high) {
6696*795d594fSAndroid Build Coastguard Worker return NewPcRelativePatch(&dex_file, string_index.index_, info_high, &boot_image_string_patches_);
6697*795d594fSAndroid Build Coastguard Worker }
6698*795d594fSAndroid Build Coastguard Worker
NewStringBssEntryPatch(const DexFile & dex_file,dex::StringIndex string_index,const PcRelativePatchInfo * info_high)6699*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewStringBssEntryPatch(
6700*795d594fSAndroid Build Coastguard Worker const DexFile& dex_file, dex::StringIndex string_index, const PcRelativePatchInfo* info_high) {
6701*795d594fSAndroid Build Coastguard Worker return NewPcRelativePatch(&dex_file, string_index.index_, info_high, &string_bss_entry_patches_);
6702*795d594fSAndroid Build Coastguard Worker }
6703*795d594fSAndroid Build Coastguard Worker
NewPcRelativePatch(const DexFile * dex_file,uint32_t offset_or_index,const PcRelativePatchInfo * info_high,ArenaDeque<PcRelativePatchInfo> * patches)6704*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* CodeGeneratorRISCV64::NewPcRelativePatch(
6705*795d594fSAndroid Build Coastguard Worker const DexFile* dex_file,
6706*795d594fSAndroid Build Coastguard Worker uint32_t offset_or_index,
6707*795d594fSAndroid Build Coastguard Worker const PcRelativePatchInfo* info_high,
6708*795d594fSAndroid Build Coastguard Worker ArenaDeque<PcRelativePatchInfo>* patches) {
6709*795d594fSAndroid Build Coastguard Worker patches->emplace_back(dex_file, offset_or_index, info_high);
6710*795d594fSAndroid Build Coastguard Worker return &patches->back();
6711*795d594fSAndroid Build Coastguard Worker }
6712*795d594fSAndroid Build Coastguard Worker
DeduplicateUint32Literal(uint32_t value)6713*795d594fSAndroid Build Coastguard Worker Literal* CodeGeneratorRISCV64::DeduplicateUint32Literal(uint32_t value) {
6714*795d594fSAndroid Build Coastguard Worker return uint32_literals_.GetOrCreate(value,
6715*795d594fSAndroid Build Coastguard Worker [this, value]() { return __ NewLiteral<uint32_t>(value); });
6716*795d594fSAndroid Build Coastguard Worker }
6717*795d594fSAndroid Build Coastguard Worker
DeduplicateUint64Literal(uint64_t value)6718*795d594fSAndroid Build Coastguard Worker Literal* CodeGeneratorRISCV64::DeduplicateUint64Literal(uint64_t value) {
6719*795d594fSAndroid Build Coastguard Worker return uint64_literals_.GetOrCreate(value,
6720*795d594fSAndroid Build Coastguard Worker [this, value]() { return __ NewLiteral<uint64_t>(value); });
6721*795d594fSAndroid Build Coastguard Worker }
6722*795d594fSAndroid Build Coastguard Worker
DeduplicateBootImageAddressLiteral(uint64_t address)6723*795d594fSAndroid Build Coastguard Worker Literal* CodeGeneratorRISCV64::DeduplicateBootImageAddressLiteral(uint64_t address) {
6724*795d594fSAndroid Build Coastguard Worker return DeduplicateUint32Literal(dchecked_integral_cast<uint32_t>(address));
6725*795d594fSAndroid Build Coastguard Worker }
6726*795d594fSAndroid Build Coastguard Worker
DeduplicateJitStringLiteral(const DexFile & dex_file,dex::StringIndex string_index,Handle<mirror::String> handle)6727*795d594fSAndroid Build Coastguard Worker Literal* CodeGeneratorRISCV64::DeduplicateJitStringLiteral(const DexFile& dex_file,
6728*795d594fSAndroid Build Coastguard Worker dex::StringIndex string_index,
6729*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> handle) {
6730*795d594fSAndroid Build Coastguard Worker ReserveJitStringRoot(StringReference(&dex_file, string_index), handle);
6731*795d594fSAndroid Build Coastguard Worker return jit_string_patches_.GetOrCreate(
6732*795d594fSAndroid Build Coastguard Worker StringReference(&dex_file, string_index),
6733*795d594fSAndroid Build Coastguard Worker [this]() { return __ NewLiteral<uint32_t>(/* value= */ 0u); });
6734*795d594fSAndroid Build Coastguard Worker }
6735*795d594fSAndroid Build Coastguard Worker
DeduplicateJitClassLiteral(const DexFile & dex_file,dex::TypeIndex type_index,Handle<mirror::Class> handle)6736*795d594fSAndroid Build Coastguard Worker Literal* CodeGeneratorRISCV64::DeduplicateJitClassLiteral(const DexFile& dex_file,
6737*795d594fSAndroid Build Coastguard Worker dex::TypeIndex type_index,
6738*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> handle) {
6739*795d594fSAndroid Build Coastguard Worker ReserveJitClassRoot(TypeReference(&dex_file, type_index), handle);
6740*795d594fSAndroid Build Coastguard Worker return jit_class_patches_.GetOrCreate(
6741*795d594fSAndroid Build Coastguard Worker TypeReference(&dex_file, type_index),
6742*795d594fSAndroid Build Coastguard Worker [this]() { return __ NewLiteral<uint32_t>(/* value= */ 0u); });
6743*795d594fSAndroid Build Coastguard Worker }
6744*795d594fSAndroid Build Coastguard Worker
PatchJitRootUse(uint8_t * code,const uint8_t * roots_data,const Literal * literal,uint64_t index_in_table) const6745*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::PatchJitRootUse(uint8_t* code,
6746*795d594fSAndroid Build Coastguard Worker const uint8_t* roots_data,
6747*795d594fSAndroid Build Coastguard Worker const Literal* literal,
6748*795d594fSAndroid Build Coastguard Worker uint64_t index_in_table) const {
6749*795d594fSAndroid Build Coastguard Worker uint32_t literal_offset = GetAssembler().GetLabelLocation(literal->GetLabel());
6750*795d594fSAndroid Build Coastguard Worker uintptr_t address =
6751*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(roots_data) + index_in_table * sizeof(GcRoot<mirror::Object>);
6752*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uint32_t*>(code + literal_offset)[0] = dchecked_integral_cast<uint32_t>(address);
6753*795d594fSAndroid Build Coastguard Worker }
6754*795d594fSAndroid Build Coastguard Worker
EmitJitRootPatches(uint8_t * code,const uint8_t * roots_data)6755*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) {
6756*795d594fSAndroid Build Coastguard Worker for (const auto& entry : jit_string_patches_) {
6757*795d594fSAndroid Build Coastguard Worker const StringReference& string_reference = entry.first;
6758*795d594fSAndroid Build Coastguard Worker Literal* table_entry_literal = entry.second;
6759*795d594fSAndroid Build Coastguard Worker uint64_t index_in_table = GetJitStringRootIndex(string_reference);
6760*795d594fSAndroid Build Coastguard Worker PatchJitRootUse(code, roots_data, table_entry_literal, index_in_table);
6761*795d594fSAndroid Build Coastguard Worker }
6762*795d594fSAndroid Build Coastguard Worker for (const auto& entry : jit_class_patches_) {
6763*795d594fSAndroid Build Coastguard Worker const TypeReference& type_reference = entry.first;
6764*795d594fSAndroid Build Coastguard Worker Literal* table_entry_literal = entry.second;
6765*795d594fSAndroid Build Coastguard Worker uint64_t index_in_table = GetJitClassRootIndex(type_reference);
6766*795d594fSAndroid Build Coastguard Worker PatchJitRootUse(code, roots_data, table_entry_literal, index_in_table);
6767*795d594fSAndroid Build Coastguard Worker }
6768*795d594fSAndroid Build Coastguard Worker }
6769*795d594fSAndroid Build Coastguard Worker
EmitPcRelativeAuipcPlaceholder(PcRelativePatchInfo * info_high,XRegister out)6770*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::EmitPcRelativeAuipcPlaceholder(PcRelativePatchInfo* info_high,
6771*795d594fSAndroid Build Coastguard Worker XRegister out) {
6772*795d594fSAndroid Build Coastguard Worker DCHECK(info_high->pc_insn_label == &info_high->label);
6773*795d594fSAndroid Build Coastguard Worker __ Bind(&info_high->label);
6774*795d594fSAndroid Build Coastguard Worker __ Auipc(out, /*imm20=*/ kLinkTimeOffsetPlaceholderHigh);
6775*795d594fSAndroid Build Coastguard Worker }
6776*795d594fSAndroid Build Coastguard Worker
EmitPcRelativeAddiPlaceholder(PcRelativePatchInfo * info_low,XRegister rd,XRegister rs1)6777*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::EmitPcRelativeAddiPlaceholder(PcRelativePatchInfo* info_low,
6778*795d594fSAndroid Build Coastguard Worker XRegister rd,
6779*795d594fSAndroid Build Coastguard Worker XRegister rs1) {
6780*795d594fSAndroid Build Coastguard Worker DCHECK(info_low->pc_insn_label != &info_low->label);
6781*795d594fSAndroid Build Coastguard Worker __ Bind(&info_low->label);
6782*795d594fSAndroid Build Coastguard Worker __ Addi(rd, rs1, /*imm12=*/ kLinkTimeOffsetPlaceholderLow);
6783*795d594fSAndroid Build Coastguard Worker }
6784*795d594fSAndroid Build Coastguard Worker
EmitPcRelativeLwuPlaceholder(PcRelativePatchInfo * info_low,XRegister rd,XRegister rs1)6785*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::EmitPcRelativeLwuPlaceholder(PcRelativePatchInfo* info_low,
6786*795d594fSAndroid Build Coastguard Worker XRegister rd,
6787*795d594fSAndroid Build Coastguard Worker XRegister rs1) {
6788*795d594fSAndroid Build Coastguard Worker DCHECK(info_low->pc_insn_label != &info_low->label);
6789*795d594fSAndroid Build Coastguard Worker __ Bind(&info_low->label);
6790*795d594fSAndroid Build Coastguard Worker __ Lwu(rd, rs1, /*offset=*/ kLinkTimeOffsetPlaceholderLow);
6791*795d594fSAndroid Build Coastguard Worker }
6792*795d594fSAndroid Build Coastguard Worker
EmitPcRelativeLdPlaceholder(PcRelativePatchInfo * info_low,XRegister rd,XRegister rs1)6793*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::EmitPcRelativeLdPlaceholder(PcRelativePatchInfo* info_low,
6794*795d594fSAndroid Build Coastguard Worker XRegister rd,
6795*795d594fSAndroid Build Coastguard Worker XRegister rs1) {
6796*795d594fSAndroid Build Coastguard Worker DCHECK(info_low->pc_insn_label != &info_low->label);
6797*795d594fSAndroid Build Coastguard Worker __ Bind(&info_low->label);
6798*795d594fSAndroid Build Coastguard Worker __ Ld(rd, rs1, /*offset=*/ kLinkTimeOffsetPlaceholderLow);
6799*795d594fSAndroid Build Coastguard Worker }
6800*795d594fSAndroid Build Coastguard Worker
6801*795d594fSAndroid Build Coastguard Worker template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)>
EmitPcRelativeLinkerPatches(const ArenaDeque<PcRelativePatchInfo> & infos,ArenaVector<linker::LinkerPatch> * linker_patches)6802*795d594fSAndroid Build Coastguard Worker inline void CodeGeneratorRISCV64::EmitPcRelativeLinkerPatches(
6803*795d594fSAndroid Build Coastguard Worker const ArenaDeque<PcRelativePatchInfo>& infos,
6804*795d594fSAndroid Build Coastguard Worker ArenaVector<linker::LinkerPatch>* linker_patches) {
6805*795d594fSAndroid Build Coastguard Worker for (const PcRelativePatchInfo& info : infos) {
6806*795d594fSAndroid Build Coastguard Worker linker_patches->push_back(Factory(__ GetLabelLocation(&info.label),
6807*795d594fSAndroid Build Coastguard Worker info.target_dex_file,
6808*795d594fSAndroid Build Coastguard Worker __ GetLabelLocation(info.pc_insn_label),
6809*795d594fSAndroid Build Coastguard Worker info.offset_or_index));
6810*795d594fSAndroid Build Coastguard Worker }
6811*795d594fSAndroid Build Coastguard Worker }
6812*795d594fSAndroid Build Coastguard Worker
6813*795d594fSAndroid Build Coastguard Worker template <linker::LinkerPatch (*Factory)(size_t, uint32_t, uint32_t)>
NoDexFileAdapter(size_t literal_offset,const DexFile * target_dex_file,uint32_t pc_insn_offset,uint32_t boot_image_offset)6814*795d594fSAndroid Build Coastguard Worker linker::LinkerPatch NoDexFileAdapter(size_t literal_offset,
6815*795d594fSAndroid Build Coastguard Worker const DexFile* target_dex_file,
6816*795d594fSAndroid Build Coastguard Worker uint32_t pc_insn_offset,
6817*795d594fSAndroid Build Coastguard Worker uint32_t boot_image_offset) {
6818*795d594fSAndroid Build Coastguard Worker DCHECK(target_dex_file == nullptr); // Unused for these patches, should be null.
6819*795d594fSAndroid Build Coastguard Worker return Factory(literal_offset, pc_insn_offset, boot_image_offset);
6820*795d594fSAndroid Build Coastguard Worker }
6821*795d594fSAndroid Build Coastguard Worker
EmitLinkerPatches(ArenaVector<linker::LinkerPatch> * linker_patches)6822*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) {
6823*795d594fSAndroid Build Coastguard Worker DCHECK(linker_patches->empty());
6824*795d594fSAndroid Build Coastguard Worker size_t size =
6825*795d594fSAndroid Build Coastguard Worker boot_image_method_patches_.size() +
6826*795d594fSAndroid Build Coastguard Worker app_image_method_patches_.size() +
6827*795d594fSAndroid Build Coastguard Worker method_bss_entry_patches_.size() +
6828*795d594fSAndroid Build Coastguard Worker boot_image_type_patches_.size() +
6829*795d594fSAndroid Build Coastguard Worker app_image_type_patches_.size() +
6830*795d594fSAndroid Build Coastguard Worker type_bss_entry_patches_.size() +
6831*795d594fSAndroid Build Coastguard Worker public_type_bss_entry_patches_.size() +
6832*795d594fSAndroid Build Coastguard Worker package_type_bss_entry_patches_.size() +
6833*795d594fSAndroid Build Coastguard Worker boot_image_string_patches_.size() +
6834*795d594fSAndroid Build Coastguard Worker string_bss_entry_patches_.size() +
6835*795d594fSAndroid Build Coastguard Worker boot_image_jni_entrypoint_patches_.size() +
6836*795d594fSAndroid Build Coastguard Worker boot_image_other_patches_.size();
6837*795d594fSAndroid Build Coastguard Worker linker_patches->reserve(size);
6838*795d594fSAndroid Build Coastguard Worker if (GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension()) {
6839*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeMethodPatch>(
6840*795d594fSAndroid Build Coastguard Worker boot_image_method_patches_, linker_patches);
6841*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeTypePatch>(
6842*795d594fSAndroid Build Coastguard Worker boot_image_type_patches_, linker_patches);
6843*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeStringPatch>(
6844*795d594fSAndroid Build Coastguard Worker boot_image_string_patches_, linker_patches);
6845*795d594fSAndroid Build Coastguard Worker } else {
6846*795d594fSAndroid Build Coastguard Worker DCHECK(boot_image_method_patches_.empty());
6847*795d594fSAndroid Build Coastguard Worker DCHECK(boot_image_type_patches_.empty());
6848*795d594fSAndroid Build Coastguard Worker DCHECK(boot_image_string_patches_.empty());
6849*795d594fSAndroid Build Coastguard Worker }
6850*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_method_patches_.empty());
6851*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(!GetCompilerOptions().IsAppImage(), app_image_type_patches_.empty());
6852*795d594fSAndroid Build Coastguard Worker if (GetCompilerOptions().IsBootImage()) {
6853*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::IntrinsicReferencePatch>>(
6854*795d594fSAndroid Build Coastguard Worker boot_image_other_patches_, linker_patches);
6855*795d594fSAndroid Build Coastguard Worker } else {
6856*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLinkerPatches<NoDexFileAdapter<linker::LinkerPatch::BootImageRelRoPatch>>(
6857*795d594fSAndroid Build Coastguard Worker boot_image_other_patches_, linker_patches);
6858*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodAppImageRelRoPatch>(
6859*795d594fSAndroid Build Coastguard Worker app_image_method_patches_, linker_patches);
6860*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeAppImageRelRoPatch>(
6861*795d594fSAndroid Build Coastguard Worker app_image_type_patches_, linker_patches);
6862*795d594fSAndroid Build Coastguard Worker }
6863*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>(
6864*795d594fSAndroid Build Coastguard Worker method_bss_entry_patches_, linker_patches);
6865*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>(
6866*795d594fSAndroid Build Coastguard Worker type_bss_entry_patches_, linker_patches);
6867*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLinkerPatches<linker::LinkerPatch::PublicTypeBssEntryPatch>(
6868*795d594fSAndroid Build Coastguard Worker public_type_bss_entry_patches_, linker_patches);
6869*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLinkerPatches<linker::LinkerPatch::PackageTypeBssEntryPatch>(
6870*795d594fSAndroid Build Coastguard Worker package_type_bss_entry_patches_, linker_patches);
6871*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>(
6872*795d594fSAndroid Build Coastguard Worker string_bss_entry_patches_, linker_patches);
6873*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeJniEntrypointPatch>(
6874*795d594fSAndroid Build Coastguard Worker boot_image_jni_entrypoint_patches_, linker_patches);
6875*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(size, linker_patches->size());
6876*795d594fSAndroid Build Coastguard Worker }
6877*795d594fSAndroid Build Coastguard Worker
LoadTypeForBootImageIntrinsic(XRegister dest,TypeReference target_type)6878*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::LoadTypeForBootImageIntrinsic(XRegister dest,
6879*795d594fSAndroid Build Coastguard Worker TypeReference target_type) {
6880*795d594fSAndroid Build Coastguard Worker // Load the type the same way as for HLoadClass::LoadKind::kBootImageLinkTimePcRelative.
6881*795d594fSAndroid Build Coastguard Worker DCHECK(GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension());
6882*795d594fSAndroid Build Coastguard Worker PcRelativePatchInfo* info_high =
6883*795d594fSAndroid Build Coastguard Worker NewBootImageTypePatch(*target_type.dex_file, target_type.TypeIndex());
6884*795d594fSAndroid Build Coastguard Worker EmitPcRelativeAuipcPlaceholder(info_high, dest);
6885*795d594fSAndroid Build Coastguard Worker PcRelativePatchInfo* info_low =
6886*795d594fSAndroid Build Coastguard Worker NewBootImageTypePatch(*target_type.dex_file, target_type.TypeIndex(), info_high);
6887*795d594fSAndroid Build Coastguard Worker EmitPcRelativeAddiPlaceholder(info_low, dest, dest);
6888*795d594fSAndroid Build Coastguard Worker }
6889*795d594fSAndroid Build Coastguard Worker
LoadBootImageRelRoEntry(XRegister dest,uint32_t boot_image_offset)6890*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::LoadBootImageRelRoEntry(XRegister dest, uint32_t boot_image_offset) {
6891*795d594fSAndroid Build Coastguard Worker PcRelativePatchInfo* info_high = NewBootImageRelRoPatch(boot_image_offset);
6892*795d594fSAndroid Build Coastguard Worker EmitPcRelativeAuipcPlaceholder(info_high, dest);
6893*795d594fSAndroid Build Coastguard Worker PcRelativePatchInfo* info_low = NewBootImageRelRoPatch(boot_image_offset, info_high);
6894*795d594fSAndroid Build Coastguard Worker // Note: Boot image is in the low 4GiB and the entry is always 32-bit, so emit a 32-bit load.
6895*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLwuPlaceholder(info_low, dest, dest);
6896*795d594fSAndroid Build Coastguard Worker }
6897*795d594fSAndroid Build Coastguard Worker
LoadBootImageAddress(XRegister dest,uint32_t boot_image_reference)6898*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::LoadBootImageAddress(XRegister dest, uint32_t boot_image_reference) {
6899*795d594fSAndroid Build Coastguard Worker if (GetCompilerOptions().IsBootImage()) {
6900*795d594fSAndroid Build Coastguard Worker PcRelativePatchInfo* info_high = NewBootImageIntrinsicPatch(boot_image_reference);
6901*795d594fSAndroid Build Coastguard Worker EmitPcRelativeAuipcPlaceholder(info_high, dest);
6902*795d594fSAndroid Build Coastguard Worker PcRelativePatchInfo* info_low = NewBootImageIntrinsicPatch(boot_image_reference, info_high);
6903*795d594fSAndroid Build Coastguard Worker EmitPcRelativeAddiPlaceholder(info_low, dest, dest);
6904*795d594fSAndroid Build Coastguard Worker } else if (GetCompilerOptions().GetCompilePic()) {
6905*795d594fSAndroid Build Coastguard Worker LoadBootImageRelRoEntry(dest, boot_image_reference);
6906*795d594fSAndroid Build Coastguard Worker } else {
6907*795d594fSAndroid Build Coastguard Worker DCHECK(GetCompilerOptions().IsJitCompiler());
6908*795d594fSAndroid Build Coastguard Worker gc::Heap* heap = Runtime::Current()->GetHeap();
6909*795d594fSAndroid Build Coastguard Worker DCHECK(!heap->GetBootImageSpaces().empty());
6910*795d594fSAndroid Build Coastguard Worker const uint8_t* address = heap->GetBootImageSpaces()[0]->Begin() + boot_image_reference;
6911*795d594fSAndroid Build Coastguard Worker // Note: Boot image is in the low 4GiB (usually the low 2GiB, requiring just LUI+ADDI).
6912*795d594fSAndroid Build Coastguard Worker // We may not have an available scratch register for `LoadConst64()` but it never
6913*795d594fSAndroid Build Coastguard Worker // emits better code than `Li()` for 32-bit unsigned constants anyway.
6914*795d594fSAndroid Build Coastguard Worker __ Li(dest, reinterpret_cast32<uint32_t>(address));
6915*795d594fSAndroid Build Coastguard Worker }
6916*795d594fSAndroid Build Coastguard Worker }
6917*795d594fSAndroid Build Coastguard Worker
LoadIntrinsicDeclaringClass(XRegister dest,HInvoke * invoke)6918*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::LoadIntrinsicDeclaringClass(XRegister dest, HInvoke* invoke) {
6919*795d594fSAndroid Build Coastguard Worker DCHECK_NE(invoke->GetIntrinsic(), Intrinsics::kNone);
6920*795d594fSAndroid Build Coastguard Worker if (GetCompilerOptions().IsBootImage()) {
6921*795d594fSAndroid Build Coastguard Worker MethodReference target_method = invoke->GetResolvedMethodReference();
6922*795d594fSAndroid Build Coastguard Worker dex::TypeIndex type_idx = target_method.dex_file->GetMethodId(target_method.index).class_idx_;
6923*795d594fSAndroid Build Coastguard Worker LoadTypeForBootImageIntrinsic(dest, TypeReference(target_method.dex_file, type_idx));
6924*795d594fSAndroid Build Coastguard Worker } else {
6925*795d594fSAndroid Build Coastguard Worker uint32_t boot_image_offset = GetBootImageOffsetOfIntrinsicDeclaringClass(invoke);
6926*795d594fSAndroid Build Coastguard Worker LoadBootImageAddress(dest, boot_image_offset);
6927*795d594fSAndroid Build Coastguard Worker }
6928*795d594fSAndroid Build Coastguard Worker }
6929*795d594fSAndroid Build Coastguard Worker
LoadClassRootForIntrinsic(XRegister dest,ClassRoot class_root)6930*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::LoadClassRootForIntrinsic(XRegister dest, ClassRoot class_root) {
6931*795d594fSAndroid Build Coastguard Worker if (GetCompilerOptions().IsBootImage()) {
6932*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
6933*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> klass = GetClassRoot(class_root);
6934*795d594fSAndroid Build Coastguard Worker TypeReference target_type(&klass->GetDexFile(), klass->GetDexTypeIndex());
6935*795d594fSAndroid Build Coastguard Worker LoadTypeForBootImageIntrinsic(dest, target_type);
6936*795d594fSAndroid Build Coastguard Worker } else {
6937*795d594fSAndroid Build Coastguard Worker uint32_t boot_image_offset = GetBootImageOffset(class_root);
6938*795d594fSAndroid Build Coastguard Worker LoadBootImageAddress(dest, boot_image_offset);
6939*795d594fSAndroid Build Coastguard Worker }
6940*795d594fSAndroid Build Coastguard Worker }
6941*795d594fSAndroid Build Coastguard Worker
LoadMethod(MethodLoadKind load_kind,Location temp,HInvoke * invoke)6942*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::LoadMethod(MethodLoadKind load_kind, Location temp, HInvoke* invoke) {
6943*795d594fSAndroid Build Coastguard Worker switch (load_kind) {
6944*795d594fSAndroid Build Coastguard Worker case MethodLoadKind::kBootImageLinkTimePcRelative: {
6945*795d594fSAndroid Build Coastguard Worker DCHECK(GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension());
6946*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* info_high =
6947*795d594fSAndroid Build Coastguard Worker NewBootImageMethodPatch(invoke->GetResolvedMethodReference());
6948*795d594fSAndroid Build Coastguard Worker EmitPcRelativeAuipcPlaceholder(info_high, temp.AsRegister<XRegister>());
6949*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* info_low =
6950*795d594fSAndroid Build Coastguard Worker NewBootImageMethodPatch(invoke->GetResolvedMethodReference(), info_high);
6951*795d594fSAndroid Build Coastguard Worker EmitPcRelativeAddiPlaceholder(
6952*795d594fSAndroid Build Coastguard Worker info_low, temp.AsRegister<XRegister>(), temp.AsRegister<XRegister>());
6953*795d594fSAndroid Build Coastguard Worker break;
6954*795d594fSAndroid Build Coastguard Worker }
6955*795d594fSAndroid Build Coastguard Worker case MethodLoadKind::kBootImageRelRo: {
6956*795d594fSAndroid Build Coastguard Worker uint32_t boot_image_offset = GetBootImageOffset(invoke);
6957*795d594fSAndroid Build Coastguard Worker LoadBootImageRelRoEntry(temp.AsRegister<XRegister>(), boot_image_offset);
6958*795d594fSAndroid Build Coastguard Worker break;
6959*795d594fSAndroid Build Coastguard Worker }
6960*795d594fSAndroid Build Coastguard Worker case MethodLoadKind::kAppImageRelRo: {
6961*795d594fSAndroid Build Coastguard Worker DCHECK(GetCompilerOptions().IsAppImage());
6962*795d594fSAndroid Build Coastguard Worker PcRelativePatchInfo* info_high =
6963*795d594fSAndroid Build Coastguard Worker NewAppImageMethodPatch(invoke->GetResolvedMethodReference());
6964*795d594fSAndroid Build Coastguard Worker EmitPcRelativeAuipcPlaceholder(info_high, temp.AsRegister<XRegister>());
6965*795d594fSAndroid Build Coastguard Worker PcRelativePatchInfo* info_low =
6966*795d594fSAndroid Build Coastguard Worker NewAppImageMethodPatch(invoke->GetResolvedMethodReference(), info_high);
6967*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLwuPlaceholder(
6968*795d594fSAndroid Build Coastguard Worker info_low, temp.AsRegister<XRegister>(), temp.AsRegister<XRegister>());
6969*795d594fSAndroid Build Coastguard Worker break;
6970*795d594fSAndroid Build Coastguard Worker }
6971*795d594fSAndroid Build Coastguard Worker case MethodLoadKind::kBssEntry: {
6972*795d594fSAndroid Build Coastguard Worker PcRelativePatchInfo* info_high = NewMethodBssEntryPatch(invoke->GetMethodReference());
6973*795d594fSAndroid Build Coastguard Worker EmitPcRelativeAuipcPlaceholder(info_high, temp.AsRegister<XRegister>());
6974*795d594fSAndroid Build Coastguard Worker PcRelativePatchInfo* info_low =
6975*795d594fSAndroid Build Coastguard Worker NewMethodBssEntryPatch(invoke->GetMethodReference(), info_high);
6976*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLdPlaceholder(
6977*795d594fSAndroid Build Coastguard Worker info_low, temp.AsRegister<XRegister>(), temp.AsRegister<XRegister>());
6978*795d594fSAndroid Build Coastguard Worker break;
6979*795d594fSAndroid Build Coastguard Worker }
6980*795d594fSAndroid Build Coastguard Worker case MethodLoadKind::kJitDirectAddress: {
6981*795d594fSAndroid Build Coastguard Worker __ LoadConst64(temp.AsRegister<XRegister>(),
6982*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uint64_t>(invoke->GetResolvedMethod()));
6983*795d594fSAndroid Build Coastguard Worker break;
6984*795d594fSAndroid Build Coastguard Worker }
6985*795d594fSAndroid Build Coastguard Worker case MethodLoadKind::kRuntimeCall: {
6986*795d594fSAndroid Build Coastguard Worker // Test situation, don't do anything.
6987*795d594fSAndroid Build Coastguard Worker break;
6988*795d594fSAndroid Build Coastguard Worker }
6989*795d594fSAndroid Build Coastguard Worker default: {
6990*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Load kind should have already been handled " << load_kind;
6991*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
6992*795d594fSAndroid Build Coastguard Worker }
6993*795d594fSAndroid Build Coastguard Worker }
6994*795d594fSAndroid Build Coastguard Worker }
6995*795d594fSAndroid Build Coastguard Worker
GenerateStaticOrDirectCall(HInvokeStaticOrDirect * invoke,Location temp,SlowPathCode * slow_path)6996*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke,
6997*795d594fSAndroid Build Coastguard Worker Location temp,
6998*795d594fSAndroid Build Coastguard Worker SlowPathCode* slow_path) {
6999*795d594fSAndroid Build Coastguard Worker // All registers are assumed to be correctly set up per the calling convention.
7000*795d594fSAndroid Build Coastguard Worker Location callee_method = temp; // For all kinds except kRecursive, callee will be in temp.
7001*795d594fSAndroid Build Coastguard Worker
7002*795d594fSAndroid Build Coastguard Worker switch (invoke->GetMethodLoadKind()) {
7003*795d594fSAndroid Build Coastguard Worker case MethodLoadKind::kStringInit: {
7004*795d594fSAndroid Build Coastguard Worker // temp = thread->string_init_entrypoint
7005*795d594fSAndroid Build Coastguard Worker uint32_t offset =
7006*795d594fSAndroid Build Coastguard Worker GetThreadOffset<kRiscv64PointerSize>(invoke->GetStringInitEntryPoint()).Int32Value();
7007*795d594fSAndroid Build Coastguard Worker __ Loadd(temp.AsRegister<XRegister>(), TR, offset);
7008*795d594fSAndroid Build Coastguard Worker break;
7009*795d594fSAndroid Build Coastguard Worker }
7010*795d594fSAndroid Build Coastguard Worker case MethodLoadKind::kRecursive:
7011*795d594fSAndroid Build Coastguard Worker callee_method = invoke->GetLocations()->InAt(invoke->GetCurrentMethodIndex());
7012*795d594fSAndroid Build Coastguard Worker break;
7013*795d594fSAndroid Build Coastguard Worker case MethodLoadKind::kRuntimeCall:
7014*795d594fSAndroid Build Coastguard Worker GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
7015*795d594fSAndroid Build Coastguard Worker return; // No code pointer retrieval; the runtime performs the call directly.
7016*795d594fSAndroid Build Coastguard Worker case MethodLoadKind::kBootImageLinkTimePcRelative:
7017*795d594fSAndroid Build Coastguard Worker DCHECK(GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension());
7018*795d594fSAndroid Build Coastguard Worker if (invoke->GetCodePtrLocation() == CodePtrLocation::kCallCriticalNative) {
7019*795d594fSAndroid Build Coastguard Worker // Do not materialize the method pointer, load directly the entrypoint.
7020*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* info_high =
7021*795d594fSAndroid Build Coastguard Worker NewBootImageJniEntrypointPatch(invoke->GetResolvedMethodReference());
7022*795d594fSAndroid Build Coastguard Worker EmitPcRelativeAuipcPlaceholder(info_high, RA);
7023*795d594fSAndroid Build Coastguard Worker CodeGeneratorRISCV64::PcRelativePatchInfo* info_low =
7024*795d594fSAndroid Build Coastguard Worker NewBootImageJniEntrypointPatch(invoke->GetResolvedMethodReference(), info_high);
7025*795d594fSAndroid Build Coastguard Worker EmitPcRelativeLdPlaceholder(info_low, RA, RA);
7026*795d594fSAndroid Build Coastguard Worker break;
7027*795d594fSAndroid Build Coastguard Worker }
7028*795d594fSAndroid Build Coastguard Worker FALLTHROUGH_INTENDED;
7029*795d594fSAndroid Build Coastguard Worker default:
7030*795d594fSAndroid Build Coastguard Worker LoadMethod(invoke->GetMethodLoadKind(), temp, invoke);
7031*795d594fSAndroid Build Coastguard Worker break;
7032*795d594fSAndroid Build Coastguard Worker }
7033*795d594fSAndroid Build Coastguard Worker
7034*795d594fSAndroid Build Coastguard Worker switch (invoke->GetCodePtrLocation()) {
7035*795d594fSAndroid Build Coastguard Worker case CodePtrLocation::kCallSelf:
7036*795d594fSAndroid Build Coastguard Worker DCHECK(!GetGraph()->HasShouldDeoptimizeFlag());
7037*795d594fSAndroid Build Coastguard Worker __ Jal(&frame_entry_label_);
7038*795d594fSAndroid Build Coastguard Worker RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
7039*795d594fSAndroid Build Coastguard Worker break;
7040*795d594fSAndroid Build Coastguard Worker case CodePtrLocation::kCallArtMethod:
7041*795d594fSAndroid Build Coastguard Worker // RA = callee_method->entry_point_from_quick_compiled_code_;
7042*795d594fSAndroid Build Coastguard Worker __ Loadd(RA,
7043*795d594fSAndroid Build Coastguard Worker callee_method.AsRegister<XRegister>(),
7044*795d594fSAndroid Build Coastguard Worker ArtMethod::EntryPointFromQuickCompiledCodeOffset(kRiscv64PointerSize).Int32Value());
7045*795d594fSAndroid Build Coastguard Worker // RA()
7046*795d594fSAndroid Build Coastguard Worker __ Jalr(RA);
7047*795d594fSAndroid Build Coastguard Worker RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
7048*795d594fSAndroid Build Coastguard Worker break;
7049*795d594fSAndroid Build Coastguard Worker case CodePtrLocation::kCallCriticalNative: {
7050*795d594fSAndroid Build Coastguard Worker size_t out_frame_size =
7051*795d594fSAndroid Build Coastguard Worker PrepareCriticalNativeCall<CriticalNativeCallingConventionVisitorRiscv64,
7052*795d594fSAndroid Build Coastguard Worker kNativeStackAlignment,
7053*795d594fSAndroid Build Coastguard Worker GetCriticalNativeDirectCallFrameSize>(invoke);
7054*795d594fSAndroid Build Coastguard Worker if (invoke->GetMethodLoadKind() == MethodLoadKind::kBootImageLinkTimePcRelative) {
7055*795d594fSAndroid Build Coastguard Worker // Entrypoint is already loaded in RA.
7056*795d594fSAndroid Build Coastguard Worker } else {
7057*795d594fSAndroid Build Coastguard Worker // RA = callee_method->ptr_sized_fields_.data_; // EntryPointFromJni
7058*795d594fSAndroid Build Coastguard Worker MemberOffset offset = ArtMethod::EntryPointFromJniOffset(kRiscv64PointerSize);
7059*795d594fSAndroid Build Coastguard Worker __ Loadd(RA, callee_method.AsRegister<XRegister>(), offset.Int32Value());
7060*795d594fSAndroid Build Coastguard Worker }
7061*795d594fSAndroid Build Coastguard Worker __ Jalr(RA);
7062*795d594fSAndroid Build Coastguard Worker RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
7063*795d594fSAndroid Build Coastguard Worker // The result is returned the same way in native ABI and managed ABI. No result conversion is
7064*795d594fSAndroid Build Coastguard Worker // needed, see comments in `Riscv64JniCallingConvention::RequiresSmallResultTypeExtension()`.
7065*795d594fSAndroid Build Coastguard Worker if (out_frame_size != 0u) {
7066*795d594fSAndroid Build Coastguard Worker DecreaseFrame(out_frame_size);
7067*795d594fSAndroid Build Coastguard Worker }
7068*795d594fSAndroid Build Coastguard Worker break;
7069*795d594fSAndroid Build Coastguard Worker }
7070*795d594fSAndroid Build Coastguard Worker }
7071*795d594fSAndroid Build Coastguard Worker
7072*795d594fSAndroid Build Coastguard Worker DCHECK(!IsLeafMethod());
7073*795d594fSAndroid Build Coastguard Worker }
7074*795d594fSAndroid Build Coastguard Worker
MaybeGenerateInlineCacheCheck(HInstruction * instruction,XRegister klass)7075*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::MaybeGenerateInlineCacheCheck(HInstruction* instruction,
7076*795d594fSAndroid Build Coastguard Worker XRegister klass) {
7077*795d594fSAndroid Build Coastguard Worker if (ProfilingInfoBuilder::IsInlineCacheUseful(instruction->AsInvoke(), this)) {
7078*795d594fSAndroid Build Coastguard Worker ProfilingInfo* info = GetGraph()->GetProfilingInfo();
7079*795d594fSAndroid Build Coastguard Worker DCHECK(info != nullptr);
7080*795d594fSAndroid Build Coastguard Worker InlineCache* cache = ProfilingInfoBuilder::GetInlineCache(
7081*795d594fSAndroid Build Coastguard Worker info, GetCompilerOptions(), instruction->AsInvoke());
7082*795d594fSAndroid Build Coastguard Worker if (cache != nullptr) {
7083*795d594fSAndroid Build Coastguard Worker uint64_t address = reinterpret_cast64<uint64_t>(cache);
7084*795d594fSAndroid Build Coastguard Worker Riscv64Label done;
7085*795d594fSAndroid Build Coastguard Worker // The `art_quick_update_inline_cache` expects the inline cache in T5.
7086*795d594fSAndroid Build Coastguard Worker XRegister ic_reg = T5;
7087*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
7088*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(srs.AvailableXRegisters(), 2u);
7089*795d594fSAndroid Build Coastguard Worker srs.ExcludeXRegister(ic_reg);
7090*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(srs.AvailableXRegisters(), 1u);
7091*795d594fSAndroid Build Coastguard Worker __ LoadConst64(ic_reg, address);
7092*795d594fSAndroid Build Coastguard Worker {
7093*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs2(GetAssembler());
7094*795d594fSAndroid Build Coastguard Worker XRegister tmp = srs2.AllocateXRegister();
7095*795d594fSAndroid Build Coastguard Worker __ Loadd(tmp, ic_reg, InlineCache::ClassesOffset().Int32Value());
7096*795d594fSAndroid Build Coastguard Worker // Fast path for a monomorphic cache.
7097*795d594fSAndroid Build Coastguard Worker __ Beq(klass, tmp, &done);
7098*795d594fSAndroid Build Coastguard Worker }
7099*795d594fSAndroid Build Coastguard Worker InvokeRuntime(kQuickUpdateInlineCache, instruction, instruction->GetDexPc());
7100*795d594fSAndroid Build Coastguard Worker __ Bind(&done);
7101*795d594fSAndroid Build Coastguard Worker } else {
7102*795d594fSAndroid Build Coastguard Worker // This is unexpected, but we don't guarantee stable compilation across
7103*795d594fSAndroid Build Coastguard Worker // JIT runs so just warn about it.
7104*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
7105*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "Missing inline cache for " << GetGraph()->GetArtMethod()->PrettyMethod();
7106*795d594fSAndroid Build Coastguard Worker }
7107*795d594fSAndroid Build Coastguard Worker }
7108*795d594fSAndroid Build Coastguard Worker }
7109*795d594fSAndroid Build Coastguard Worker
GenerateVirtualCall(HInvokeVirtual * invoke,Location temp_location,SlowPathCode * slow_path)7110*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::GenerateVirtualCall(HInvokeVirtual* invoke,
7111*795d594fSAndroid Build Coastguard Worker Location temp_location,
7112*795d594fSAndroid Build Coastguard Worker SlowPathCode* slow_path) {
7113*795d594fSAndroid Build Coastguard Worker // Use the calling convention instead of the location of the receiver, as
7114*795d594fSAndroid Build Coastguard Worker // intrinsics may have put the receiver in a different register. In the intrinsics
7115*795d594fSAndroid Build Coastguard Worker // slow path, the arguments have been moved to the right place, so here we are
7116*795d594fSAndroid Build Coastguard Worker // guaranteed that the receiver is the first register of the calling convention.
7117*795d594fSAndroid Build Coastguard Worker InvokeDexCallingConvention calling_convention;
7118*795d594fSAndroid Build Coastguard Worker XRegister receiver = calling_convention.GetRegisterAt(0);
7119*795d594fSAndroid Build Coastguard Worker XRegister temp = temp_location.AsRegister<XRegister>();
7120*795d594fSAndroid Build Coastguard Worker MemberOffset method_offset =
7121*795d594fSAndroid Build Coastguard Worker mirror::Class::EmbeddedVTableEntryOffset(invoke->GetVTableIndex(), kRiscv64PointerSize);
7122*795d594fSAndroid Build Coastguard Worker MemberOffset class_offset = mirror::Object::ClassOffset();
7123*795d594fSAndroid Build Coastguard Worker Offset entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kRiscv64PointerSize);
7124*795d594fSAndroid Build Coastguard Worker
7125*795d594fSAndroid Build Coastguard Worker // temp = object->GetClass();
7126*795d594fSAndroid Build Coastguard Worker __ Loadwu(temp, receiver, class_offset.Int32Value());
7127*795d594fSAndroid Build Coastguard Worker MaybeRecordImplicitNullCheck(invoke);
7128*795d594fSAndroid Build Coastguard Worker // Instead of simply (possibly) unpoisoning `temp` here, we should
7129*795d594fSAndroid Build Coastguard Worker // emit a read barrier for the previous class reference load.
7130*795d594fSAndroid Build Coastguard Worker // However this is not required in practice, as this is an
7131*795d594fSAndroid Build Coastguard Worker // intermediate/temporary reference and because the current
7132*795d594fSAndroid Build Coastguard Worker // concurrent copying collector keeps the from-space memory
7133*795d594fSAndroid Build Coastguard Worker // intact/accessible until the end of the marking phase (the
7134*795d594fSAndroid Build Coastguard Worker // concurrent copying collector may not in the future).
7135*795d594fSAndroid Build Coastguard Worker MaybeUnpoisonHeapReference(temp);
7136*795d594fSAndroid Build Coastguard Worker
7137*795d594fSAndroid Build Coastguard Worker // If we're compiling baseline, update the inline cache.
7138*795d594fSAndroid Build Coastguard Worker MaybeGenerateInlineCacheCheck(invoke, temp);
7139*795d594fSAndroid Build Coastguard Worker
7140*795d594fSAndroid Build Coastguard Worker // temp = temp->GetMethodAt(method_offset);
7141*795d594fSAndroid Build Coastguard Worker __ Loadd(temp, temp, method_offset.Int32Value());
7142*795d594fSAndroid Build Coastguard Worker // RA = temp->GetEntryPoint();
7143*795d594fSAndroid Build Coastguard Worker __ Loadd(RA, temp, entry_point.Int32Value());
7144*795d594fSAndroid Build Coastguard Worker // RA();
7145*795d594fSAndroid Build Coastguard Worker __ Jalr(RA);
7146*795d594fSAndroid Build Coastguard Worker RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
7147*795d594fSAndroid Build Coastguard Worker }
7148*795d594fSAndroid Build Coastguard Worker
MoveFromReturnRegister(Location trg,DataType::Type type)7149*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::MoveFromReturnRegister(Location trg, DataType::Type type) {
7150*795d594fSAndroid Build Coastguard Worker if (!trg.IsValid()) {
7151*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(type, DataType::Type::kVoid);
7152*795d594fSAndroid Build Coastguard Worker return;
7153*795d594fSAndroid Build Coastguard Worker }
7154*795d594fSAndroid Build Coastguard Worker
7155*795d594fSAndroid Build Coastguard Worker DCHECK_NE(type, DataType::Type::kVoid);
7156*795d594fSAndroid Build Coastguard Worker
7157*795d594fSAndroid Build Coastguard Worker if (DataType::IsIntegralType(type) || type == DataType::Type::kReference) {
7158*795d594fSAndroid Build Coastguard Worker XRegister trg_reg = trg.AsRegister<XRegister>();
7159*795d594fSAndroid Build Coastguard Worker XRegister res_reg = Riscv64ReturnLocation(type).AsRegister<XRegister>();
7160*795d594fSAndroid Build Coastguard Worker if (trg_reg != res_reg) {
7161*795d594fSAndroid Build Coastguard Worker __ Mv(trg_reg, res_reg);
7162*795d594fSAndroid Build Coastguard Worker }
7163*795d594fSAndroid Build Coastguard Worker } else {
7164*795d594fSAndroid Build Coastguard Worker FRegister trg_reg = trg.AsFpuRegister<FRegister>();
7165*795d594fSAndroid Build Coastguard Worker FRegister res_reg = Riscv64ReturnLocation(type).AsFpuRegister<FRegister>();
7166*795d594fSAndroid Build Coastguard Worker if (trg_reg != res_reg) {
7167*795d594fSAndroid Build Coastguard Worker __ FMvD(trg_reg, res_reg); // 64-bit move is OK also for `float`.
7168*795d594fSAndroid Build Coastguard Worker }
7169*795d594fSAndroid Build Coastguard Worker }
7170*795d594fSAndroid Build Coastguard Worker }
7171*795d594fSAndroid Build Coastguard Worker
PoisonHeapReference(XRegister reg)7172*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::PoisonHeapReference(XRegister reg) {
7173*795d594fSAndroid Build Coastguard Worker __ Sub(reg, Zero, reg); // Negate the ref.
7174*795d594fSAndroid Build Coastguard Worker __ ZextW(reg, reg); // Zero-extend the 32-bit ref.
7175*795d594fSAndroid Build Coastguard Worker }
7176*795d594fSAndroid Build Coastguard Worker
UnpoisonHeapReference(XRegister reg)7177*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::UnpoisonHeapReference(XRegister reg) {
7178*795d594fSAndroid Build Coastguard Worker __ Sub(reg, Zero, reg); // Negate the ref.
7179*795d594fSAndroid Build Coastguard Worker __ ZextW(reg, reg); // Zero-extend the 32-bit ref.
7180*795d594fSAndroid Build Coastguard Worker }
7181*795d594fSAndroid Build Coastguard Worker
MaybePoisonHeapReference(XRegister reg)7182*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::MaybePoisonHeapReference(XRegister reg) {
7183*795d594fSAndroid Build Coastguard Worker if (kPoisonHeapReferences) {
7184*795d594fSAndroid Build Coastguard Worker PoisonHeapReference(reg);
7185*795d594fSAndroid Build Coastguard Worker }
7186*795d594fSAndroid Build Coastguard Worker }
7187*795d594fSAndroid Build Coastguard Worker
MaybeUnpoisonHeapReference(XRegister reg)7188*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::MaybeUnpoisonHeapReference(XRegister reg) {
7189*795d594fSAndroid Build Coastguard Worker if (kPoisonHeapReferences) {
7190*795d594fSAndroid Build Coastguard Worker UnpoisonHeapReference(reg);
7191*795d594fSAndroid Build Coastguard Worker }
7192*795d594fSAndroid Build Coastguard Worker }
7193*795d594fSAndroid Build Coastguard Worker
SwapLocations(Location loc1,Location loc2,DataType::Type type)7194*795d594fSAndroid Build Coastguard Worker void CodeGeneratorRISCV64::SwapLocations(Location loc1, Location loc2, DataType::Type type) {
7195*795d594fSAndroid Build Coastguard Worker DCHECK(!loc1.IsConstant());
7196*795d594fSAndroid Build Coastguard Worker DCHECK(!loc2.IsConstant());
7197*795d594fSAndroid Build Coastguard Worker
7198*795d594fSAndroid Build Coastguard Worker if (loc1.Equals(loc2)) {
7199*795d594fSAndroid Build Coastguard Worker return;
7200*795d594fSAndroid Build Coastguard Worker }
7201*795d594fSAndroid Build Coastguard Worker
7202*795d594fSAndroid Build Coastguard Worker bool is_slot1 = loc1.IsStackSlot() || loc1.IsDoubleStackSlot();
7203*795d594fSAndroid Build Coastguard Worker bool is_slot2 = loc2.IsStackSlot() || loc2.IsDoubleStackSlot();
7204*795d594fSAndroid Build Coastguard Worker bool is_simd1 = loc1.IsSIMDStackSlot();
7205*795d594fSAndroid Build Coastguard Worker bool is_simd2 = loc2.IsSIMDStackSlot();
7206*795d594fSAndroid Build Coastguard Worker bool is_fp_reg1 = loc1.IsFpuRegister();
7207*795d594fSAndroid Build Coastguard Worker bool is_fp_reg2 = loc2.IsFpuRegister();
7208*795d594fSAndroid Build Coastguard Worker
7209*795d594fSAndroid Build Coastguard Worker if ((is_slot1 != is_slot2) ||
7210*795d594fSAndroid Build Coastguard Worker (loc2.IsRegister() && loc1.IsRegister()) ||
7211*795d594fSAndroid Build Coastguard Worker (is_fp_reg2 && is_fp_reg1)) {
7212*795d594fSAndroid Build Coastguard Worker if ((is_fp_reg2 && is_fp_reg1) && GetGraph()->HasSIMD()) {
7213*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unsupported";
7214*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
7215*795d594fSAndroid Build Coastguard Worker }
7216*795d594fSAndroid Build Coastguard Worker ScratchRegisterScope srs(GetAssembler());
7217*795d594fSAndroid Build Coastguard Worker Location tmp = (is_fp_reg2 || is_fp_reg1)
7218*795d594fSAndroid Build Coastguard Worker ? Location::FpuRegisterLocation(srs.AllocateFRegister())
7219*795d594fSAndroid Build Coastguard Worker : Location::RegisterLocation(srs.AllocateXRegister());
7220*795d594fSAndroid Build Coastguard Worker MoveLocation(tmp, loc1, type);
7221*795d594fSAndroid Build Coastguard Worker MoveLocation(loc1, loc2, type);
7222*795d594fSAndroid Build Coastguard Worker MoveLocation(loc2, tmp, type);
7223*795d594fSAndroid Build Coastguard Worker } else if (is_slot1 && is_slot2) {
7224*795d594fSAndroid Build Coastguard Worker move_resolver_.Exchange(loc1.GetStackIndex(), loc2.GetStackIndex(), loc1.IsDoubleStackSlot());
7225*795d594fSAndroid Build Coastguard Worker } else if (is_simd1 && is_simd2) {
7226*795d594fSAndroid Build Coastguard Worker // TODO(riscv64): Add VECTOR/SIMD later.
7227*795d594fSAndroid Build Coastguard Worker UNIMPLEMENTED(FATAL) << "Vector extension is unsupported";
7228*795d594fSAndroid Build Coastguard Worker } else if ((is_fp_reg1 && is_simd2) || (is_fp_reg2 && is_simd1)) {
7229*795d594fSAndroid Build Coastguard Worker // TODO(riscv64): Add VECTOR/SIMD later.
7230*795d594fSAndroid Build Coastguard Worker UNIMPLEMENTED(FATAL) << "Vector extension is unsupported";
7231*795d594fSAndroid Build Coastguard Worker } else {
7232*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unimplemented swap between locations " << loc1 << " and " << loc2;
7233*795d594fSAndroid Build Coastguard Worker }
7234*795d594fSAndroid Build Coastguard Worker }
7235*795d594fSAndroid Build Coastguard Worker
7236*795d594fSAndroid Build Coastguard Worker } // namespace riscv64
7237*795d594fSAndroid Build Coastguard Worker } // namespace art
7238