8290154: [JVMCI] partially implement JVMCI for RISC-V

Reviewed-by: ihse, dnsimon, yadongwang
This commit is contained in:
Sacha Coppey 2022-10-07 13:09:09 +00:00 committed by Doug Simon
parent b38bed6d0e
commit 7a194d31a3
20 changed files with 1722 additions and 22 deletions

View File

@ -275,6 +275,8 @@ AC_DEFUN_ONCE([JVM_FEATURES_CHECK_JVMCI],
AC_MSG_RESULT([yes])
elif test "x$OPENJDK_TARGET_CPU" = "xaarch64"; then
AC_MSG_RESULT([yes])
elif test "x$OPENJDK_TARGET_CPU" = "xriscv64"; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no, $OPENJDK_TARGET_CPU])
AVAILABLE=false

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "jvmci/jvmci.hpp"
#include "jvmci/jvmciCodeInstaller.hpp"
#include "jvmci/jvmciRuntime.hpp"
#include "jvmci/jvmciCompilerToVM.hpp"
#include "jvmci/jvmciJavaClasses.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/sharedRuntime.hpp"
#include "vmreg_riscv.inline.hpp"
jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, JVMCI_TRAPS) {
address pc = (address) inst;
if (inst->is_call()) {
return pc_offset + NativeCall::instruction_size;
} else if (inst->is_jump()) {
return pc_offset + NativeJump::instruction_size;
} else if (inst->is_movptr()) {
return pc_offset + NativeMovConstReg::movptr_instruction_size;
} else {
JVMCI_ERROR_0("unsupported type of instruction for call site");
}
}
void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& obj, bool compressed, JVMCI_TRAPS) {
address pc = _instructions->start() + pc_offset;
jobject value = JNIHandles::make_local(obj());
MacroAssembler::patch_oop(pc, cast_from_oop<address>(obj()));
int oop_index = _oop_recorder->find_index(value);
RelocationHolder rspec = oop_Relocation::spec(oop_index);
_instructions->relocate(pc, rspec);
}
void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, HotSpotCompiledCodeStream* stream, u1 tag, JVMCI_TRAPS) {
address pc = _instructions->start() + pc_offset;
if (tag == PATCH_NARROW_KLASS) {
narrowKlass narrowOop = record_narrow_metadata_reference(_instructions, pc, stream, tag, JVMCI_CHECK);
MacroAssembler::pd_patch_instruction_size(pc, (address) (long) narrowOop);
JVMCI_event_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/0x%x", p2i(pc), narrowOop);
} else {
NativeMovConstReg* move = nativeMovConstReg_at(pc);
void* reference = record_metadata_reference(_instructions, pc, stream, tag, JVMCI_CHECK);
move->set_data((intptr_t) reference);
JVMCI_event_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(reference));
}
}
void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, JVMCI_TRAPS) {
address pc = _instructions->start() + pc_offset;
address dest = _constants->start() + data_offset;
_instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS));
JVMCI_event_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset);
}
void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, JVMCI_TRAPS) {
address pc = (address) inst;
if (inst->is_jal()) {
NativeCall* call = nativeCall_at(pc);
call->set_destination((address) foreign_call_destination);
_instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec());
} else if (inst->is_jump()) {
NativeJump* jump = nativeJump_at(pc);
jump->set_jump_destination((address) foreign_call_destination);
_instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec());
} else if (inst->is_movptr()) {
NativeMovConstReg* movptr = nativeMovConstReg_at(pc);
movptr->set_data((intptr_t) foreign_call_destination);
_instructions->relocate(movptr->instruction_address(), runtime_call_Relocation::spec());
} else {
JVMCI_ERROR("unknown call or jump instruction at " PTR_FORMAT, p2i(pc));
}
JVMCI_event_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst));
}
void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &cbuf, methodHandle& method, jint pc_offset, JVMCI_TRAPS) {
Unimplemented();
}
void CodeInstaller::pd_relocate_poll(address pc, jint mark, JVMCI_TRAPS) {
Unimplemented();
}
// convert JVMCI register indices (as used in oop maps) to HotSpot registers
VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, JVMCI_TRAPS) {
if (jvmci_reg < Register::number_of_registers) {
return as_Register(jvmci_reg)->as_VMReg();
} else {
jint floatRegisterNumber = jvmci_reg - Register::number_of_registers;
if (floatRegisterNumber >= 0 && floatRegisterNumber < FloatRegister::number_of_registers) {
return as_FloatRegister(floatRegisterNumber)->as_VMReg();
}
JVMCI_ERROR_NULL("invalid register number: %d", jvmci_reg);
}
}
bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) {
return !(hotspotRegister->is_FloatRegister() || hotspotRegister->is_VectorRegister());
}

View File

@ -56,6 +56,9 @@
#include "adfiles/ad_riscv.hpp"
#include "opto/runtime.hpp"
#endif
#if INCLUDE_JVMCI
#include "jvmci/jvmciJavaClasses.hpp"
#endif
#define __ masm->
@ -208,6 +211,9 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm) {
#ifdef COMPILER2
__ pop_CPU_state(_save_vectors, Matcher::scalable_vector_reg_size(T_BYTE));
#else
#if !INCLUDE_JVMCI
assert(!_save_vectors, "vectors are generated only by C2 and JVMCI");
#endif
__ pop_CPU_state(_save_vectors);
#endif
__ leave();
@ -493,6 +499,18 @@ void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
// Pre-load the register-jump target early, to schedule it better.
__ ld(t1, Address(xmethod, in_bytes(Method::from_compiled_offset())));
#if INCLUDE_JVMCI
if (EnableJVMCI) {
// check if this call should be routed towards a specific entry point
__ ld(t0, Address(xthread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())));
Label no_alternative_target;
__ beqz(t0, no_alternative_target);
__ mv(t1, t0);
__ sd(zr, Address(xthread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())));
__ bind(no_alternative_target);
}
#endif // INCLUDE_JVMCI
// Now generate the shuffle code.
for (int i = 0; i < total_args_passed; i++) {
if (sig_bt[i] == T_VOID) {
@ -1675,6 +1693,11 @@ void SharedRuntime::generate_deopt_blob() {
ResourceMark rm;
// Setup code generation tools
int pad = 0;
#if INCLUDE_JVMCI
if (EnableJVMCI) {
pad += 512; // Increase the buffer size when compiling for JVMCI
}
#endif
CodeBuffer buffer("deopt_blob", 2048 + pad, 1024);
MacroAssembler* masm = new MacroAssembler(&buffer);
int frame_size_in_words = -1;
@ -1726,6 +1749,12 @@ void SharedRuntime::generate_deopt_blob() {
__ j(cont);
int reexecute_offset = __ pc() - start;
#if INCLUDE_JVMCI && !defined(COMPILER1)
if (EnableJVMCI && UseJVMCICompiler) {
// JVMCI does not use this kind of deoptimization
__ should_not_reach_here();
}
#endif
// Reexecute case
// return address is the pc describes what bci to do re-execute at
@ -1736,6 +1765,44 @@ void SharedRuntime::generate_deopt_blob() {
__ mvw(xcpool, Deoptimization::Unpack_reexecute); // callee-saved
__ j(cont);
#if INCLUDE_JVMCI
Label after_fetch_unroll_info_call;
int implicit_exception_uncommon_trap_offset = 0;
int uncommon_trap_offset = 0;
if (EnableJVMCI) {
implicit_exception_uncommon_trap_offset = __ pc() - start;
__ ld(ra, Address(xthread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset())));
__ sd(zr, Address(xthread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset())));
uncommon_trap_offset = __ pc() - start;
// Save everything in sight.
reg_saver.save_live_registers(masm, 0, &frame_size_in_words);
// fetch_unroll_info needs to call last_java_frame()
Label retaddr;
__ set_last_Java_frame(sp, noreg, retaddr, t0);
__ lw(c_rarg1, Address(xthread, in_bytes(JavaThread::pending_deoptimization_offset())));
__ mvw(t0, -1);
__ sw(t0, Address(xthread, in_bytes(JavaThread::pending_deoptimization_offset())));
__ mvw(xcpool, (int32_t)Deoptimization::Unpack_reexecute);
__ mv(c_rarg0, xthread);
__ orrw(c_rarg2, zr, xcpool); // exec mode
int32_t offset = 0;
__ la_patchable(t0, RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)), offset);
__ jalr(x1, t0, offset);
__ bind(retaddr);
oop_maps->add_gc_map( __ pc()-start, map->deep_copy());
__ reset_last_Java_frame(false);
__ j(after_fetch_unroll_info_call);
} // EnableJVMCI
#endif // INCLUDE_JVMCI
int exception_offset = __ pc() - start;
// Prolog for exception case
@ -1829,6 +1896,12 @@ void SharedRuntime::generate_deopt_blob() {
__ reset_last_Java_frame(false);
#if INCLUDE_JVMCI
if (EnableJVMCI) {
__ bind(after_fetch_unroll_info_call);
}
#endif
// Load UnrollBlock* into x15
__ mv(x15, x10);
@ -1984,6 +2057,12 @@ void SharedRuntime::generate_deopt_blob() {
_deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words);
assert(_deopt_blob != NULL, "create deoptimization blob fail!");
_deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset);
#if INCLUDE_JVMCI
if (EnableJVMCI) {
_deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset);
_deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset);
}
#endif
}
// Number of stack slots between incoming argument block and the start of

View File

@ -0,0 +1,161 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.vm.ci.hotspot.riscv64;
import static java.util.Collections.emptyMap;
import static jdk.vm.ci.common.InitTimer.timer;
import java.util.EnumSet;
import java.util.Map;
import jdk.vm.ci.riscv64.RISCV64;
import jdk.vm.ci.riscv64.RISCV64.CPUFeature;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.code.RegisterConfig;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.code.stack.StackIntrospection;
import jdk.vm.ci.common.InitTimer;
import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
import jdk.vm.ci.hotspot.HotSpotMetaAccessProvider;
import jdk.vm.ci.hotspot.HotSpotStackIntrospection;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.runtime.JVMCIBackend;
public class RISCV64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
private static EnumSet<RISCV64.CPUFeature> computeFeatures(RISCV64HotSpotVMConfig config) {
// Configure the feature set using the HotSpot flag settings.
Map<String, Long> constants = config.getStore().getConstants();
return HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, config.vmVersionFeatures, emptyMap());
}
private static EnumSet<RISCV64.Flag> computeFlags(RISCV64HotSpotVMConfig config) {
EnumSet<RISCV64.Flag> flags = EnumSet.noneOf(RISCV64.Flag.class);
if (config.useConservativeFence) {
flags.add(RISCV64.Flag.UseConservativeFence);
}
if (config.avoidUnalignedAccesses) {
flags.add(RISCV64.Flag.AvoidUnalignedAccesses);
}
if (config.nearCpool) {
flags.add(RISCV64.Flag.NearCpool);
}
if (config.traceTraps) {
flags.add(RISCV64.Flag.TraceTraps);
}
if (config.useRVV) {
flags.add(RISCV64.Flag.UseRVV);
}
if (config.useRVC) {
flags.add(RISCV64.Flag.UseRVC);
}
if (config.useZba) {
flags.add(RISCV64.Flag.UseZba);
}
if (config.useZbb) {
flags.add(RISCV64.Flag.UseZbb);
}
if (config.useRVVForBigIntegerShiftIntrinsics) {
flags.add(RISCV64.Flag.UseRVVForBigIntegerShiftIntrinsics);
}
return flags;
}
private static TargetDescription createTarget(RISCV64HotSpotVMConfig config) {
final int stackFrameAlignment = 16;
final int implicitNullCheckLimit = 4096;
final boolean inlineObjects = true;
Architecture arch = new RISCV64(computeFeatures(config), computeFlags(config));
return new TargetDescription(arch, true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
}
protected HotSpotConstantReflectionProvider createConstantReflection(HotSpotJVMCIRuntime runtime) {
return new HotSpotConstantReflectionProvider(runtime);
}
private static RegisterConfig createRegisterConfig(RISCV64HotSpotVMConfig config, TargetDescription target) {
return new RISCV64HotSpotRegisterConfig(target, config.useCompressedOops, config.linuxOs);
}
protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntime runtime, TargetDescription target, RegisterConfig regConfig) {
return new HotSpotCodeCacheProvider(runtime, target, regConfig);
}
protected HotSpotMetaAccessProvider createMetaAccess(HotSpotJVMCIRuntime runtime) {
return new HotSpotMetaAccessProvider(runtime);
}
@Override
public String getArchitecture() {
return "riscv64";
}
@Override
public String toString() {
return "JVMCIBackend:" + getArchitecture();
}
@Override
@SuppressWarnings("try")
public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntime runtime, JVMCIBackend host) {
assert host == null;
RISCV64HotSpotVMConfig config = new RISCV64HotSpotVMConfig(runtime.getConfigStore());
TargetDescription target = createTarget(config);
RegisterConfig regConfig;
HotSpotCodeCacheProvider codeCache;
ConstantReflectionProvider constantReflection;
HotSpotMetaAccessProvider metaAccess;
StackIntrospection stackIntrospection;
try (InitTimer t = timer("create providers")) {
try (InitTimer rt = timer("create MetaAccess provider")) {
metaAccess = createMetaAccess(runtime);
}
try (InitTimer rt = timer("create RegisterConfig")) {
regConfig = createRegisterConfig(config, target);
}
try (InitTimer rt = timer("create CodeCache provider")) {
codeCache = createCodeCache(runtime, target, regConfig);
}
try (InitTimer rt = timer("create ConstantReflection provider")) {
constantReflection = createConstantReflection(runtime);
}
try (InitTimer rt = timer("create StackIntrospection provider")) {
stackIntrospection = new HotSpotStackIntrospection(runtime);
}
}
try (InitTimer rt = timer("instantiate backend")) {
return createBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
}
}
protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection,
StackIntrospection stackIntrospection) {
return new JVMCIBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
}
}

View File

