Commit 1d6dc2b9 authored by Liu Yu's avatar Liu Yu Committed by V8 LUCI CQ

[loong64][mips64][fastcall] Enable float support on loong64 and mips64

Port commit 098f31f4

Bug: chromium:1052746

Change-Id: I4f9fd952c2ce8b51772eac89d4852d55363d1ed1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3292352
Auto-Submit: Liu yu <liuyu@loongson.cn>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78106}
parent 52d84a98
...@@ -3892,16 +3892,19 @@ void TurboAssembler::Float64MinOutOfLine(FPURegister dst, FPURegister src1, ...@@ -3892,16 +3892,19 @@ void TurboAssembler::Float64MinOutOfLine(FPURegister dst, FPURegister src1,
} }
static const int kRegisterPassedArguments = 8; static const int kRegisterPassedArguments = 8;
static const int kFPRegisterPassedArguments = 8;
int TurboAssembler::CalculateStackPassedWords(int num_reg_arguments, int TurboAssembler::CalculateStackPassedWords(int num_reg_arguments,
int num_double_arguments) { int num_double_arguments) {
int stack_passed_words = 0; int stack_passed_words = 0;
num_reg_arguments += 2 * num_double_arguments;
// Up to eight simple arguments are passed in registers a0..a7. // Up to eight simple arguments are passed in registers a0..a7.
if (num_reg_arguments > kRegisterPassedArguments) { if (num_reg_arguments > kRegisterPassedArguments) {
stack_passed_words += num_reg_arguments - kRegisterPassedArguments; stack_passed_words += num_reg_arguments - kRegisterPassedArguments;
} }
if (num_double_arguments > kFPRegisterPassedArguments) {
stack_passed_words += num_double_arguments - kFPRegisterPassedArguments;
}
return stack_passed_words; return stack_passed_words;
} }
......
...@@ -5906,12 +5906,11 @@ static const int kRegisterPassedArguments = 8; ...@@ -5906,12 +5906,11 @@ static const int kRegisterPassedArguments = 8;
int TurboAssembler::CalculateStackPassedWords(int num_reg_arguments, int TurboAssembler::CalculateStackPassedWords(int num_reg_arguments,
int num_double_arguments) { int num_double_arguments) {
int stack_passed_words = 0; int stack_passed_words = 0;
num_reg_arguments += 2 * num_double_arguments; int num_args = num_reg_arguments + num_double_arguments;
// O32: Up to four simple arguments are passed in registers a0..a3. // Up to eight arguments are passed in FPURegisters and GPRegisters.
// N64: Up to eight simple arguments are passed in registers a0..a7. if (num_args > kRegisterPassedArguments) {
if (num_reg_arguments > kRegisterPassedArguments) { stack_passed_words = num_args - kRegisterPassedArguments;
stack_passed_words += num_reg_arguments - kRegisterPassedArguments;
} }
stack_passed_words += kCArgSlotCount; stack_passed_words += kCArgSlotCount;
return stack_passed_words; return stack_passed_words;
......
...@@ -650,8 +650,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -650,8 +650,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchPrepareCallCFunction: { case kArchPrepareCallCFunction: {
UseScratchRegisterScope temps(tasm()); UseScratchRegisterScope temps(tasm());
Register scratch = temps.Acquire(); Register scratch = temps.Acquire();
int const num_parameters = MiscField::decode(instr->opcode()); int const num_gp_parameters = ParamField::decode(instr->opcode());
__ PrepareCallCFunction(num_parameters, scratch); int const num_fp_parameters = FPParamField::decode(instr->opcode());
__ PrepareCallCFunction(num_gp_parameters, num_fp_parameters, scratch);
// Frame alignment requires using FP-relative frame addressing. // Frame alignment requires using FP-relative frame addressing.
frame_access_state()->SetFrameAccessToFP(); frame_access_state()->SetFrameAccessToFP();
break; break;
...@@ -687,7 +688,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -687,7 +688,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
AssemblePrepareTailCall(); AssemblePrepareTailCall();
break; break;
case kArchCallCFunction: { case kArchCallCFunction: {
int const num_parameters = MiscField::decode(instr->opcode()); int const num_gp_parameters = ParamField::decode(instr->opcode());
int const num_fp_parameters = FPParamField::decode(instr->opcode());
#if V8_ENABLE_WEBASSEMBLY #if V8_ENABLE_WEBASSEMBLY
Label start_call; Label start_call;
bool isWasmCapiFunction = bool isWasmCapiFunction =
...@@ -709,10 +711,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -709,10 +711,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
#endif // V8_ENABLE_WEBASSEMBLY #endif // V8_ENABLE_WEBASSEMBLY
if (instr->InputAt(0)->IsImmediate()) { if (instr->InputAt(0)->IsImmediate()) {
ExternalReference ref = i.InputExternalReference(0); ExternalReference ref = i.InputExternalReference(0);
__ CallCFunction(ref, num_parameters); __ CallCFunction(ref, num_gp_parameters, num_fp_parameters);
} else { } else {
Register func = i.InputRegister(0); Register func = i.InputRegister(0);
__ CallCFunction(func, num_parameters); __ CallCFunction(func, num_gp_parameters, num_fp_parameters);
} }
#if V8_ENABLE_WEBASSEMBLY #if V8_ENABLE_WEBASSEMBLY
if (isWasmCapiFunction) { if (isWasmCapiFunction) {
......
...@@ -1671,8 +1671,10 @@ void InstructionSelector::EmitPrepareArguments( ...@@ -1671,8 +1671,10 @@ void InstructionSelector::EmitPrepareArguments(
// Prepare for C function call. // Prepare for C function call.
if (call_descriptor->IsCFunctionCall()) { if (call_descriptor->IsCFunctionCall()) {
Emit(kArchPrepareCallCFunction | MiscField::encode(static_cast<int>( int gp_param_count = static_cast<int>(call_descriptor->GPParameterCount());
call_descriptor->ParameterCount())), int fp_param_count = static_cast<int>(call_descriptor->FPParameterCount());
Emit(kArchPrepareCallCFunction | ParamField::encode(gp_param_count) |
FPParamField::encode(fp_param_count),
0, nullptr, 0, nullptr); 0, nullptr, 0, nullptr);
// Poke any stack arguments. // Poke any stack arguments.
......
...@@ -704,7 +704,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -704,7 +704,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
AssemblePrepareTailCall(); AssemblePrepareTailCall();
break; break;
case kArchCallCFunction: { case kArchCallCFunction: {
int const num_parameters = MiscField::decode(instr->opcode()); int const num_gp_parameters = ParamField::decode(instr->opcode());
int const num_fp_parameters = FPParamField::decode(instr->opcode());
#if V8_ENABLE_WEBASSEMBLY #if V8_ENABLE_WEBASSEMBLY
Label start_call; Label start_call;
bool isWasmCapiFunction = bool isWasmCapiFunction =
...@@ -731,10 +732,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -731,10 +732,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
#endif // V8_ENABLE_WEBASSEMBLY #endif // V8_ENABLE_WEBASSEMBLY
if (instr->InputAt(0)->IsImmediate()) { if (instr->InputAt(0)->IsImmediate()) {
ExternalReference ref = i.InputExternalReference(0); ExternalReference ref = i.InputExternalReference(0);
__ CallCFunction(ref, num_parameters); __ CallCFunction(ref, num_gp_parameters, num_fp_parameters);
} else { } else {
Register func = i.InputRegister(0); Register func = i.InputRegister(0);
__ CallCFunction(func, num_parameters); __ CallCFunction(func, num_gp_parameters, num_fp_parameters);
} }
#if V8_ENABLE_WEBASSEMBLY #if V8_ENABLE_WEBASSEMBLY
if (isWasmCapiFunction) { if (isWasmCapiFunction) {
......
...@@ -96,6 +96,9 @@ namespace { ...@@ -96,6 +96,9 @@ namespace {
// == mips64 ================================================================= // == mips64 =================================================================
// =========================================================================== // ===========================================================================
#define PARAM_REGISTERS a0, a1, a2, a3, a4, a5, a6, a7 #define PARAM_REGISTERS a0, a1, a2, a3, a4, a5, a6, a7
#define FP_PARAM_REGISTERS f12, f13, f14, f15, f16, f17, f18, f19
#define FP_RETURN_REGISTER f0
#define CALLEE_SAVE_REGISTERS \ #define CALLEE_SAVE_REGISTERS \
s0.bit() | s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() | s6.bit() | \ s0.bit() | s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() | s6.bit() | \
s7.bit() s7.bit()
...@@ -107,6 +110,8 @@ namespace { ...@@ -107,6 +110,8 @@ namespace {
// == loong64 ================================================================ // == loong64 ================================================================
// =========================================================================== // ===========================================================================
#define PARAM_REGISTERS a0, a1, a2, a3, a4, a5, a6, a7 #define PARAM_REGISTERS a0, a1, a2, a3, a4, a5, a6, a7
#define FP_PARAM_REGISTERS f0, f1, f2, f3, f4, f5, f6, f7
#define FP_RETURN_REGISTER f0
#define CALLEE_SAVE_REGISTERS \ #define CALLEE_SAVE_REGISTERS \
s0.bit() | s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() | s6.bit() | \ s0.bit() | s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() | s6.bit() | \
s7.bit() | s8.bit() | fp.bit() s7.bit() | s8.bit() | fp.bit()
...@@ -166,12 +171,15 @@ namespace { ...@@ -166,12 +171,15 @@ namespace {
#endif #endif
} // namespace } // namespace
#if defined(V8_TARGET_OS_WIN) && defined(V8_TARGET_ARCH_X64) #if (defined(V8_TARGET_OS_WIN) && defined(V8_TARGET_ARCH_X64)) || \
defined(V8_TARGET_ARCH_MIPS64)
// As defined in // As defined in
// https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2019#parameter-passing, // https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2019#parameter-passing,
// Windows calling convention doesn't differentiate between GP and FP params // Windows calling convention doesn't differentiate between GP and FP params
// when counting how many of them should be placed in registers. That's why // when counting how many of them should be placed in registers. That's why
// we use the same counter {i} for both types here. // we use the same counter {i} for both types here.
// MIPS is the same, as defined in
// https://techpubs.jurassic.nl/manuals/0630/developer/Mpro_n32_ABI/sgi_html/ch02.html#id52620.
void BuildParameterLocations(const MachineSignature* msig, void BuildParameterLocations(const MachineSignature* msig,
size_t kFPParamRegisterCount, size_t kFPParamRegisterCount,
size_t kParamRegisterCount, size_t kParamRegisterCount,
...@@ -203,7 +211,8 @@ void BuildParameterLocations(const MachineSignature* msig, ...@@ -203,7 +211,8 @@ void BuildParameterLocations(const MachineSignature* msig,
} }
} }
} }
#else // defined(V8_TARGET_OS_WIN) && defined(V8_TARGET_ARCH_X64) #else // (defined(V8_TARGET_OS_WIN) && defined(V8_TARGET_ARCH_X64)) ||
// defined(V8_TARGET_ARCH_MIPS64)
// As defined in https://www.agner.org/optimize/calling_conventions.pdf, // As defined in https://www.agner.org/optimize/calling_conventions.pdf,
// Section 7, Linux and Mac place parameters in consecutive registers, // Section 7, Linux and Mac place parameters in consecutive registers,
// differentiating between GP and FP params. That's why we maintain two // differentiating between GP and FP params. That's why we maintain two
...@@ -244,7 +253,8 @@ void BuildParameterLocations(const MachineSignature* msig, ...@@ -244,7 +253,8 @@ void BuildParameterLocations(const MachineSignature* msig,
} }
} }
} }
#endif // defined(V8_TARGET_OS_WIN) && defined(V8_TARGET_ARCH_X64) #endif // (defined(V8_TARGET_OS_WIN) && defined(V8_TARGET_ARCH_X64)) ||
// defined(V8_TARGET_ARCH_MIPS64)
// General code uses the above configuration data. // General code uses the above configuration data.
CallDescriptor* Linkage::GetSimplifiedCDescriptor(Zone* zone, CallDescriptor* Linkage::GetSimplifiedCDescriptor(Zone* zone,
......
...@@ -93,7 +93,9 @@ const int kMaxFastLiteralProperties = JSObject::kMaxInObjectProperties; ...@@ -93,7 +93,9 @@ const int kMaxFastLiteralProperties = JSObject::kMaxInObjectProperties;
// (using FP stack). As support is added to more platforms, please make sure // (using FP stack). As support is added to more platforms, please make sure
// to list them here in order to enable tests of this functionality. // to list them here in order to enable tests of this functionality.
// Make sure to sync the following with src/d8/d8-test.cc. // Make sure to sync the following with src/d8/d8-test.cc.
#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64) #if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64) || \
(defined(V8_TARGET_ARCH_MIPS64) && !defined(USE_SIMULATOR)) || \
(defined(V8_TARGET_ARCH_LOONG64) && !defined(USE_SIMULATOR))
#define V8_ENABLE_FP_PARAMS_IN_C_LINKAGE #define V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
#endif #endif
......
...@@ -17,7 +17,9 @@ ...@@ -17,7 +17,9 @@
// and resetting these counters. // and resetting these counters.
// Make sure to sync the following with src/compiler/globals.h. // Make sure to sync the following with src/compiler/globals.h.
#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64) #if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64) || \
(defined(V8_TARGET_ARCH_MIPS64) && !defined(USE_SIMULATOR)) || \
(defined(V8_TARGET_ARCH_LOONG64) && !defined(USE_SIMULATOR))
#define V8_ENABLE_FP_PARAMS_IN_C_LINKAGE #define V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
#endif #endif
......
...@@ -2228,7 +2228,18 @@ void Simulator::SoftwareInterrupt() { ...@@ -2228,7 +2228,18 @@ void Simulator::SoftwareInterrupt() {
reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external); reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
target(arg0, arg1, Redirection::ReverseRedirection(arg2)); target(arg0, arg1, Redirection::ReverseRedirection(arg2));
} else { } else {
DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL || // FAST_C_CALL is temporarily handled here as well, because we lack
// proper support for direct C calls with FP params in the simulator.
// The generic BUILTIN_CALL path assumes all parameters are passed in
// the GP registers, thus supporting calling the slow callback without
// crashing. The reason for that is that in the mjsunit tests we check
// the `fast_c_api.supports_fp_params` (which is false on simulator
// builds for loong64), thus we expect that the slow path will be
// called. And since the slow path passes the arguments as a `const
// FunctionCallbackInfo<Value>&` (which is a GP argument), the call is
// made correctly.
DCHECK(redirection->type() == ExternalReference::FAST_C_CALL ||
redirection->type() == ExternalReference::BUILTIN_CALL ||
redirection->type() == ExternalReference::BUILTIN_CALL_PAIR); redirection->type() == ExternalReference::BUILTIN_CALL_PAIR);
SimulatorRuntimeCall target = SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(external); reinterpret_cast<SimulatorRuntimeCall>(external);
......
...@@ -2423,7 +2423,18 @@ void Simulator::SoftwareInterrupt() { ...@@ -2423,7 +2423,18 @@ void Simulator::SoftwareInterrupt() {
reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external); reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
target(arg0, arg1, Redirection::ReverseRedirection(arg2)); target(arg0, arg1, Redirection::ReverseRedirection(arg2));
} else { } else {
DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL || // FAST_C_CALL is temporarily handled here as well, because we lack
// proper support for direct C calls with FP params in the simulator.
// The generic BUILTIN_CALL path assumes all parameters are passed in
// the GP registers, thus supporting calling the slow callback without
// crashing. The reason for that is that in the mjsunit tests we check
// the `fast_c_api.supports_fp_params` (which is false on simulator
// builds for mips64), thus we expect that the slow path will be
// called. And since the slow path passes the arguments as a `const
// FunctionCallbackInfo<Value>&` (which is a GP argument), the call is
// made correctly.
DCHECK(redirection->type() == ExternalReference::FAST_C_CALL ||
redirection->type() == ExternalReference::BUILTIN_CALL ||
redirection->type() == ExternalReference::BUILTIN_CALL_PAIR); redirection->type() == ExternalReference::BUILTIN_CALL_PAIR);
SimulatorRuntimeCall target = SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(external); reinterpret_cast<SimulatorRuntimeCall>(external);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment