8290154: [JVMCI] partially implement JVMCI for RISC-V
Reviewed-by: ihse, dnsimon, yadongwang
This commit is contained in:
parent
b38bed6d0e
commit
7a194d31a3
@ -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
|
||||
|
124
src/hotspot/cpu/riscv/jvmciCodeInstaller_riscv.cpp
Normal file
124
src/hotspot/cpu/riscv/jvmciCodeInstaller_riscv.cpp
Normal 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());
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
@ -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
|
||||
|
||||
}
|
@ -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;
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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 '-';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user