@ -0,0 +1,303 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.vm.ci.hotspot.riscv64;
import static jdk.vm.ci.riscv64.RISCV64.x0;
import static jdk.vm.ci.riscv64.RISCV64.x1;
import static jdk.vm.ci.riscv64.RISCV64.x2;
import static jdk.vm.ci.riscv64.RISCV64.x3;
import static jdk.vm.ci.riscv64.RISCV64.x4;
import static jdk.vm.ci.riscv64.RISCV64.x5;
import static jdk.vm.ci.riscv64.RISCV64.x6;
import static jdk.vm.ci.riscv64.RISCV64.x7;
import static jdk.vm.ci.riscv64.RISCV64.x8;
import static jdk.vm.ci.riscv64.RISCV64.x10;
import static jdk.vm.ci.riscv64.RISCV64.x11;
import static jdk.vm.ci.riscv64.RISCV64.x12;
import static jdk.vm.ci.riscv64.RISCV64.x13;
import static jdk.vm.ci.riscv64.RISCV64.x14;
import static jdk.vm.ci.riscv64.RISCV64.x15;
import static jdk.vm.ci.riscv64.RISCV64.x16;
import static jdk.vm.ci.riscv64.RISCV64.x17;
import static jdk.vm.ci.riscv64.RISCV64.x23;
import static jdk.vm.ci.riscv64.RISCV64.x27;
import static jdk.vm.ci.riscv64.RISCV64.f10;
import static jdk.vm.ci.riscv64.RISCV64.f11;
import static jdk.vm.ci.riscv64.RISCV64.f12;
import static jdk.vm.ci.riscv64.RISCV64.f13;
import static jdk.vm.ci.riscv64.RISCV64.f14;
import static jdk.vm.ci.riscv64.RISCV64.f15;
import static jdk.vm.ci.riscv64.RISCV64.f16;
import static jdk.vm.ci.riscv64.RISCV64.f17;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import jdk.vm.ci.riscv64.RISCV64;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.code.CallingConvention.Type;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.RegisterArray;
import jdk.vm.ci.code.RegisterAttributes;
import jdk.vm.ci.code.RegisterConfig;
import jdk.vm.ci.code.StackSlot;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.code.ValueKindFactory;
import jdk.vm.ci.common.JVMCIError;
import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.PlatformKind;
import jdk.vm.ci.meta.Value;
import jdk.vm.ci.meta.ValueKind;
public class RISCV64HotSpotRegisterConfig implements RegisterConfig {
private final TargetDescription target;
private final RegisterArray allocatable;
/**
* The caller saved registers always include all parameter registers.
*/
private final RegisterArray callerSaved;
private final boolean allAllocatableAreCallerSaved;
private final RegisterAttributes[] attributesMap;
@Override
public RegisterArray getAllocatableRegisters() {
return allocatable;
}
@Override
public RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers) {
ArrayList<Register> list = new ArrayList<>();
for (Register reg : registers) {
if (target.arch.canStoreValue(reg.getRegisterCategory(), kind)) {
list.add(reg);
}
}
return new RegisterArray(list);
}
@Override
public RegisterAttributes[] getAttributesMap() {
return attributesMap.clone();
}
private final RegisterArray javaGeneralParameterRegisters = new RegisterArray(x11, x12, x13, x14, x15, x16, x17, x10);
private final RegisterArray nativeGeneralParameterRegisters = new RegisterArray(x10, x11, x12, x13, x14, x15, x16, x17);
private final RegisterArray fpParameterRegisters = new RegisterArray(f10, f11, f12, f13, f14, f15, f16, f17);
public static final Register zero = x0;
public static final Register ra = x1;
public static final Register sp = x2;
public static final Register gp = x3;
public static final Register tp = x4;
public static final Register t0 = x5;
public static final Register t1 = x6;
public static final Register t2 = x7;
public static final Register fp = x8;
public static final Register threadRegister = x23;
public static final Register heapBaseRegister = x27;
private static final RegisterArray reservedRegisters = new RegisterArray(zero, ra, sp, gp, tp, t0, t1, t2, fp);
private static RegisterArray initAllocatable(Architecture arch, boolean reserveForHeapBase) {
RegisterArray allRegisters = arch.getAvailableValueRegisters();
Register[] registers = new Register[allRegisters.size() - reservedRegisters.size() - (reserveForHeapBase ? 1 : 0)];
List<Register> reservedRegistersList = reservedRegisters.asList();
int idx = 0;
for (Register reg : allRegisters) {
if (reservedRegistersList.contains(reg)) {
// skip reserved registers
continue;
}
assert !(reg.equals(zero) || reg.equals(ra) || reg.equals(sp) || reg.equals(gp) || reg.equals(tp) ||
reg.equals(t0) || reg.equals(t1) || reg.equals(t2) || reg.equals(fp));
if (reserveForHeapBase && reg.equals(heapBaseRegister)) {
// skip heap base register
continue;
}
registers[idx++] = reg;
}
assert idx == registers.length;
return new RegisterArray(registers);
}
public RISCV64HotSpotRegisterConfig(TargetDescription target, boolean useCompressedOops, boolean linuxOs) {
this(target, initAllocatable(target.arch, useCompressedOops));
assert callerSaved.size() >= allocatable.size();
}
public RISCV64HotSpotRegisterConfig(TargetDescription target, RegisterArray allocatable) {
this.target = target;
this.allocatable = allocatable;
Set<Register> callerSaveSet = new HashSet<>();
allocatable.addTo(callerSaveSet);
fpParameterRegisters.addTo(callerSaveSet);
javaGeneralParameterRegisters.addTo(callerSaveSet);
nativeGeneralParameterRegisters.addTo(callerSaveSet);
callerSaved = new RegisterArray(callerSaveSet);
allAllocatableAreCallerSaved = true;
attributesMap = RegisterAttributes.createMap(this, RISCV64.allRegisters);
}
@Override
public RegisterArray getCallerSaveRegisters() {
return callerSaved;
}
@Override
public RegisterArray getCalleeSaveRegisters() {
return null;
}
@Override
public boolean areAllAllocatableRegistersCallerSaved() {
return allAllocatableAreCallerSaved;
}
@Override
public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory<?> valueKindFactory) {
HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
if (type == HotSpotCallingConventionType.NativeCall) {
return callingConvention(nativeGeneralParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory);
}
return callingConvention(javaGeneralParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory);
}
@Override
public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) {
HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
switch (kind) {
case Boolean:
case Byte:
case Short:
case Char:
case Int:
case Long:
case Object:
return hotspotType == HotSpotCallingConventionType.NativeCall ? nativeGeneralParameterRegisters : javaGeneralParameterRegisters;
case Float:
case Double:
return fpParameterRegisters;
default:
throw JVMCIError.shouldNotReachHere();
}
}
private CallingConvention callingConvention(RegisterArray generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
ValueKindFactory<?> valueKindFactory) {
AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
int currentGeneral = 0;
int currentFP = 0;
int currentStackOffset = 0;
for (int i = 0; i < parameterTypes.length; i++) {
final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind();
switch (kind) {
case Byte:
case Boolean:
case Short:
case Char:
case Int:
case Long:
case Object:
if (currentGeneral < generalParameterRegisters.size()) {
Register register = generalParameterRegisters.get(currentGeneral++);
locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
}
break;
case Float:
case Double:
if (currentFP < fpParameterRegisters.size()) {
Register register = fpParameterRegisters.get(currentFP++);
locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
} else if (currentGeneral < generalParameterRegisters.size()) {
Register register = generalParameterRegisters.get(currentGeneral++);
locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
}
break;
default:
throw JVMCIError.shouldNotReachHere();
}
if (locations[i] == null) {
ValueKind<?> valueKind = valueKindFactory.getValueKind(kind);
locations[i] = StackSlot.get(valueKind, currentStackOffset, !type.out);
currentStackOffset += Math.max(valueKind.getPlatformKind().getSizeInBytes(), target.wordSize);
}
}
JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind();
AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(valueKindFactory.getValueKind(returnKind.getStackKind()));
return new CallingConvention(currentStackOffset, returnLocation, locations);
}
@Override
public Register getReturnRegister(JavaKind kind) {
switch (kind) {
case Boolean:
case Byte:
case Char:
case Short:
case Int:
case Long:
case Object:
return x10;
case Float:
case Double:
return f10;
case Void:
case Illegal:
return null;
default:
throw new UnsupportedOperationException("no return register for type " + kind);
}
}
@Override
public Register getFrameRegister() {
return x2;
}
@Override
public String toString() {
return String.format("Allocatable: " + getAllocatableRegisters() + "%n" + "CallerSave: " + getCallerSaveRegisters() + "%n");
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.vm.ci.hotspot.riscv64;
import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
import jdk.vm.ci.services.Services;
/**
* Used to access native configuration details.
*
* All non-static, public fields in this class are so that they can be compiled as constants.
*/
class RISCV64HotSpotVMConfig extends HotSpotVMConfigAccess {
RISCV64HotSpotVMConfig(HotSpotVMConfigStore config) {
super(config);
}
final boolean linuxOs = Services.getSavedProperty("os.name", "").startsWith("Linux");
final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
// CPU Capabilities
/*
* These flags are set based on the corresponding command line flags.
*/
final boolean useConservativeFence = getFlag("UseConservativeFence", Boolean.class);
final boolean avoidUnalignedAccesses = getFlag("AvoidUnalignedAccesses", Boolean.class);
final boolean nearCpool = getFlag("NearCpool", Boolean.class);
final boolean traceTraps = getFlag("TraceTraps", Boolean.class);
final boolean useRVV = getFlag("UseRVV", Boolean.class);
final boolean useRVC = getFlag("UseRVC", Boolean.class);
final boolean useZba = getFlag("UseZba", Boolean.class);
final boolean useZbb = getFlag("UseZbb", Boolean.class);
final boolean useRVVForBigIntegerShiftIntrinsics = getFlag("UseRVVForBigIntegerShiftIntrinsics", Boolean.class);
final long vmVersionFeatures = getFieldValue("Abstract_VM_Version::_features", Long.class, "uint64_t");
/*
* These flags are set if the corresponding support is in the hardware.
*/
// Checkstyle: stop
// CPU feature flags are currently not available in VM_Version
// Checkstyle: resume
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* The RISCV64 HotSpot specific portions of the JVMCI API.
*/
package jdk.vm.ci.hotspot.riscv64;

View File

@ -0,0 +1,237 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.vm.ci.riscv64;
import java.nio.ByteOrder;
import java.util.EnumSet;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.code.CPUFeatureName;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.Register.RegisterCategory;
import jdk.vm.ci.code.RegisterArray;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.PlatformKind;
/**
* Represents the RISCV64 architecture.
*/
public class RISCV64 extends Architecture {
public static final RegisterCategory CPU = new RegisterCategory("CPU");
// General purpose CPU registers
public static final Register x0 = new Register(0, 0, "x0", CPU);
public static final Register x1 = new Register(1, 1, "x1", CPU);
public static final Register x2 = new Register(2, 2, "x2", CPU);
public static final Register x3 = new Register(3, 3, "x3", CPU);
public static final Register x4 = new Register(4, 4, "x4", CPU);
public static final Register x5 = new Register(5, 5, "x5", CPU);
public static final Register x6 = new Register(6, 6, "x6", CPU);
public static final Register x7 = new Register(7, 7, "x7", CPU);
public static final Register x8 = new Register(8, 8, "x8", CPU);
public static final Register x9 = new Register(9, 9, "x9", CPU);
public static final Register x10 = new Register(10, 10, "x10", CPU);
public static final Register x11 = new Register(11, 11, "x11", CPU);
public static final Register x12 = new Register(12, 12, "x12", CPU);
public static final Register x13 = new Register(13, 13, "x13", CPU);
public static final Register x14 = new Register(14, 14, "x14", CPU);
public static final Register x15 = new Register(15, 15, "x15", CPU);
public static final Register x16 = new Register(16, 16, "x16", CPU);
public static final Register x17 = new Register(17, 17, "x17", CPU);
public static final Register x18 = new Register(18, 18, "x18", CPU);
public static final Register x19 = new Register(19, 19, "x19", CPU);
public static final Register x20 = new Register(20, 20, "x20", CPU);
public static final Register x21 = new Register(21, 21, "x21", CPU);
public static final Register x22 = new Register(22, 22, "x22", CPU);
public static final Register x23 = new Register(23, 23, "x23", CPU);
public static final Register x24 = new Register(24, 24, "x24", CPU);
public static final Register x25 = new Register(25, 25, "x25", CPU);
public static final Register x26 = new Register(26, 26, "x26", CPU);
public static final Register x27 = new Register(27, 27, "x27", CPU);
public static final Register x28 = new Register(28, 28, "x28", CPU);
public static final Register x29 = new Register(29, 29, "x29", CPU);
public static final Register x30 = new Register(30, 30, "x30", CPU);
public static final Register x31 = new Register(31, 31, "x31", CPU);
// @formatter:off
public static final RegisterArray cpuRegisters = new RegisterArray(
x0, x1, x2, x3, x4, x5, x6, x7,
x8, x9, x10, x11, x12, x13, x14, x15,
x16, x17, x18, x19, x20, x21, x22, x23,
x24, x25, x26, x27, x28, x29, x30, x31
);
// @formatter:on
public static final RegisterCategory FP = new RegisterCategory("FP");
// Simd registers
public static final Register f0 = new Register(32, 0, "f0", FP);
public static final Register f1 = new Register(33, 1, "f1", FP);
public static final Register f2 = new Register(34, 2, "f2", FP);
public static final Register f3 = new Register(35, 3, "f3", FP);
public static final Register f4 = new Register(36, 4, "f4", FP);
public static final Register f5 = new Register(37, 5, "f5", FP);
public static final Register f6 = new Register(38, 6, "f6", FP);
public static final Register f7 = new Register(39, 7, "f7", FP);
public static final Register f8 = new Register(40, 8, "f8", FP);
public static final Register f9 = new Register(41, 9, "f9", FP);
public static final Register f10 = new Register(42, 10, "f10", FP);
public static final Register f11 = new Register(43, 11, "f11", FP);
public static final Register f12 = new Register(44, 12, "f12", FP);
public static final Register f13 = new Register(45, 13, "f13", FP);
public static final Register f14 = new Register(46, 14, "f14", FP);
public static final Register f15 = new Register(47, 15, "f15", FP);
public static final Register f16 = new Register(48, 16, "f16", FP);
public static final Register f17 = new Register(49, 17, "f17", FP);
public static final Register f18 = new Register(50, 18, "f18", FP);
public static final Register f19 = new Register(51, 19, "f19", FP);
public static final Register f20 = new Register(52, 20, "f20", FP);
public static final Register f21 = new Register(53, 21, "f21", FP);
public static final Register f22 = new Register(54, 22, "f22", FP);
public static final Register f23 = new Register(55, 23, "f23", FP);
public static final Register f24 = new Register(56, 24, "f24", FP);
public static final Register f25 = new Register(57, 25, "f25", FP);
public static final Register f26 = new Register(58, 26, "f26", FP);
public static final Register f27 = new Register(59, 27, "f27", FP);
public static final Register f28 = new Register(60, 28, "f28", FP);
public static final Register f29 = new Register(61, 29, "f29", FP);
public static final Register f30 = new Register(62, 30, "f30", FP);
public static final Register f31 = new Register(63, 31, "f31", FP);
// @formatter:off
public static final RegisterArray fpRegisters = new RegisterArray(
f0, f1, f2, f3, f4, f5, f6, f7,
f8, f9, f10, f11, f12, f13, f14, f15,
f16, f17, f18, f19, f20, f21, f22, f23,
f24, f25, f26, f27, f28, f29, f30, f31
);
// @formatter:on
// @formatter:off
public static final RegisterArray allRegisters = new RegisterArray(
x0, x1, x2, x3, x4, x5, x6, x7,
x8, x9, x10, x11, x12, x13, x14, x15,
x16, x17, x18, x19, x20, x21, x22, x23,
x24, x25, x26, x27, x28, x29, x30, x31,
f0, f1, f2, f3, f4, f5, f6, f7,
f8, f9, f10, f11, f12, f13, f14, f15,
f16, f17, f18, f19, f20, f21, f22, f23,
f24, f25, f26, f27, f28, f29, f30, f31
);
// @formatter:on
/**
* Basic set of CPU features mirroring what is returned from the mcpuid register. See:
* {@code VM_Version::cpuFeatureFlags}.
*/
public enum CPUFeature implements CPUFeatureName {
I,
M,
A,
F,
D,
C,
V
}
private final EnumSet<CPUFeature> features;
/**
* Set of flags to control code emission.
*/
public enum Flag {
UseConservativeFence,
AvoidUnalignedAccesses,
NearCpool,
TraceTraps,
UseRVV,
UseRVC,
UseZba,
UseZbb,
UseRVVForBigIntegerShiftIntrinsics
}
private final EnumSet<Flag> flags;
public RISCV64(EnumSet<CPUFeature> features, EnumSet<Flag> flags) {
super("riscv64", RISCV64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, 0, 0, 8);
this.features = features;
this.flags = flags;
}
@Override
public EnumSet<CPUFeature> getFeatures() {
return features;
}
public EnumSet<Flag> getFlags() {
return flags;
}
@Override
public PlatformKind getPlatformKind(JavaKind javaKind) {
switch (javaKind) {
case Boolean:
case Byte:
return RISCV64Kind.BYTE;
case Short:
case Char:
return RISCV64Kind.WORD;
case Int:
return RISCV64Kind.DWORD;
case Long:
case Object:
return RISCV64Kind.QWORD;
case Float:
return RISCV64Kind.SINGLE;
case Double:
return RISCV64Kind.DOUBLE;
default:
return null;
}
}
@Override
public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
RISCV64Kind kind = (RISCV64Kind) platformKind;
if (kind.isInteger()) {
return category.equals(CPU);
} else if (kind.isFP()) {
return category.equals(FP);
}
return false;
}
@Override
public RISCV64Kind getLargestStorableKind(RegisterCategory category) {
if (category.equals(CPU)) {
return RISCV64Kind.QWORD;
} else if (category.equals(FP)) {
return RISCV64Kind.DOUBLE;
} else {
return null;
}
}
}

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.vm.ci.riscv64;
import jdk.vm.ci.meta.PlatformKind;
public enum RISCV64Kind implements PlatformKind {
// scalar
BYTE(1),
WORD(2),
DWORD(4),
QWORD(8),
SINGLE(4),
DOUBLE(8);
private final int size;
private final int vectorLength;
private final RISCV64Kind scalar;
private final EnumKey<RISCV64Kind> key = new EnumKey<>(this);
RISCV64Kind(int size) {
this.size = size;
this.scalar = this;
this.vectorLength = 1;
}
RISCV64Kind(int size, RISCV64Kind scalar) {
this.size = size;
this.scalar = scalar;
assert size % scalar.size == 0;
this.vectorLength = size / scalar.size;
}
public RISCV64Kind getScalar() {
return scalar;
}
@Override
public int getSizeInBytes() {
return size;
}
@Override
public int getVectorLength() {
return vectorLength;
}
@Override
public Key getKey() {
return key;
}
public boolean isInteger() {
switch (this) {
case BYTE:
case WORD:
case DWORD:
case QWORD:
return true;
default:
return false;
}
}
public boolean isFP() {
switch (this) {
case SINGLE:
case DOUBLE:
return true;
default:
return false;
}
}
@Override
public char getTypeChar() {
switch (this) {
case BYTE:
return 'b';
case WORD:
return 'w';
case DWORD:
return 'd';
case QWORD:
return 'q';
case SINGLE:
return 'S';
case DOUBLE:
return 'D';
default:
return '-';
}
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* The RISCV64 platform independent portions of the JVMCI API.
*/
package jdk.vm.ci.riscv64;

View File

@ -39,5 +39,6 @@ module jdk.internal.vm.ci {
provides jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory with
jdk.vm.ci.hotspot.aarch64.AArch64HotSpotJVMCIBackendFactory,
jdk.vm.ci.hotspot.amd64.AMD64HotSpotJVMCIBackendFactory;
jdk.vm.ci.hotspot.amd64.AMD64HotSpotJVMCIBackendFactory,
jdk.vm.ci.hotspot.riscv64.RISCV64HotSpotJVMCIBackendFactory;
}

View File

@ -24,12 +24,14 @@ package jdk.vm.ci.code.test;
import jdk.vm.ci.aarch64.AArch64;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.riscv64.RISCV64;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.code.InstalledCode;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.code.test.aarch64.AArch64TestAssembler;
import jdk.vm.ci.code.test.amd64.AMD64TestAssembler;
import jdk.vm.ci.code.test.riscv64.RISCV64TestAssembler;
import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
import jdk.vm.ci.hotspot.HotSpotCompiledCode;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
@ -76,6 +78,8 @@ public class CodeInstallationTest {
return new AMD64TestAssembler(codeCache, config);
} else if (arch instanceof AArch64) {
return new AArch64TestAssembler(codeCache, config);
} else if (arch instanceof RISCV64) {
return new RISCV64TestAssembler(codeCache, config);
} else {
Assert.fail("unsupported architecture");
return null;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,7 @@
/**
* @test
* @requires vm.jvmci
* @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64"
* @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64"
* @library /
* @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
* jdk.internal.vm.ci/jdk.vm.ci.meta
@ -33,7 +33,8 @@
* jdk.internal.vm.ci/jdk.vm.ci.runtime
* jdk.internal.vm.ci/jdk.vm.ci.aarch64
* jdk.internal.vm.ci/jdk.vm.ci.amd64
* @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java
* jdk.internal.vm.ci/jdk.vm.ci.riscv64
* @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java riscv64/RISCV64TestAssembler.java
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:-UseJVMCICompiler jdk.vm.ci.code.test.DataPatchTest
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,7 @@
/**
* @test
* @requires vm.jvmci
* @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64"
* @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64"
* @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
* jdk.internal.vm.ci/jdk.vm.ci.code
* jdk.internal.vm.ci/jdk.vm.ci.code.site
@ -33,7 +33,8 @@
* jdk.internal.vm.ci/jdk.vm.ci.common
* jdk.internal.vm.ci/jdk.vm.ci.aarch64
* jdk.internal.vm.ci/jdk.vm.ci.amd64
* @compile CodeInstallationTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java
* jdk.internal.vm.ci/jdk.vm.ci.riscv64
* @compile CodeInstallationTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java riscv64/RISCV64TestAssembler.java
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:-UseJVMCICompiler jdk.vm.ci.code.test.InterpreterFrameSizeTest
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,7 @@
/**
* @test
* @requires vm.jvmci
* @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64"
* @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64"
* @library /
* @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
* jdk.internal.vm.ci/jdk.vm.ci.meta
@ -34,7 +34,8 @@
* jdk.internal.vm.ci/jdk.vm.ci.runtime
* jdk.internal.vm.ci/jdk.vm.ci.aarch64
* jdk.internal.vm.ci/jdk.vm.ci.amd64
* @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java
* jdk.internal.vm.ci/jdk.vm.ci.riscv64
* @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java riscv64/RISCV64TestAssembler.java
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:-UseJVMCICompiler jdk.vm.ci.code.test.MaxOopMapStackOffsetTest
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,7 @@
/**
* @test
* @requires vm.jvmci
* @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64"
* @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64"
* @library /test/lib /
* @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
* jdk.internal.vm.ci/jdk.vm.ci.code
@ -34,7 +34,8 @@
* jdk.internal.vm.ci/jdk.vm.ci.common
* jdk.internal.vm.ci/jdk.vm.ci.aarch64
* jdk.internal.vm.ci/jdk.vm.ci.amd64
* @compile CodeInstallationTest.java TestHotSpotVMConfig.java NativeCallTest.java TestAssembler.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java
* jdk.internal.vm.ci/jdk.vm.ci.riscv64
* @compile CodeInstallationTest.java TestHotSpotVMConfig.java NativeCallTest.java TestAssembler.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java riscv64/RISCV64TestAssembler.java
* @run junit/othervm/native -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Xbootclasspath/a:. jdk.vm.ci.code.test.NativeCallTest
*/
package jdk.vm.ci.code.test;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,7 @@
/**
* @test
* @requires vm.jvmci
* @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64"
* @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64"
* @library /
* @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
* jdk.internal.vm.ci/jdk.vm.ci.meta
@ -33,7 +33,8 @@
* jdk.internal.vm.ci/jdk.vm.ci.runtime
* jdk.internal.vm.ci/jdk.vm.ci.aarch64
* jdk.internal.vm.ci/jdk.vm.ci.amd64
* @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java
* jdk.internal.vm.ci/jdk.vm.ci.riscv64
* @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java riscv64/RISCV64TestAssembler.java
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:-UseJVMCICompiler jdk.vm.ci.code.test.SimpleCodeInstallationTest
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,7 @@
/**
* @test
* @requires vm.jvmci
* @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64"
* @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64"
* @library /
* @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
* jdk.internal.vm.ci/jdk.vm.ci.meta
@ -33,7 +33,8 @@
* jdk.internal.vm.ci/jdk.vm.ci.runtime
* jdk.internal.vm.ci/jdk.vm.ci.aarch64
* jdk.internal.vm.ci/jdk.vm.ci.amd64
* @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java
* jdk.internal.vm.ci/jdk.vm.ci.riscv64
* @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java riscv64/RISCV64TestAssembler.java
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:-UseJVMCICompiler jdk.vm.ci.code.test.SimpleDebugInfoTest
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,7 @@
/**
* @test
* @requires vm.jvmci
* @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64"
* @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64"
* @library /
* @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
* jdk.internal.vm.ci/jdk.vm.ci.meta
@ -33,7 +33,8 @@
* jdk.internal.vm.ci/jdk.vm.ci.runtime
* jdk.internal.vm.ci/jdk.vm.ci.aarch64
* jdk.internal.vm.ci/jdk.vm.ci.amd64
* @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java
* jdk.internal.vm.ci/jdk.vm.ci.riscv64
* @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java riscv64/RISCV64TestAssembler.java
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:-UseJVMCICompiler jdk.vm.ci.code.test.VirtualObjectDebugInfoTest
*/

View File

@ -0,0 +1,542 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.vm.ci.code.test.riscv64;
import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.code.DebugInfo;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.RegisterValue;
import jdk.vm.ci.code.StackSlot;
import jdk.vm.ci.code.site.ConstantReference;
import jdk.vm.ci.code.site.DataSectionReference;
import jdk.vm.ci.code.test.TestAssembler;
import jdk.vm.ci.code.test.TestHotSpotVMConfig;
import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
import jdk.vm.ci.hotspot.HotSpotConstant;
import jdk.vm.ci.hotspot.HotSpotForeignCallTarget;
import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.VMConstant;
import jdk.vm.ci.riscv64.RISCV64;
import jdk.vm.ci.riscv64.RISCV64Kind;
public class RISCV64TestAssembler extends TestAssembler {
private static final Register scratchRegister = RISCV64.x5;
private static final Register doubleScratch = RISCV64.f5;
public RISCV64TestAssembler(CodeCacheProvider codeCache, TestHotSpotVMConfig config) {
super(codeCache, config,
16 /* initialFrameSize */, 16 /* stackAlignment */,
RISCV64Kind.DWORD /* narrowOopKind */,
/* registers */
RISCV64.x10, RISCV64.x11, RISCV64.x12, RISCV64.x13,
RISCV64.x14, RISCV64.x15, RISCV64.x16, RISCV64.x17);
}
private static int f(int val, int msb, int lsb) {
int nbits = msb - lsb + 1;
assert val >= 0;
assert val < (1 << nbits);
assert msb >= lsb;
return val << lsb;
}
private static int f(Register r, int msb, int lsb) {
assert msb - lsb == 4;
return f(r.encoding, msb, lsb);
}
private static int instructionImmediate(int imm, int rs1, int funct, int rd, int opcode) {
return f(imm, 31, 20) | f(rs1, 19, 15) | f(funct, 14, 12) | f(rd, 11, 7) | f(opcode, 6, 0);
}
private static int instructionRegister(int funct7, int rs2, int rs1, int funct3, int rd, int opcode) {
return f(funct7, 31, 25) | f(rs2, 24, 20) | f(rs1, 19, 15) | f(funct3, 14, 12) | f(rd, 11, 7) | f(opcode, 6, 0);
}
private void emitNop() {
code.emitInt(instructionImmediate(0, 0, 0b000, 0, 0b0010011));
}
private void emitAdd(Register Rd, Register Rm, Register Rn) {
// ADD
code.emitInt(instructionRegister(0b0000000, Rn.encoding, Rm.encoding, 0b000, Rd.encoding, 0b0110011));
}
private void emitAdd(Register Rd, Register Rn, int imm12) {
// ADDI
code.emitInt(instructionImmediate(imm12 & 0xfff, Rn.encoding, 0b000, Rd.encoding, 0b0010011));
}
private void emitAddW(Register Rd, Register Rn, int imm12) {
// ADDIW
code.emitInt(instructionImmediate(imm12 & 0xfff, Rn.encoding, 0b000, Rd.encoding, 0b0011011));
}
private void emitSub(Register Rd, Register Rn, int imm12) {
// SUBI
emitAdd(Rd, Rn, -imm12);;
}
private void emitSub(Register Rd, Register Rm, Register Rn) {
// SUB
code.emitInt(instructionRegister(0b0100000, Rn.encoding, Rm.encoding, 0b000, Rd.encoding, 0b0110011));
}
private void emitMv(Register Rd, Register Rn) {
// MV
code.emitInt(instructionRegister(0b0000000, 0, Rn.encoding, 0b000, Rd.encoding, 0b0110011));
}
private void emitShiftLeft(Register Rd, Register Rn, int shift) {
// SLLI
code.emitInt(instructionImmediate(shift & 0x3f, Rn.encoding, 0b001, Rd.encoding, 0b0010011));
}
private void emitShiftRight(Register Rd, Register Rn, int shift) {
// SRLI
code.emitInt(instructionImmediate(shift & 0x3f, Rn.encoding, 0b101, Rd.encoding, 0b0010011));
}
private void emitLui(Register Rd, int imm20) {
// LUI
code.emitInt(f(imm20, 31, 12) | f(Rd, 11, 7) | f(0b0110111, 6, 0));
}
private void emitAuipc(Register Rd, int imm20) {
// AUIPC
code.emitInt(f(imm20, 31, 12) | f(Rd, 11, 7) | f(0b0010111, 6, 0));
}
private void emitLoadImmediate(Register Rd, int imm32) {
long upper = imm32, lower = imm32;
lower = (lower << 52) >> 52;
upper -= lower;
upper = (int) upper;
emitLui(Rd, ((int) (upper >> 12)) & 0xfffff);
emitAddW(Rd, Rd, (int) lower);
}
private void emitLoadRegister(Register Rd, RISCV64Kind kind, Register Rn, int offset) {
// LB/LH/LW/LD (immediate)
assert offset >= 0;
int size = 0;
int opc = 0;
switch (kind) {
case BYTE: size = 0b000; opc = 0b0000011; break;
case WORD: size = 0b001; opc = 0b0000011; break;
case DWORD: size = 0b010; opc = 0b0000011; break;
case QWORD: size = 0b011; opc = 0b0000011; break;
case SINGLE: size = 0b010; opc = 0b0000111; break;
case DOUBLE: size = 0b011; opc = 0b0000111; break;
default: throw new IllegalArgumentException();
}
code.emitInt(f(offset, 31, 20) | f(Rn, 19, 15) | f(size, 14, 12) | f(Rd, 11, 7) | f(opc, 6, 0));
}
private void emitStoreRegister(Register Rd, RISCV64Kind kind, Register Rn, int offset) {
// SB/SH/SW/SD (immediate)
assert offset >= 0;
int size = 0;
int opc = 0;
switch (kind) {
case BYTE: size = 0b000; opc = 0b0100011; break;
case WORD: size = 0b001; opc = 0b0100011; break;
case DWORD: size = 0b010; opc = 0b0100011; break;
case QWORD: size = 0b011; opc = 0b0100011; break;
case SINGLE: size = 0b010; opc = 0b0100111; break;
case DOUBLE: size = 0b011; opc = 0b0100111; break;
default: throw new IllegalArgumentException();
}
code.emitInt(f((offset >> 5), 31, 25) | f(Rd, 24, 20) | f(Rn, 19, 15) | f(size, 14, 12) | f((offset & 0x1f), 11, 7) | f(opc, 6, 0));
}
private void emitJalr(Register Rd, Register Rn, int imm) {
code.emitInt(instructionImmediate(imm & 0xfff, Rn.encoding, 0b000, Rd.encoding, 0b1100111));
}
private void emitFmv(Register Rd, RISCV64Kind kind, Register Rn) {
int funct = 0;
switch (kind) {
case SINGLE: funct = 0b1111000; break;
case DOUBLE: funct = 0b1111001; break;
default: throw new IllegalArgumentException();
}
code.emitInt(instructionRegister(funct, 0b00000, Rn.encoding, 0b000, Rd.encoding, 0b1010011));
}
@Override
public void emitGrowStack(int size) {
assert size % 16 == 0;
if (size > -2048 && size < 0) {
emitAdd(RISCV64.x2, RISCV64.x2, -size);
} else if (size == 0) {
// No-op
} else if (size < 2048) {
emitSub(RISCV64.x2, RISCV64.x2, size);
} else if (size < 65535) {
emitLoadImmediate(scratchRegister, size);
emitSub(RISCV64.x2, RISCV64.x2, scratchRegister);
} else {
throw new IllegalArgumentException();
}
}
@Override
public void emitPrologue() {
// Must be patchable by NativeJump::patch_verified_entry
emitNop();
emitAdd(RISCV64.x2, RISCV64.x2, -32); // addi sp sp -32
emitStoreRegister(RISCV64.x8, RISCV64Kind.QWORD, RISCV64.x2, 0); // sd x8 sp(0)
emitStoreRegister(RISCV64.x1, RISCV64Kind.QWORD, RISCV64.x2, 8); // sd x1 sp(8)
emitMv(RISCV64.x8, RISCV64.x2); // mv x8, x2
setDeoptRescueSlot(newStackSlot(RISCV64Kind.QWORD));
}
@Override
public void emitEpilogue() {
recordMark(config.MARKID_DEOPT_HANDLER_ENTRY);
recordCall(new HotSpotForeignCallTarget(config.handleDeoptStub), 6*4, true, null);
emitCall(0xdeaddeaddeadL);
}
@Override
public void emitCallPrologue(CallingConvention cc, Object... prim) {
emitGrowStack(cc.getStackSize());
frameSize += cc.getStackSize();
AllocatableValue[] args = cc.getArguments();
for (int i = 0; i < args.length; i++) {
emitLoad(args[i], prim[i]);
}
}
@Override
public void emitCallEpilogue(CallingConvention cc) {
emitGrowStack(-cc.getStackSize());
frameSize -= cc.getStackSize();
}
@Override
public void emitCall(long addr) {
emitMovPtrHelper(scratchRegister, addr);
emitJalr(RISCV64.x1, scratchRegister, (int) (addr & 0x3f));
}
@Override
public void emitLoad(AllocatableValue av, Object prim) {
if (av instanceof RegisterValue) {
Register reg = ((RegisterValue) av).getRegister();
if (prim instanceof Float) {
emitLoadFloat(reg, (Float) prim);
} else if (prim instanceof Double) {
emitLoadDouble(reg, (Double) prim);
} else if (prim instanceof Integer) {
emitLoadInt(reg, (Integer) prim);
} else if (prim instanceof Long) {
emitLoadLong(reg, (Long) prim);
}
} else if (av instanceof StackSlot) {
StackSlot slot = (StackSlot) av;
if (prim instanceof Float) {
emitFloatToStack(slot, emitLoadFloat(doubleScratch, (Float) prim));
} else if (prim instanceof Double) {
emitDoubleToStack(slot, emitLoadDouble(doubleScratch, (Double) prim));
} else if (prim instanceof Integer) {
emitIntToStack(slot, emitLoadInt(scratchRegister, (Integer) prim));
} else if (prim instanceof Long) {
emitLongToStack(slot, emitLoadLong(scratchRegister, (Long) prim));
} else {
assert false : "Unimplemented";
}
} else {
throw new IllegalArgumentException("Unknown value " + av);
}
}
private void emitLoad32(Register ret, int addr) {
long upper = addr, lower = addr;
lower = (lower << 52) >> 52;
upper -= lower;
upper = (int) upper;
emitLui(ret, ((int) (upper >> 12)) & 0xfffff);
emitAdd(ret, ret, (int) lower);
}
private void emitMovPtrHelper(Register ret, long addr) {
// 48-bit VA
assert (addr >> 48) == 0 : "invalid pointer" + Long.toHexString(addr);
emitLoad32(ret, (int) (addr >> 17));
emitShiftLeft(ret, ret, 11);
emitAdd(ret, ret, (int) ((addr >> 6) & 0x7ff));
emitShiftLeft(ret, ret, 6);
}
private void emitLoadPointer32(Register ret, int addr) {
emitLoadImmediate(ret, addr);
// Lui sign-extends the value, which we do not want
emitShiftLeft(ret, ret, 32);
emitShiftRight(ret, ret, 32);
}
private void emitLoadPointer48(Register ret, long addr) {
emitMovPtrHelper(ret, addr);
emitAdd(ret, ret, (int) (addr & 0x3f));
}
@Override
public Register emitLoadPointer(HotSpotConstant c) {
recordDataPatchInCode(new ConstantReference((VMConstant) c));
Register ret = newRegister();
if (c.isCompressed()) {
emitLoadPointer32(ret, 0xdeaddead);
} else {
emitLoadPointer48(ret, 0xdeaddeaddeadL);
}
return ret;
}
@Override
public Register emitLoadPointer(Register b, int offset) {
Register ret = newRegister();
emitLoadRegister(ret, RISCV64Kind.QWORD, b, offset & 0xfff);
return ret;
}
@Override
public Register emitLoadNarrowPointer(DataSectionReference ref) {
recordDataPatchInCode(ref);
Register ret = newRegister();
emitAuipc(ret, 0xdead >> 11);
emitLoadRegister(ret, RISCV64Kind.DWORD, ret, 0xdead & 0x7ff);
// The value is sign-extendsed, which we do not want
emitShiftLeft(ret, ret, 32);
emitShiftRight(ret, ret, 32);
return ret;
}
@Override
public Register emitLoadPointer(DataSectionReference ref) {
recordDataPatchInCode(ref);
Register ret = newRegister();
emitAuipc(ret, 0xdead >> 11);
emitLoadRegister(ret, RISCV64Kind.QWORD, ret, 0xdead & 0x7ff);
return ret;
}
private Register emitLoadDouble(Register reg, double c) {
DataSectionReference ref = new DataSectionReference();
ref.setOffset(data.position());
data.emitDouble(c);
recordDataPatchInCode(ref);
emitAuipc(scratchRegister, 0xdead >> 11);
emitLoadRegister(scratchRegister, RISCV64Kind.QWORD, scratchRegister, 0xdead & 0x7ff);
if (reg.getRegisterCategory().equals(RISCV64.FP)) {
emitFmv(reg, RISCV64Kind.DOUBLE, scratchRegister);
} else {
emitMv(reg, scratchRegister);
}
return reg;
}
private Register emitLoadFloat(Register reg, float c) {
DataSectionReference ref = new DataSectionReference();
ref.setOffset(data.position());
data.emitFloat(c);
recordDataPatchInCode(ref);
emitAuipc(scratchRegister, 0xdead >> 11);
emitLoadRegister(scratchRegister, RISCV64Kind.DWORD, scratchRegister, 0xdead & 0x7ff);
if (reg.getRegisterCategory().equals(RISCV64.FP)) {
emitFmv(reg, RISCV64Kind.SINGLE, scratchRegister);
} else {
emitMv(reg, scratchRegister);
}
return reg;
}
@Override
public Register emitLoadFloat(float c) {
Register ret = RISCV64.f10;
return emitLoadFloat(ret, c);
}
private Register emitLoadLong(Register reg, long c) {
long lower = c & 0xffffffff;
lower = lower - ((lower << 44) >> 44);
emitLoad32(reg, (int) ((c >> 32) & 0xffffffff));
emitShiftLeft(reg, reg, 12);
emitAdd(reg, reg, (int) ((lower >> 20) & 0xfff));
emitShiftLeft(reg, reg, 12);
emitAdd(reg, reg, (int) ((c << 44) >> 52));
emitShiftLeft(reg, reg, 8);
emitAdd(reg, reg, (int) (c & 0xff));
return reg;
}
@Override
public Register emitLoadLong(long c) {
Register ret = newRegister();
return emitLoadLong(ret, c);
}
private Register emitLoadInt(Register reg, int c) {
emitLoadImmediate(reg, c);
return reg;
}
@Override
public Register emitLoadInt(int c) {
Register ret = newRegister();
return emitLoadInt(ret, c);
}
@Override
public Register emitIntArg0() {
return codeCache.getRegisterConfig()
.getCallingConventionRegisters(HotSpotCallingConventionType.JavaCall, JavaKind.Int)
.get(0);
}
@Override
public Register emitIntArg1() {
return codeCache.getRegisterConfig()
.getCallingConventionRegisters(HotSpotCallingConventionType.JavaCall, JavaKind.Int)
.get(1);
}
@Override
public Register emitIntAdd(Register a, Register b) {
emitAdd(a, a, b);
return a;
}
@Override
public void emitTrap(DebugInfo info) {
// Dereference null pointer
emitAdd(scratchRegister, RISCV64.x0, 0);
recordImplicitException(info);
emitLoadRegister(RISCV64.x0, RISCV64Kind.QWORD, scratchRegister, 0);
}
@Override
public void emitIntRet(Register a) {
emitMv(RISCV64.x10, a);
emitMv(RISCV64.x2, RISCV64.x8); // mv sp, x8
emitLoadRegister(RISCV64.x8, RISCV64Kind.QWORD, RISCV64.x2, 0); // ld x8 0(sp)
emitLoadRegister(RISCV64.x1, RISCV64Kind.QWORD, RISCV64.x2, 8); // ld x1 8(sp)
emitAdd(RISCV64.x2, RISCV64.x2, 32); // addi sp sp 32
emitJalr(RISCV64.x0, RISCV64.x1, 0); // ret
}
@Override
public void emitFloatRet(Register a) {
assert a == RISCV64.f10 : "Unimplemented move " + a;
emitMv(RISCV64.x2, RISCV64.x8); // mv sp, x8
emitLoadRegister(RISCV64.x8, RISCV64Kind.QWORD, RISCV64.x2, 0); // ld x8 0(sp)
emitLoadRegister(RISCV64.x1, RISCV64Kind.QWORD, RISCV64.x2, 8); // ld x1 8(sp)
emitAdd(RISCV64.x2, RISCV64.x2, 32); // addi sp sp 32
emitJalr(RISCV64.x0, RISCV64.x1, 0); // ret
}
@Override
public void emitPointerRet(Register a) {
emitIntRet(a);
}
@Override
public StackSlot emitPointerToStack(Register a) {
return emitLongToStack(a);
}
@Override
public StackSlot emitNarrowPointerToStack(Register a) {
return emitIntToStack(a);
}
@Override
public Register emitUncompressPointer(Register compressed, long base, int shift) {
if (shift > 0) {
emitShiftLeft(compressed, compressed, shift);
}
if (base != 0) {
emitLoadLong(scratchRegister, base);
emitAdd(compressed, compressed, scratchRegister);
}
return compressed;
}
private StackSlot emitDoubleToStack(StackSlot slot, Register a) {
emitStoreRegister(a, RISCV64Kind.DOUBLE, RISCV64.x2, slot.getOffset(frameSize) & 0xfff);
return slot;
}
@Override
public StackSlot emitDoubleToStack(Register a) {
StackSlot ret = newStackSlot(RISCV64Kind.DOUBLE);
return emitDoubleToStack(ret, a);
}
private StackSlot emitFloatToStack(StackSlot slot, Register a) {
emitStoreRegister(a, RISCV64Kind.SINGLE, RISCV64.x2, slot.getOffset(frameSize) & 0xfff);
return slot;
}
@Override
public StackSlot emitFloatToStack(Register a) {
StackSlot ret = newStackSlot(RISCV64Kind.SINGLE);
return emitFloatToStack(ret, a);
}
private StackSlot emitIntToStack(StackSlot slot, Register a) {
emitStoreRegister(a, RISCV64Kind.DWORD, RISCV64.x2, slot.getOffset(frameSize) & 0xfff);
return slot;
}
@Override
public StackSlot emitIntToStack(Register a) {
StackSlot ret = newStackSlot(RISCV64Kind.DWORD);
return emitIntToStack(ret, a);
}
private StackSlot emitLongToStack(StackSlot slot, Register a) {
emitStoreRegister(a, RISCV64Kind.QWORD, RISCV64.x2, slot.getOffset(frameSize) & 0xfff);
return slot;
}
@Override
public StackSlot emitLongToStack(Register a) {
StackSlot ret = newStackSlot(RISCV64Kind.QWORD);
return emitLongToStack(ret, a);
}
}