[codegen] Change RegList into a class
Modernise the RegList interface to be a proper class, rather than a typedef to an integer, and add proper methods onto it rather than ad-hoc bit manipulation. In particular, this makes RegList typesafe, adding a DoubleRegList for DoubleRegisters. The Arm64 CPURegList isn't updated to use (or extend) the new RegList interface, because of its weird type-erasing semantics (it can store Registers and VRegisters). Maybe in the future we'll want to get rid of CPURegList entirely and use RegList/DoubleRegList directly. Change-Id: I3cb2a4d386cb92a4dcd2edbdd3fba9ef71f354d6 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3516747 Commit-Queue: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/main@{#79460}
This commit is contained in:
parent
5a968b08b3
commit
8a0d1b6fe5
@ -1116,10 +1116,12 @@ filegroup(
|
||||
"src/codegen/optimized-compilation-info.h",
|
||||
"src/codegen/pending-optimization-table.cc",
|
||||
"src/codegen/pending-optimization-table.h",
|
||||
"src/codegen/register-arch.h",
|
||||
"src/codegen/register-base.h",
|
||||
"src/codegen/register-configuration.cc",
|
||||
"src/codegen/register-configuration.h",
|
||||
"src/codegen/register.h",
|
||||
"src/codegen/reglist-base.h",
|
||||
"src/codegen/reglist.h",
|
||||
"src/codegen/reloc-info.cc",
|
||||
"src/codegen/reloc-info.h",
|
||||
@ -2102,6 +2104,7 @@ filegroup(
|
||||
"src/codegen/ia32/macro-assembler-ia32.cc",
|
||||
"src/codegen/ia32/macro-assembler-ia32.h",
|
||||
"src/codegen/ia32/register-ia32.h",
|
||||
"src/codegen/ia32/reglist-ia32.h",
|
||||
"src/compiler/backend/ia32/code-generator-ia32.cc",
|
||||
"src/compiler/backend/ia32/instruction-codes-ia32.h",
|
||||
"src/compiler/backend/ia32/instruction-scheduler-ia32.cc",
|
||||
@ -2131,6 +2134,7 @@ filegroup(
|
||||
"src/codegen/x64/macro-assembler-x64.cc",
|
||||
"src/codegen/x64/macro-assembler-x64.h",
|
||||
"src/codegen/x64/register-x64.h",
|
||||
"src/codegen/x64/reglist-x64.h",
|
||||
"src/compiler/backend/x64/code-generator-x64.cc",
|
||||
"src/compiler/backend/x64/instruction-codes-x64.h",
|
||||
"src/compiler/backend/x64/instruction-scheduler-x64.cc",
|
||||
@ -2160,6 +2164,7 @@ filegroup(
|
||||
"src/codegen/arm/macro-assembler-arm.cc",
|
||||
"src/codegen/arm/macro-assembler-arm.h",
|
||||
"src/codegen/arm/register-arm.h",
|
||||
"src/codegen/arm/reglist-arm.h",
|
||||
"src/compiler/backend/arm/code-generator-arm.cc",
|
||||
"src/compiler/backend/arm/instruction-codes-arm.h",
|
||||
"src/compiler/backend/arm/instruction-scheduler-arm.cc",
|
||||
@ -2198,6 +2203,7 @@ filegroup(
|
||||
"src/codegen/arm64/macro-assembler-arm64.h",
|
||||
"src/codegen/arm64/register-arm64.cc",
|
||||
"src/codegen/arm64/register-arm64.h",
|
||||
"src/codegen/arm64/reglist-arm64.h",
|
||||
"src/codegen/arm64/utils-arm64.cc",
|
||||
"src/codegen/arm64/utils-arm64.h",
|
||||
"src/compiler/backend/arm64/code-generator-arm64.cc",
|
||||
@ -2234,6 +2240,7 @@ filegroup(
|
||||
"src/codegen/s390/macro-assembler-s390.cc",
|
||||
"src/codegen/s390/macro-assembler-s390.h",
|
||||
"src/codegen/s390/register-s390.h",
|
||||
"src/codegen/s390/reglist-s390.h",
|
||||
"src/compiler/backend/s390/code-generator-s390.cc",
|
||||
"src/compiler/backend/s390/instruction-codes-s390.h",
|
||||
"src/compiler/backend/s390/instruction-scheduler-s390.cc",
|
||||
@ -2265,6 +2272,7 @@ filegroup(
|
||||
"src/codegen/riscv64/macro-assembler-riscv64.cc",
|
||||
"src/codegen/riscv64/macro-assembler-riscv64.h",
|
||||
"src/codegen/riscv64/register-riscv64.h",
|
||||
"src/codegen/riscv64/reglist-riscv64.h",
|
||||
"src/compiler/backend/riscv64/code-generator-riscv64.cc",
|
||||
"src/compiler/backend/riscv64/instruction-codes-riscv64.h",
|
||||
"src/compiler/backend/riscv64/instruction-scheduler-riscv64.cc",
|
||||
@ -2293,6 +2301,7 @@ filegroup(
|
||||
"src/codegen/ppc/macro-assembler-ppc.cc",
|
||||
"src/codegen/ppc/macro-assembler-ppc.h",
|
||||
"src/codegen/ppc/register-ppc.h",
|
||||
"src/codegen/ppc/reglist-ppc.h",
|
||||
"src/compiler/backend/ppc/code-generator-ppc.cc",
|
||||
"src/compiler/backend/ppc/instruction-codes-ppc.h",
|
||||
"src/compiler/backend/ppc/instruction-scheduler-ppc.cc",
|
||||
|
13
BUILD.gn
13
BUILD.gn
@ -2728,9 +2728,11 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/codegen/macro-assembler.h",
|
||||
"src/codegen/optimized-compilation-info.h",
|
||||
"src/codegen/pending-optimization-table.h",
|
||||
"src/codegen/register-arch.h",
|
||||
"src/codegen/register-base.h",
|
||||
"src/codegen/register-configuration.h",
|
||||
"src/codegen/register.h",
|
||||
"src/codegen/reglist-base.h",
|
||||
"src/codegen/reglist.h",
|
||||
"src/codegen/reloc-info.h",
|
||||
"src/codegen/safepoint-table.h",
|
||||
@ -3629,6 +3631,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/codegen/ia32/interface-descriptors-ia32-inl.h",
|
||||
"src/codegen/ia32/macro-assembler-ia32.h",
|
||||
"src/codegen/ia32/register-ia32.h",
|
||||
"src/codegen/ia32/reglist-ia32.h",
|
||||
"src/codegen/ia32/sse-instr.h",
|
||||
"src/codegen/shared-ia32-x64/macro-assembler-shared-ia32-x64.h",
|
||||
"src/compiler/backend/ia32/instruction-codes-ia32.h",
|
||||
@ -3648,6 +3651,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/codegen/x64/interface-descriptors-x64-inl.h",
|
||||
"src/codegen/x64/macro-assembler-x64.h",
|
||||
"src/codegen/x64/register-x64.h",
|
||||
"src/codegen/x64/reglist-x64.h",
|
||||
"src/codegen/x64/sse-instr.h",
|
||||
"src/compiler/backend/x64/instruction-codes-x64.h",
|
||||
"src/compiler/backend/x64/unwinding-info-writer-x64.h",
|
||||
@ -3681,6 +3685,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/codegen/arm/interface-descriptors-arm-inl.h",
|
||||
"src/codegen/arm/macro-assembler-arm.h",
|
||||
"src/codegen/arm/register-arm.h",
|
||||
"src/codegen/arm/reglist-arm.h",
|
||||
"src/compiler/backend/arm/instruction-codes-arm.h",
|
||||
"src/compiler/backend/arm/unwinding-info-writer-arm.h",
|
||||
"src/execution/arm/frame-constants-arm.h",
|
||||
@ -3702,6 +3707,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/codegen/arm64/macro-assembler-arm64-inl.h",
|
||||
"src/codegen/arm64/macro-assembler-arm64.h",
|
||||
"src/codegen/arm64/register-arm64.h",
|
||||
"src/codegen/arm64/reglist-arm64.h",
|
||||
"src/codegen/arm64/utils-arm64.h",
|
||||
"src/compiler/backend/arm64/instruction-codes-arm64.h",
|
||||
"src/compiler/backend/arm64/unwinding-info-writer-arm64.h",
|
||||
@ -3738,6 +3744,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/codegen/mips/constants-mips.h",
|
||||
"src/codegen/mips/macro-assembler-mips.h",
|
||||
"src/codegen/mips/register-mips.h",
|
||||
"src/codegen/mips/reglist-mips.h",
|
||||
"src/compiler/backend/mips/instruction-codes-mips.h",
|
||||
"src/execution/mips/frame-constants-mips.h",
|
||||
"src/execution/mips/simulator-mips.h",
|
||||
@ -3753,6 +3760,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/codegen/mips64/constants-mips64.h",
|
||||
"src/codegen/mips64/macro-assembler-mips64.h",
|
||||
"src/codegen/mips64/register-mips64.h",
|
||||
"src/codegen/mips64/reglist-mips64.h",
|
||||
"src/compiler/backend/mips64/instruction-codes-mips64.h",
|
||||
"src/execution/mips64/frame-constants-mips64.h",
|
||||
"src/execution/mips64/simulator-mips64.h",
|
||||
@ -3768,6 +3776,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/codegen/loong64/constants-loong64.h",
|
||||
"src/codegen/loong64/macro-assembler-loong64.h",
|
||||
"src/codegen/loong64/register-loong64.h",
|
||||
"src/codegen/loong64/reglist-loong64.h",
|
||||
"src/compiler/backend/loong64/instruction-codes-loong64.h",
|
||||
"src/execution/loong64/frame-constants-loong64.h",
|
||||
"src/execution/loong64/simulator-loong64.h",
|
||||
@ -3782,6 +3791,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/codegen/ppc/interface-descriptors-ppc-inl.h",
|
||||
"src/codegen/ppc/macro-assembler-ppc.h",
|
||||
"src/codegen/ppc/register-ppc.h",
|
||||
"src/codegen/ppc/reglist-ppc.h",
|
||||
"src/compiler/backend/ppc/instruction-codes-ppc.h",
|
||||
"src/compiler/backend/ppc/unwinding-info-writer-ppc.h",
|
||||
"src/execution/ppc/frame-constants-ppc.h",
|
||||
@ -3799,6 +3809,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/codegen/ppc/interface-descriptors-ppc-inl.h",
|
||||
"src/codegen/ppc/macro-assembler-ppc.h",
|
||||
"src/codegen/ppc/register-ppc.h",
|
||||
"src/codegen/ppc/reglist-ppc.h",
|
||||
"src/compiler/backend/ppc/instruction-codes-ppc.h",
|
||||
"src/compiler/backend/ppc/unwinding-info-writer-ppc.h",
|
||||
"src/execution/ppc/frame-constants-ppc.h",
|
||||
@ -3816,6 +3827,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/codegen/s390/interface-descriptors-s390-inl.h",
|
||||
"src/codegen/s390/macro-assembler-s390.h",
|
||||
"src/codegen/s390/register-s390.h",
|
||||
"src/codegen/s390/reglist-s390.h",
|
||||
"src/compiler/backend/s390/instruction-codes-s390.h",
|
||||
"src/compiler/backend/s390/unwinding-info-writer-s390.h",
|
||||
"src/execution/s390/frame-constants-s390.h",
|
||||
@ -3832,6 +3844,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/codegen/riscv64/constants-riscv64.h",
|
||||
"src/codegen/riscv64/macro-assembler-riscv64.h",
|
||||
"src/codegen/riscv64/register-riscv64.h",
|
||||
"src/codegen/riscv64/reglist-riscv64.h",
|
||||
"src/compiler/backend/riscv64/instruction-codes-riscv64.h",
|
||||
"src/execution/riscv64/frame-constants-riscv64.h",
|
||||
"src/execution/riscv64/simulator-riscv64.h",
|
||||
|
@ -22,7 +22,7 @@ class BaselineAssembler::ScratchRegisterScope {
|
||||
if (!assembler_->scratch_register_scope_) {
|
||||
// If we haven't opened a scratch scope yet, for the first one add a
|
||||
// couple of extra registers.
|
||||
wrapped_scope_.Include(t0.bit() | t1.bit() | t2.bit() | t3.bit());
|
||||
wrapped_scope_.Include({t0, t1, t2, t3});
|
||||
}
|
||||
assembler_->scratch_register_scope_ = this;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ class BaselineAssembler::ScratchRegisterScope {
|
||||
if (!assembler_->scratch_register_scope_) {
|
||||
// If we haven't opened a scratch scope yet, for the first one add a
|
||||
// couple of extra registers.
|
||||
wrapped_scope_.Include(t4.bit() | t5.bit() | t6.bit() | t7.bit());
|
||||
wrapped_scope_.Include({t4, t5, t6, t7});
|
||||
}
|
||||
assembler_->scratch_register_scope_ = this;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ class BaselineAssembler::ScratchRegisterScope {
|
||||
if (!assembler_->scratch_register_scope_) {
|
||||
// If we haven't opened a scratch scope yet, for the first one add a
|
||||
// couple of extra registers.
|
||||
wrapped_scope_.Include(t0.bit() | t1.bit() | t2.bit() | t3.bit());
|
||||
wrapped_scope_.Include({t0, t1, t2, t3});
|
||||
}
|
||||
assembler_->scratch_register_scope_ = this;
|
||||
}
|
||||
|
@ -555,7 +555,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
|
||||
// r1: microtask_queue
|
||||
// Preserve all but r0 and pass them to entry_trampoline.
|
||||
Label invoke, handler_entry, exit;
|
||||
const RegList kCalleeSavedWithoutFp = kCalleeSaved & ~fp.bit();
|
||||
const RegList kCalleeSavedWithoutFp = kCalleeSaved - fp;
|
||||
|
||||
// Update |pushed_stack_space| when we manipulate the stack.
|
||||
int pushed_stack_space = EntryFrameConstants::kCallerFPOffset;
|
||||
@ -589,7 +589,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
|
||||
masm->isolate()));
|
||||
__ ldr(r5, MemOperand(r4));
|
||||
|
||||
__ stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | fp.bit() | lr.bit());
|
||||
__ stm(db_w, sp, {r5, r6, r7, fp, lr});
|
||||
pushed_stack_space += 5 * kPointerSize /* r5, r6, r7, fp, lr */;
|
||||
|
||||
// Clear c_entry_fp, now we've pushed its previous value to the stack.
|
||||
@ -690,7 +690,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
|
||||
Operand(-EntryFrameConstants::kCallerFPOffset -
|
||||
kSystemPointerSize /* already popped one */));
|
||||
|
||||
__ ldm(ia_w, sp, fp.bit() | lr.bit());
|
||||
__ ldm(ia_w, sp, {fp, lr});
|
||||
|
||||
// Restore callee-saved vfp registers.
|
||||
__ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
|
||||
@ -1202,7 +1202,7 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
|
||||
temps.Exclude(optimization_state);
|
||||
|
||||
// Drop the frame created by the baseline call.
|
||||
__ ldm(ia_w, sp, fp.bit() | lr.bit());
|
||||
__ ldm(ia_w, sp, {fp, lr});
|
||||
MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(masm, optimization_state,
|
||||
feedback_vector);
|
||||
__ Trap();
|
||||
@ -2628,9 +2628,9 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
// Save all parameter registers (see wasm-linkage.h). They might be
|
||||
// overwritten in the runtime call below. We don't have any callee-saved
|
||||
// registers in wasm, so no need to store anything else.
|
||||
RegList gp_regs = 0;
|
||||
RegList gp_regs;
|
||||
for (Register gp_param_reg : wasm::kGpParamRegisters) {
|
||||
gp_regs |= gp_param_reg.bit();
|
||||
gp_regs.set(gp_param_reg);
|
||||
}
|
||||
DwVfpRegister lowest_fp_reg = std::begin(wasm::kFpParamRegisters)[0];
|
||||
DwVfpRegister highest_fp_reg = std::end(wasm::kFpParamRegisters)[-1];
|
||||
@ -2639,10 +2639,10 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
fp_param_reg.code() <= highest_fp_reg.code());
|
||||
}
|
||||
|
||||
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters));
|
||||
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters));
|
||||
CHECK_EQ(highest_fp_reg.code() - lowest_fp_reg.code() + 1,
|
||||
arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(NumRegs(gp_regs),
|
||||
CHECK_EQ(gp_regs.Count(),
|
||||
WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs);
|
||||
CHECK_EQ(highest_fp_reg.code() - lowest_fp_reg.code() + 1,
|
||||
WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs);
|
||||
@ -2675,20 +2675,19 @@ void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
|
||||
FrameAndConstantPoolScope scope(masm, StackFrame::WASM_DEBUG_BREAK);
|
||||
|
||||
STATIC_ASSERT(DwVfpRegister::kNumRegisters == 32);
|
||||
constexpr uint32_t last =
|
||||
31 - base::bits::CountLeadingZeros32(
|
||||
WasmDebugBreakFrameConstants::kPushedFpRegs);
|
||||
constexpr uint32_t first = base::bits::CountTrailingZeros32(
|
||||
WasmDebugBreakFrameConstants::kPushedFpRegs);
|
||||
constexpr DwVfpRegister last =
|
||||
WasmDebugBreakFrameConstants::kPushedFpRegs.last();
|
||||
constexpr DwVfpRegister first =
|
||||
WasmDebugBreakFrameConstants::kPushedFpRegs.first();
|
||||
static_assert(
|
||||
base::bits::CountPopulation(
|
||||
WasmDebugBreakFrameConstants::kPushedFpRegs) == last - first + 1,
|
||||
WasmDebugBreakFrameConstants::kPushedFpRegs.Count() ==
|
||||
last.code() - first.code() + 1,
|
||||
"All registers in the range from first to last have to be set");
|
||||
|
||||
// Save all parameter registers. They might hold live values, we restore
|
||||
// them after the runtime call.
|
||||
constexpr DwVfpRegister lowest_fp_reg = DwVfpRegister::from_code(first);
|
||||
constexpr DwVfpRegister highest_fp_reg = DwVfpRegister::from_code(last);
|
||||
constexpr DwVfpRegister lowest_fp_reg = first;
|
||||
constexpr DwVfpRegister highest_fp_reg = last;
|
||||
|
||||
// Store gp parameter registers.
|
||||
__ stm(db_w, sp, WasmDebugBreakFrameConstants::kPushedGpRegs);
|
||||
@ -3340,12 +3339,12 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
|
||||
STATIC_ASSERT(kNumberOfRegisters == 16);
|
||||
|
||||
// Everything but pc, lr and ip which will be saved but not restored.
|
||||
RegList restored_regs = kJSCallerSaved | kCalleeSaved | ip.bit();
|
||||
RegList restored_regs = kJSCallerSaved | kCalleeSaved | RegList{ip};
|
||||
|
||||
// Push all 16 registers (needed to populate FrameDescription::registers_).
|
||||
// TODO(v8:1588): Note that using pc with stm is deprecated, so we should
|
||||
// perhaps handle this a bit differently.
|
||||
__ stm(db_w, sp, restored_regs | sp.bit() | lr.bit() | pc.bit());
|
||||
__ stm(db_w, sp, restored_regs | RegList{sp, lr, pc});
|
||||
|
||||
{
|
||||
UseScratchRegisterScope temps(masm);
|
||||
|
@ -3037,27 +3037,27 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
// Save all parameter registers (see wasm-linkage.h). They might be
|
||||
// overwritten in the runtime call below. We don't have any callee-saved
|
||||
// registers in wasm, so no need to store anything else.
|
||||
RegList gp_regs = 0;
|
||||
RegList gp_regs;
|
||||
for (Register gp_param_reg : wasm::kGpParamRegisters) {
|
||||
gp_regs |= gp_param_reg.bit();
|
||||
gp_regs.set(gp_param_reg);
|
||||
}
|
||||
// Also push x1, because we must push multiples of 16 bytes (see
|
||||
// {TurboAssembler::PushCPURegList}.
|
||||
CHECK_EQ(1, NumRegs(gp_regs) % 2);
|
||||
gp_regs |= x1.bit();
|
||||
CHECK_EQ(0, NumRegs(gp_regs) % 2);
|
||||
CHECK_EQ(1, gp_regs.Count() % 2);
|
||||
gp_regs.set(x1);
|
||||
CHECK_EQ(0, gp_regs.Count() % 2);
|
||||
|
||||
RegList fp_regs = 0;
|
||||
DoubleRegList fp_regs;
|
||||
for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) {
|
||||
fp_regs |= fp_param_reg.bit();
|
||||
fp_regs.set(fp_param_reg);
|
||||
}
|
||||
|
||||
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters) + 1);
|
||||
CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters) + 1);
|
||||
CHECK_EQ(fp_regs.Count(), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs,
|
||||
NumRegs(gp_regs));
|
||||
gp_regs.Count());
|
||||
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
|
||||
NumRegs(fp_regs));
|
||||
fp_regs.Count());
|
||||
|
||||
__ PushXRegList(gp_regs);
|
||||
__ PushQRegList(fp_regs);
|
||||
@ -3868,8 +3868,9 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
|
||||
|
||||
// Save all allocatable double registers.
|
||||
CPURegList saved_double_registers(
|
||||
CPURegister::kVRegister, kDRegSizeInBits,
|
||||
RegisterConfiguration::Default()->allocatable_double_codes_mask());
|
||||
kDRegSizeInBits,
|
||||
DoubleRegList::FromBits(
|
||||
RegisterConfiguration::Default()->allocatable_double_codes_mask()));
|
||||
DCHECK_EQ(saved_double_registers.Count() % 2, 0);
|
||||
__ PushCPURegList(saved_double_registers);
|
||||
|
||||
@ -4273,7 +4274,9 @@ void Builtins::Generate_DynamicCheckMapsTrampoline(
|
||||
RegList registers = descriptor.allocatable_registers();
|
||||
// FLAG_debug_code is enabled CSA checks will call C function and so we need
|
||||
// to save all CallerSaved registers too.
|
||||
if (FLAG_debug_code) registers |= kCallerSaved.list();
|
||||
if (FLAG_debug_code) {
|
||||
registers |= RegList::FromBits(static_cast<uint32_t>(kCallerSaved.bits()));
|
||||
}
|
||||
__ MaybeSaveRegisters(registers);
|
||||
|
||||
// Load the immediate arguments from the deopt exit to pass to the builtin.
|
||||
|
@ -2923,19 +2923,19 @@ void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
|
||||
|
||||
// Save all parameter registers. They might hold live values, we restore
|
||||
// them after the runtime call.
|
||||
for (int reg_code : base::bits::IterateBitsBackwards(
|
||||
WasmDebugBreakFrameConstants::kPushedGpRegs)) {
|
||||
__ Push(Register::from_code(reg_code));
|
||||
for (Register reg :
|
||||
base::Reversed(WasmDebugBreakFrameConstants::kPushedGpRegs)) {
|
||||
__ Push(reg);
|
||||
}
|
||||
|
||||
constexpr int kFpStackSize =
|
||||
kSimd128Size * WasmDebugBreakFrameConstants::kNumPushedFpRegisters;
|
||||
__ AllocateStackSpace(kFpStackSize);
|
||||
int offset = kFpStackSize;
|
||||
for (int reg_code : base::bits::IterateBitsBackwards(
|
||||
WasmDebugBreakFrameConstants::kPushedFpRegs)) {
|
||||
for (DoubleRegister reg :
|
||||
base::Reversed(WasmDebugBreakFrameConstants::kPushedFpRegs)) {
|
||||
offset -= kSimd128Size;
|
||||
__ movdqu(Operand(esp, offset), DoubleRegister::from_code(reg_code));
|
||||
__ movdqu(Operand(esp, offset), reg);
|
||||
}
|
||||
|
||||
// Initialize the JavaScript context with 0. CEntry will use it to
|
||||
@ -2944,15 +2944,13 @@ void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
|
||||
__ CallRuntime(Runtime::kWasmDebugBreak, 0);
|
||||
|
||||
// Restore registers.
|
||||
for (int reg_code :
|
||||
base::bits::IterateBits(WasmDebugBreakFrameConstants::kPushedFpRegs)) {
|
||||
__ movdqu(DoubleRegister::from_code(reg_code), Operand(esp, offset));
|
||||
for (DoubleRegister reg : WasmDebugBreakFrameConstants::kPushedFpRegs) {
|
||||
__ movdqu(reg, Operand(esp, offset));
|
||||
offset += kSimd128Size;
|
||||
}
|
||||
__ add(esp, Immediate(kFpStackSize));
|
||||
for (int reg_code :
|
||||
base::bits::IterateBits(WasmDebugBreakFrameConstants::kPushedGpRegs)) {
|
||||
__ Pop(Register::from_code(reg_code));
|
||||
for (Register reg : WasmDebugBreakFrameConstants::kPushedGpRegs) {
|
||||
__ Pop(reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -553,7 +553,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
|
||||
// a1: microtask_queue
|
||||
|
||||
// Save callee saved registers on the stack.
|
||||
__ MultiPush(kCalleeSaved | ra.bit());
|
||||
__ MultiPush(kCalleeSaved | ra);
|
||||
|
||||
// Save callee-saved FPU registers.
|
||||
__ MultiPushFPU(kCalleeSavedFPU);
|
||||
@ -707,7 +707,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
|
||||
__ MultiPopFPU(kCalleeSavedFPU);
|
||||
|
||||
// Restore callee saved registers from the stack.
|
||||
__ MultiPop(kCalleeSaved | ra.bit());
|
||||
__ MultiPop(kCalleeSaved | ra);
|
||||
// Return.
|
||||
__ Jump(ra);
|
||||
}
|
||||
@ -1053,8 +1053,8 @@ static void MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(
|
||||
// static
|
||||
void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
|
||||
UseScratchRegisterScope temps(masm);
|
||||
temps.Include(s1.bit() | s2.bit());
|
||||
temps.Exclude(t7.bit());
|
||||
temps.Include({s1, s2});
|
||||
temps.Exclude({t7});
|
||||
auto descriptor =
|
||||
Builtins::CallInterfaceDescriptorFor(Builtin::kBaselineOutOfLinePrologue);
|
||||
Register closure = descriptor.GetRegisterParameter(
|
||||
@ -1197,7 +1197,7 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
|
||||
__ Pop(kJavaScriptCallNewTargetRegister);
|
||||
}
|
||||
__ Ret();
|
||||
temps.Exclude(s1.bit() | s2.bit());
|
||||
temps.Exclude({s1, s2});
|
||||
}
|
||||
|
||||
// Generate code for entering a JS function with the interpreter.
|
||||
@ -2664,22 +2664,22 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
// Save all parameter registers (see wasm-linkage.h). They might be
|
||||
// overwritten in the runtime call below. We don't have any callee-saved
|
||||
// registers in wasm, so no need to store anything else.
|
||||
RegList gp_regs = 0;
|
||||
RegList gp_regs;
|
||||
for (Register gp_param_reg : wasm::kGpParamRegisters) {
|
||||
gp_regs |= gp_param_reg.bit();
|
||||
gp_regs.set(gp_param_reg);
|
||||
}
|
||||
|
||||
RegList fp_regs = 0;
|
||||
RegList fp_regs;
|
||||
for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) {
|
||||
fp_regs |= fp_param_reg.bit();
|
||||
fp_regs.set(fp_param_reg);
|
||||
}
|
||||
|
||||
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters));
|
||||
CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters));
|
||||
CHECK_EQ(fp_regs.Count(), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs,
|
||||
NumRegs(gp_regs));
|
||||
gp_regs.Count());
|
||||
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
|
||||
NumRegs(fp_regs));
|
||||
fp_regs.Count());
|
||||
|
||||
__ MultiPush(gp_regs);
|
||||
__ MultiPushFPU(fp_regs);
|
||||
@ -3375,7 +3375,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
|
||||
const int kNumberOfRegisters = Register::kNumRegisters;
|
||||
|
||||
RegList restored_regs = kJSCallerSaved | kCalleeSaved;
|
||||
RegList saved_regs = restored_regs | sp.bit() | ra.bit();
|
||||
RegList saved_regs = restored_regs | sp | ra;
|
||||
|
||||
const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kNumRegisters;
|
||||
|
||||
@ -3539,7 +3539,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
|
||||
|
||||
// Technically restoring 'at' should work unless zero_reg is also restored
|
||||
// but it's safer to check for this.
|
||||
DCHECK(!(t7.bit() & restored_regs));
|
||||
DCHECK(!(restored_regs.has(t7)));
|
||||
// Restore the registers from the last output frame.
|
||||
__ mov(t7, a2);
|
||||
for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
|
||||
|
@ -390,7 +390,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
|
||||
// a0: root_register_value
|
||||
|
||||
// Save callee saved registers on the stack.
|
||||
__ MultiPush(kCalleeSaved | ra.bit());
|
||||
__ MultiPush(kCalleeSaved | ra);
|
||||
pushed_stack_space +=
|
||||
kNumCalleeSaved * kPointerSize + kPointerSize /* ra */;
|
||||
|
||||
@ -524,7 +524,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
|
||||
__ MultiPopFPU(kCalleeSavedFPU);
|
||||
|
||||
// Restore callee saved registers from the stack.
|
||||
__ MultiPop(kCalleeSaved | ra.bit());
|
||||
__ MultiPop(kCalleeSaved | ra);
|
||||
// Return.
|
||||
__ Jump(ra);
|
||||
}
|
||||
@ -1052,7 +1052,7 @@ static void MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(
|
||||
// static
|
||||
void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
|
||||
UseScratchRegisterScope temps(masm);
|
||||
temps.Include(s1.bit() | s2.bit());
|
||||
temps.Include({s1, s2});
|
||||
auto descriptor =
|
||||
Builtins::CallInterfaceDescriptorFor(Builtin::kBaselineOutOfLinePrologue);
|
||||
Register closure = descriptor.GetRegisterParameter(
|
||||
@ -1193,7 +1193,7 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
|
||||
__ Pop(kJavaScriptCallNewTargetRegister);
|
||||
}
|
||||
__ Ret();
|
||||
temps.Exclude(kScratchReg.bit() | kScratchReg2.bit());
|
||||
temps.Exclude({kScratchReg, kScratchReg2});
|
||||
}
|
||||
|
||||
// Generate code for entering a JS function with the interpreter.
|
||||
@ -2608,22 +2608,22 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
// Save all parameter registers (see wasm-linkage.h). They might be
|
||||
// overwritten in the runtime call below. We don't have any callee-saved
|
||||
// registers in wasm, so no need to store anything else.
|
||||
RegList gp_regs = 0;
|
||||
RegList gp_regs;
|
||||
for (Register gp_param_reg : wasm::kGpParamRegisters) {
|
||||
gp_regs |= gp_param_reg.bit();
|
||||
gp_regs.set(gp_param_reg);
|
||||
}
|
||||
|
||||
RegList fp_regs = 0;
|
||||
RegList fp_regs;
|
||||
for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) {
|
||||
fp_regs |= fp_param_reg.bit();
|
||||
fp_regs.set(fp_param_reg);
|
||||
}
|
||||
|
||||
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters));
|
||||
CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters));
|
||||
CHECK_EQ(fp_regs.Count(), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs,
|
||||
NumRegs(gp_regs));
|
||||
gp_regs.Count());
|
||||
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
|
||||
NumRegs(fp_regs));
|
||||
fp_regs.Count());
|
||||
|
||||
__ MultiPush(gp_regs);
|
||||
__ MultiPushFPU(fp_regs);
|
||||
@ -3821,7 +3821,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
|
||||
static constexpr int kNumberOfRegisters = Register::kNumRegisters;
|
||||
|
||||
RegList restored_regs = kJSCallerSaved | kCalleeSaved;
|
||||
RegList saved_regs = restored_regs | sp.bit() | ra.bit();
|
||||
RegList saved_regs = restored_regs | sp | ra;
|
||||
|
||||
static constexpr int kDoubleRegsSize =
|
||||
kDoubleSize * DoubleRegister::kNumRegisters;
|
||||
@ -3987,7 +3987,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
|
||||
|
||||
// Technically restoring 'at' should work unless zero_reg is also restored
|
||||
// but it's safer to check for this.
|
||||
DCHECK(!(at.bit() & restored_regs));
|
||||
DCHECK(!(restored_regs.has(at)));
|
||||
// Restore the registers from the last output frame.
|
||||
__ mov(at, a2);
|
||||
for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
|
||||
|
@ -556,7 +556,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
|
||||
// 0 arg slots on mips64 (4 args slots on mips)
|
||||
|
||||
// Save callee saved registers on the stack.
|
||||
__ MultiPush(kCalleeSaved | ra.bit());
|
||||
__ MultiPush(kCalleeSaved | ra);
|
||||
|
||||
// Save callee-saved FPU registers.
|
||||
__ MultiPushFPU(kCalleeSavedFPU);
|
||||
@ -709,7 +709,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
|
||||
__ MultiPopFPU(kCalleeSavedFPU);
|
||||
|
||||
// Restore callee saved registers from the stack.
|
||||
__ MultiPop(kCalleeSaved | ra.bit());
|
||||
__ MultiPop(kCalleeSaved | ra);
|
||||
// Return.
|
||||
__ Jump(ra);
|
||||
}
|
||||
@ -1059,7 +1059,7 @@ static void MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(
|
||||
// static
|
||||
void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
|
||||
UseScratchRegisterScope temps(masm);
|
||||
temps.Include(s1.bit() | s2.bit());
|
||||
temps.Include({s1, s2});
|
||||
auto descriptor =
|
||||
Builtins::CallInterfaceDescriptorFor(Builtin::kBaselineOutOfLinePrologue);
|
||||
Register closure = descriptor.GetRegisterParameter(
|
||||
@ -1200,7 +1200,7 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
|
||||
__ Pop(kJavaScriptCallNewTargetRegister);
|
||||
}
|
||||
__ Ret();
|
||||
temps.Exclude(kScratchReg.bit() | kScratchReg2.bit());
|
||||
temps.Exclude({kScratchReg, kScratchReg2});
|
||||
}
|
||||
|
||||
// Generate code for entering a JS function with the interpreter.
|
||||
@ -2658,22 +2658,22 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
// Save all parameter registers (see wasm-linkage.h). They might be
|
||||
// overwritten in the runtime call below. We don't have any callee-saved
|
||||
// registers in wasm, so no need to store anything else.
|
||||
RegList gp_regs = 0;
|
||||
RegList gp_regs;
|
||||
for (Register gp_param_reg : wasm::kGpParamRegisters) {
|
||||
gp_regs |= gp_param_reg.bit();
|
||||
gp_regs.set(gp_param_reg);
|
||||
}
|
||||
|
||||
RegList fp_regs = 0;
|
||||
RegList fp_regs;
|
||||
for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) {
|
||||
fp_regs |= fp_param_reg.bit();
|
||||
fp_regs.set(fp_param_reg);
|
||||
}
|
||||
|
||||
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters));
|
||||
CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters));
|
||||
CHECK_EQ(fp_regs.Count(), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs,
|
||||
NumRegs(gp_regs));
|
||||
gp_regs.Count());
|
||||
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
|
||||
NumRegs(fp_regs));
|
||||
fp_regs.Count());
|
||||
|
||||
__ MultiPush(gp_regs);
|
||||
// Check if machine has simd enabled, if so push vector registers. If not
|
||||
@ -3400,7 +3400,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
|
||||
const int kNumberOfRegisters = Register::kNumRegisters;
|
||||
|
||||
RegList restored_regs = kJSCallerSaved | kCalleeSaved;
|
||||
RegList saved_regs = restored_regs | sp.bit() | ra.bit();
|
||||
RegList saved_regs = restored_regs | sp | ra;
|
||||
|
||||
const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kNumRegisters;
|
||||
|
||||
@ -3565,7 +3565,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
|
||||
|
||||
// Technically restoring 'at' should work unless zero_reg is also restored
|
||||
// but it's safer to check for this.
|
||||
DCHECK(!(at.bit() & restored_regs));
|
||||
DCHECK(!(restored_regs.has(at)));
|
||||
// Restore the registers from the last output frame.
|
||||
__ mov(at, a2);
|
||||
for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
|
||||
|
@ -2470,29 +2470,28 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
// Save all parameter registers (see wasm-linkage.h). They might be
|
||||
// overwritten in the runtime call below. We don't have any callee-saved
|
||||
// registers in wasm, so no need to store anything else.
|
||||
RegList gp_regs = 0;
|
||||
RegList gp_regs;
|
||||
for (Register gp_param_reg : wasm::kGpParamRegisters) {
|
||||
gp_regs |= gp_param_reg.bit();
|
||||
gp_regs.set(gp_param_reg);
|
||||
}
|
||||
|
||||
RegList fp_regs = 0;
|
||||
RegList fp_regs;
|
||||
for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) {
|
||||
fp_regs |= fp_param_reg.bit();
|
||||
fp_regs.set(fp_param_reg);
|
||||
}
|
||||
|
||||
// List must match register numbers under kFpParamRegisters.
|
||||
constexpr RegList simd_regs =
|
||||
Simd128Register::ListOf(v1, v2, v3, v4, v5, v6, v7, v8);
|
||||
constexpr RegList simd_regs = {v1, v2, v3, v4, v5, v6, v7, v8};
|
||||
|
||||
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters));
|
||||
CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(NumRegs(simd_regs), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters));
|
||||
CHECK_EQ(fp_regs.Count(), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(simd_regs.Count(), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs,
|
||||
NumRegs(gp_regs));
|
||||
gp_regs.Count());
|
||||
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
|
||||
NumRegs(fp_regs));
|
||||
fp_regs.Count());
|
||||
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
|
||||
NumRegs(simd_regs));
|
||||
simd_regs.Count());
|
||||
|
||||
__ MultiPush(gp_regs);
|
||||
__ MultiPushF64AndV128(fp_regs, simd_regs);
|
||||
@ -3246,7 +3245,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
|
||||
const int kNumberOfRegisters = Register::kNumRegisters;
|
||||
|
||||
RegList restored_regs = kJSCallerSaved | kCalleeSaved;
|
||||
RegList saved_regs = restored_regs | sp.bit();
|
||||
RegList saved_regs = restored_regs | sp;
|
||||
|
||||
const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kNumRegisters;
|
||||
|
||||
@ -3429,7 +3428,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
|
||||
{
|
||||
UseScratchRegisterScope temps(masm);
|
||||
Register scratch = temps.Acquire();
|
||||
DCHECK(!(scratch.bit() & restored_regs));
|
||||
DCHECK(!(restored_regs.has(scratch)));
|
||||
__ mr(scratch, r5);
|
||||
for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
|
||||
int offset =
|
||||
|
@ -587,7 +587,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
|
||||
// a1: microtask_queue
|
||||
|
||||
// Save callee saved registers on the stack.
|
||||
__ MultiPush(kCalleeSaved | ra.bit());
|
||||
__ MultiPush(kCalleeSaved | ra);
|
||||
|
||||
// Save callee-saved FPU registers.
|
||||
__ MultiPushFPU(kCalleeSavedFPU);
|
||||
@ -743,7 +743,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
|
||||
__ MultiPopFPU(kCalleeSavedFPU);
|
||||
|
||||
// Restore callee saved registers from the stack.
|
||||
__ MultiPop(kCalleeSaved | ra.bit());
|
||||
__ MultiPop(kCalleeSaved | ra);
|
||||
// Return.
|
||||
__ Jump(ra);
|
||||
}
|
||||
@ -1121,7 +1121,7 @@ static void MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(
|
||||
// static
|
||||
void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
|
||||
UseScratchRegisterScope temps(masm);
|
||||
temps.Include(kScratchReg.bit() | kScratchReg2.bit());
|
||||
temps.Include({kScratchReg, kScratchReg2});
|
||||
auto descriptor =
|
||||
Builtins::CallInterfaceDescriptorFor(Builtin::kBaselineOutOfLinePrologue);
|
||||
Register closure = descriptor.GetRegisterParameter(
|
||||
@ -1255,7 +1255,7 @@ void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
|
||||
__ Pop(kJavaScriptCallNewTargetRegister);
|
||||
}
|
||||
__ Ret();
|
||||
temps.Exclude(kScratchReg.bit() | kScratchReg2.bit());
|
||||
temps.Exclude({kScratchReg, kScratchReg2});
|
||||
}
|
||||
|
||||
// Generate code for entering a JS function with the interpreter.
|
||||
@ -2766,28 +2766,28 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
// Save all parameter registers (see kGpParamRegisters in wasm-linkage.cc).
|
||||
// They might be overwritten in the runtime call below. We don't have any
|
||||
// callee-saved registers in wasm, so no need to store anything else.
|
||||
RegList gp_regs = 0;
|
||||
RegList gp_regs;
|
||||
for (Register gp_param_reg : wasm::kGpParamRegisters) {
|
||||
gp_regs |= gp_param_reg.bit();
|
||||
gp_regs.set(gp_param_reg);
|
||||
}
|
||||
// Also push a1, because we must push multiples of 16 bytes (see
|
||||
// {TurboAssembler::PushCPURegList}.
|
||||
CHECK_EQ(1, NumRegs(gp_regs) % 2);
|
||||
gp_regs |= a1.bit();
|
||||
CHECK_EQ(1, gp_regs.Count() % 2);
|
||||
gp_regs.set(a1);
|
||||
// Ensure that A1 will not be repeated.
|
||||
CHECK_EQ(0, NumRegs(gp_regs) % 2);
|
||||
CHECK_EQ(0, gp_regs.Count() % 2);
|
||||
|
||||
RegList fp_regs = 0;
|
||||
RegList fp_regs;
|
||||
for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) {
|
||||
fp_regs |= fp_param_reg.bit();
|
||||
fp_regs.set(fp_param_reg);
|
||||
}
|
||||
|
||||
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters) + 1);
|
||||
CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters) + 1);
|
||||
CHECK_EQ(fp_regs.Count(), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs,
|
||||
NumRegs(gp_regs));
|
||||
gp_regs.Count());
|
||||
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
|
||||
NumRegs(fp_regs));
|
||||
fp_regs.Count());
|
||||
__ MultiPush(gp_regs);
|
||||
__ MultiPushFPU(fp_regs);
|
||||
|
||||
@ -3486,7 +3486,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
|
||||
const int kNumberOfRegisters = Register::kNumRegisters;
|
||||
|
||||
RegList restored_regs = kJSCallerSaved | kCalleeSaved;
|
||||
RegList saved_regs = restored_regs | sp.bit() | ra.bit();
|
||||
RegList saved_regs = restored_regs | sp | ra;
|
||||
|
||||
const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kNumRegisters;
|
||||
|
||||
@ -3651,7 +3651,7 @@ void Generate_DeoptimizationEntry(MacroAssembler* masm,
|
||||
|
||||
// Technically restoring 't3' should work unless zero_reg is also restored
|
||||
// but it's safer to check for this.
|
||||
DCHECK(!(t3.bit() & restored_regs));
|
||||
DCHECK(!(restored_regs.has(t3)));
|
||||
// Restore the registers from the last output frame.
|
||||
__ Move(t3, a2);
|
||||
for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
|
||||
|
@ -2899,22 +2899,22 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
// Save all parameter registers (see wasm-linkage.h). They might be
|
||||
// overwritten in the runtime call below. We don't have any callee-saved
|
||||
// registers in wasm, so no need to store anything else.
|
||||
RegList gp_regs = 0;
|
||||
RegList gp_regs;
|
||||
for (Register gp_param_reg : wasm::kGpParamRegisters) {
|
||||
gp_regs |= gp_param_reg.bit();
|
||||
gp_regs.set(gp_param_reg);
|
||||
}
|
||||
|
||||
RegList fp_regs = 0;
|
||||
RegList fp_regs;
|
||||
for (DoubleRegister fp_param_reg : wasm::kFpParamRegisters) {
|
||||
fp_regs |= fp_param_reg.bit();
|
||||
fp_regs.set(fp_param_reg);
|
||||
}
|
||||
|
||||
CHECK_EQ(NumRegs(gp_regs), arraysize(wasm::kGpParamRegisters));
|
||||
CHECK_EQ(NumRegs(fp_regs), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(gp_regs.Count(), arraysize(wasm::kGpParamRegisters));
|
||||
CHECK_EQ(fp_regs.Count(), arraysize(wasm::kFpParamRegisters));
|
||||
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs,
|
||||
NumRegs(gp_regs));
|
||||
gp_regs.Count());
|
||||
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs,
|
||||
NumRegs(fp_regs));
|
||||
fp_regs.Count());
|
||||
|
||||
__ MultiPush(gp_regs);
|
||||
__ MultiPushF64OrV128(fp_regs);
|
||||
|
@ -2845,19 +2845,19 @@ void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
|
||||
|
||||
// Save all parameter registers. They might hold live values, we restore
|
||||
// them after the runtime call.
|
||||
for (int reg_code : base::bits::IterateBitsBackwards(
|
||||
WasmDebugBreakFrameConstants::kPushedGpRegs)) {
|
||||
__ Push(Register::from_code(reg_code));
|
||||
for (Register reg :
|
||||
base::Reversed(WasmDebugBreakFrameConstants::kPushedGpRegs)) {
|
||||
__ Push(reg);
|
||||
}
|
||||
|
||||
constexpr int kFpStackSize =
|
||||
kSimd128Size * WasmDebugBreakFrameConstants::kNumPushedFpRegisters;
|
||||
__ AllocateStackSpace(kFpStackSize);
|
||||
int offset = kFpStackSize;
|
||||
for (int reg_code : base::bits::IterateBitsBackwards(
|
||||
WasmDebugBreakFrameConstants::kPushedFpRegs)) {
|
||||
for (DoubleRegister reg :
|
||||
base::Reversed(WasmDebugBreakFrameConstants::kPushedFpRegs)) {
|
||||
offset -= kSimd128Size;
|
||||
__ movdqu(Operand(rsp, offset), DoubleRegister::from_code(reg_code));
|
||||
__ movdqu(Operand(rsp, offset), reg);
|
||||
}
|
||||
|
||||
// Initialize the JavaScript context with 0. CEntry will use it to
|
||||
@ -2866,15 +2866,13 @@ void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
|
||||
__ CallRuntime(Runtime::kWasmDebugBreak, 0);
|
||||
|
||||
// Restore registers.
|
||||
for (int reg_code :
|
||||
base::bits::IterateBits(WasmDebugBreakFrameConstants::kPushedFpRegs)) {
|
||||
__ movdqu(DoubleRegister::from_code(reg_code), Operand(rsp, offset));
|
||||
for (DoubleRegister reg : WasmDebugBreakFrameConstants::kPushedFpRegs) {
|
||||
__ movdqu(reg, Operand(rsp, offset));
|
||||
offset += kSimd128Size;
|
||||
}
|
||||
__ addq(rsp, Immediate(kFpStackSize));
|
||||
for (int reg_code :
|
||||
base::bits::IterateBits(WasmDebugBreakFrameConstants::kPushedGpRegs)) {
|
||||
__ Pop(Register::from_code(reg_code));
|
||||
for (Register reg : WasmDebugBreakFrameConstants::kPushedGpRegs) {
|
||||
__ Pop(reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -533,7 +533,7 @@ Assembler::Assembler(const AssemblerOptions& options,
|
||||
std::unique_ptr<AssemblerBuffer> buffer)
|
||||
: AssemblerBase(options, std::move(buffer)),
|
||||
pending_32_bit_constants_(),
|
||||
scratch_register_list_(ip.bit()) {
|
||||
scratch_register_list_({ip}) {
|
||||
reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
|
||||
constant_pool_deadline_ = kMaxInt;
|
||||
const_pool_blocked_nesting_ = 0;
|
||||
@ -1412,9 +1412,9 @@ void Assembler::AddrMode3(Instr instr, Register rd, const MemOperand& x) {
|
||||
|
||||
void Assembler::AddrMode4(Instr instr, Register rn, RegList rl) {
|
||||
DCHECK((instr & ~(kCondMask | P | U | W | L)) == B27);
|
||||
DCHECK_NE(rl, 0);
|
||||
DCHECK(!rl.is_empty());
|
||||
DCHECK(rn != pc);
|
||||
emit(instr | rn.code() * B16 | rl);
|
||||
emit(instr | rn.code() * B16 | rl.bits());
|
||||
}
|
||||
|
||||
void Assembler::AddrMode5(Instr instr, CRegister crd, const MemOperand& x) {
|
||||
@ -2251,12 +2251,12 @@ void Assembler::pld(const MemOperand& address) {
|
||||
void Assembler::ldm(BlockAddrMode am, Register base, RegList dst,
|
||||
Condition cond) {
|
||||
// ABI stack constraint: ldmxx base, {..sp..} base != sp is not restartable.
|
||||
DCHECK(base == sp || (dst & sp.bit()) == 0);
|
||||
DCHECK(base == sp || !dst.has(sp));
|
||||
|
||||
AddrMode4(cond | B27 | am | L, base, dst);
|
||||
|
||||
// Emit the constant pool after a function return implemented by ldm ..{..pc}.
|
||||
if (cond == al && (dst & pc.bit()) != 0) {
|
||||
if (cond == al && dst.has(pc)) {
|
||||
// There is a slight chance that the ldm instruction was actually a call,
|
||||
// in which case it would be wrong to return into the constant pool; we
|
||||
// recognize this case by checking if the emission of the pool was blocked
|
||||
@ -5499,11 +5499,7 @@ UseScratchRegisterScope::~UseScratchRegisterScope() {
|
||||
Register UseScratchRegisterScope::Acquire() {
|
||||
RegList* available = assembler_->GetScratchRegisterList();
|
||||
DCHECK_NOT_NULL(available);
|
||||
DCHECK_NE(*available, 0);
|
||||
int index = static_cast<int>(base::bits::CountTrailingZeros32(*available));
|
||||
Register reg = Register::from_code(index);
|
||||
*available &= ~reg.bit();
|
||||
return reg;
|
||||
return available->PopFirst();
|
||||
}
|
||||
|
||||
LoadStoreLaneParams::LoadStoreLaneParams(MachineRepresentation rep,
|
||||
|
@ -1399,21 +1399,25 @@ class V8_EXPORT_PRIVATE V8_NODISCARD UseScratchRegisterScope {
|
||||
}
|
||||
|
||||
// Check if we have registers available to acquire.
|
||||
bool CanAcquire() const { return *assembler_->GetScratchRegisterList() != 0; }
|
||||
bool CanAcquire() const {
|
||||
return !assembler_->GetScratchRegisterList()->is_empty();
|
||||
}
|
||||
bool CanAcquireD() const { return CanAcquireVfp<DwVfpRegister>(); }
|
||||
|
||||
void Include(const Register& reg1, const Register& reg2 = no_reg) {
|
||||
RegList* available = assembler_->GetScratchRegisterList();
|
||||
DCHECK_NOT_NULL(available);
|
||||
DCHECK_EQ((*available) & (reg1.bit() | reg2.bit()), 0);
|
||||
*available |= reg1.bit() | reg2.bit();
|
||||
DCHECK(!available->has(reg1));
|
||||
DCHECK(!available->has(reg2));
|
||||
available->set(reg1);
|
||||
available->set(reg2);
|
||||
}
|
||||
void Exclude(const Register& reg1, const Register& reg2 = no_reg) {
|
||||
RegList* available = assembler_->GetScratchRegisterList();
|
||||
DCHECK_NOT_NULL(available);
|
||||
DCHECK_EQ((*available) & (reg1.bit() | reg2.bit()),
|
||||
reg1.bit() | reg2.bit());
|
||||
*available &= ~(reg1.bit() | reg2.bit());
|
||||
DCHECK(available->has(reg1));
|
||||
DCHECK_IMPLIES(reg2.is_valid(), available->has(reg2));
|
||||
available->clear(RegList{reg1, reg2});
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -24,21 +24,21 @@ template <typename DerivedDescriptor>
|
||||
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
|
||||
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
|
||||
RegList allocatable_regs = data->allocatable_registers();
|
||||
if (argc >= 1) DCHECK(allocatable_regs | r0.bit());
|
||||
if (argc >= 2) DCHECK(allocatable_regs | r1.bit());
|
||||
if (argc >= 3) DCHECK(allocatable_regs | r2.bit());
|
||||
if (argc >= 4) DCHECK(allocatable_regs | r3.bit());
|
||||
if (argc >= 5) DCHECK(allocatable_regs | r4.bit());
|
||||
if (argc >= 6) DCHECK(allocatable_regs | r5.bit());
|
||||
if (argc >= 7) DCHECK(allocatable_regs | r6.bit());
|
||||
if (argc >= 8) DCHECK(allocatable_regs | r7.bit());
|
||||
if (argc >= 1) DCHECK(allocatable_regs.has(r0));
|
||||
if (argc >= 2) DCHECK(allocatable_regs.has(r1));
|
||||
if (argc >= 3) DCHECK(allocatable_regs.has(r2));
|
||||
if (argc >= 4) DCHECK(allocatable_regs.has(r3));
|
||||
if (argc >= 5) DCHECK(allocatable_regs.has(r4));
|
||||
if (argc >= 6) DCHECK(allocatable_regs.has(r5));
|
||||
if (argc >= 7) DCHECK(allocatable_regs.has(r6));
|
||||
if (argc >= 8) DCHECK(allocatable_regs.has(r7));
|
||||
// Additional arguments are passed on the stack.
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
// static
|
||||
constexpr auto WriteBarrierDescriptor::registers() {
|
||||
return RegisterArray(r1, r5, r4, r2, r0);
|
||||
return RegisterArray(r1, r5, r4, r2, r0, r3, kContextRegister);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -45,20 +45,10 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
|
||||
Register exclusion2,
|
||||
Register exclusion3) const {
|
||||
int bytes = 0;
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = (kCallerSaved | lr) - exclusions;
|
||||
|
||||
RegList list = (kCallerSaved | lr.bit()) & ~exclusions;
|
||||
|
||||
bytes += NumRegs(list) * kPointerSize;
|
||||
bytes += list.Count() * kPointerSize;
|
||||
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
bytes += DwVfpRegister::kNumRegisters * DwVfpRegister::kSizeInBytes;
|
||||
@ -71,21 +61,11 @@ int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
|
||||
Register exclusion2, Register exclusion3) {
|
||||
ASM_CODE_COMMENT(this);
|
||||
int bytes = 0;
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = (kCallerSaved | lr.bit()) & ~exclusions;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = (kCallerSaved | lr) - exclusions;
|
||||
stm(db_w, sp, list);
|
||||
|
||||
bytes += NumRegs(list) * kPointerSize;
|
||||
bytes += list.Count() * kPointerSize;
|
||||
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
SaveFPRegs(sp, lr);
|
||||
@ -104,21 +84,11 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
|
||||
bytes += DwVfpRegister::kNumRegisters * DwVfpRegister::kSizeInBytes;
|
||||
}
|
||||
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = (kCallerSaved | lr.bit()) & ~exclusions;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = (kCallerSaved | lr) - exclusions;
|
||||
ldm(ia_w, sp, list);
|
||||
|
||||
bytes += NumRegs(list) * kPointerSize;
|
||||
bytes += list.Count() * kPointerSize;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
@ -696,27 +666,15 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
if (registers.is_empty()) return;
|
||||
ASM_CODE_COMMENT(this);
|
||||
RegList regs = 0;
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
regs |= Register::from_code(i).bit();
|
||||
}
|
||||
}
|
||||
stm(db_w, sp, regs);
|
||||
stm(db_w, sp, registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
if (registers.is_empty()) return;
|
||||
ASM_CODE_COMMENT(this);
|
||||
RegList regs = 0;
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
regs |= Register::from_code(i).bit();
|
||||
}
|
||||
}
|
||||
ldm(ia_w, sp, regs);
|
||||
ldm(ia_w, sp, registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object, Operand offset,
|
||||
@ -876,15 +834,15 @@ void TurboAssembler::PushCommonFrame(Register marker_reg) {
|
||||
ASM_CODE_COMMENT(this);
|
||||
if (marker_reg.is_valid()) {
|
||||
if (marker_reg.code() > fp.code()) {
|
||||
stm(db_w, sp, fp.bit() | lr.bit());
|
||||
stm(db_w, sp, {fp, lr});
|
||||
mov(fp, Operand(sp));
|
||||
Push(marker_reg);
|
||||
} else {
|
||||
stm(db_w, sp, marker_reg.bit() | fp.bit() | lr.bit());
|
||||
stm(db_w, sp, {marker_reg, fp, lr});
|
||||
add(fp, sp, Operand(kPointerSize));
|
||||
}
|
||||
} else {
|
||||
stm(db_w, sp, fp.bit() | lr.bit());
|
||||
stm(db_w, sp, {fp, lr});
|
||||
mov(fp, sp);
|
||||
}
|
||||
}
|
||||
@ -892,9 +850,7 @@ void TurboAssembler::PushCommonFrame(Register marker_reg) {
|
||||
void TurboAssembler::PushStandardFrame(Register function_reg) {
|
||||
ASM_CODE_COMMENT(this);
|
||||
DCHECK(!function_reg.is_valid() || function_reg.code() < cp.code());
|
||||
stm(db_w, sp,
|
||||
(function_reg.is_valid() ? function_reg.bit() : 0) | cp.bit() | fp.bit() |
|
||||
lr.bit());
|
||||
stm(db_w, sp, {function_reg, cp, fp, lr});
|
||||
int offset = -StandardFrameConstants::kContextOffset;
|
||||
offset += function_reg.is_valid() ? kPointerSize : 0;
|
||||
add(fp, sp, Operand(offset));
|
||||
@ -1426,7 +1382,7 @@ int TurboAssembler::LeaveFrame(StackFrame::Type type) {
|
||||
// the caller frame pointer and return address.
|
||||
mov(sp, fp);
|
||||
int frame_ends = pc_offset();
|
||||
ldm(ia_w, sp, fp.bit() | lr.bit());
|
||||
ldm(ia_w, sp, {fp, lr});
|
||||
return frame_ends;
|
||||
}
|
||||
|
||||
@ -1575,7 +1531,7 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count,
|
||||
|
||||
// Tear down the exit frame, pop the arguments, and return.
|
||||
mov(sp, Operand(fp));
|
||||
ldm(ia_w, sp, fp.bit() | lr.bit());
|
||||
ldm(ia_w, sp, {fp, lr});
|
||||
if (argument_count.is_valid()) {
|
||||
if (argument_count_is_length) {
|
||||
add(sp, sp, argument_count);
|
||||
@ -2659,19 +2615,13 @@ void TurboAssembler::CheckPageFlag(Register object, int mask, Condition cc,
|
||||
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
|
||||
Register reg4, Register reg5,
|
||||
Register reg6) {
|
||||
RegList regs = 0;
|
||||
if (reg1.is_valid()) regs |= reg1.bit();
|
||||
if (reg2.is_valid()) regs |= reg2.bit();
|
||||
if (reg3.is_valid()) regs |= reg3.bit();
|
||||
if (reg4.is_valid()) regs |= reg4.bit();
|
||||
if (reg5.is_valid()) regs |= reg5.bit();
|
||||
if (reg6.is_valid()) regs |= reg6.bit();
|
||||
RegList regs = {reg1, reg2, reg3, reg4, reg5, reg6};
|
||||
|
||||
const RegisterConfiguration* config = RegisterConfiguration::Default();
|
||||
for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
|
||||
int code = config->GetAllocatableGeneralCode(i);
|
||||
Register candidate = Register::from_code(code);
|
||||
if (regs & candidate.bit()) continue;
|
||||
if (regs.has(candidate)) continue;
|
||||
return candidate;
|
||||
}
|
||||
UNREACHABLE();
|
||||
|
@ -97,7 +97,7 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
// Push two registers. Pushes leftmost register first (to highest address).
|
||||
void Push(Register src1, Register src2, Condition cond = al) {
|
||||
if (src1.code() > src2.code()) {
|
||||
stm(db_w, sp, src1.bit() | src2.bit(), cond);
|
||||
stm(db_w, sp, {src1, src2}, cond);
|
||||
} else {
|
||||
str(src1, MemOperand(sp, 4, NegPreIndex), cond);
|
||||
str(src2, MemOperand(sp, 4, NegPreIndex), cond);
|
||||
@ -108,9 +108,9 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
void Push(Register src1, Register src2, Register src3, Condition cond = al) {
|
||||
if (src1.code() > src2.code()) {
|
||||
if (src2.code() > src3.code()) {
|
||||
stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
|
||||
stm(db_w, sp, {src1, src2, src3}, cond);
|
||||
} else {
|
||||
stm(db_w, sp, src1.bit() | src2.bit(), cond);
|
||||
stm(db_w, sp, {src1, src2}, cond);
|
||||
str(src3, MemOperand(sp, 4, NegPreIndex), cond);
|
||||
}
|
||||
} else {
|
||||
@ -125,14 +125,13 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
if (src1.code() > src2.code()) {
|
||||
if (src2.code() > src3.code()) {
|
||||
if (src3.code() > src4.code()) {
|
||||
stm(db_w, sp, src1.bit() | src2.bit() | src3.bit() | src4.bit(),
|
||||
cond);
|
||||
stm(db_w, sp, {src1, src2, src3, src4}, cond);
|
||||
} else {
|
||||
stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
|
||||
stm(db_w, sp, {src1, src2, src3}, cond);
|
||||
str(src4, MemOperand(sp, 4, NegPreIndex), cond);
|
||||
}
|
||||
} else {
|
||||
stm(db_w, sp, src1.bit() | src2.bit(), cond);
|
||||
stm(db_w, sp, {src1, src2}, cond);
|
||||
Push(src3, src4, cond);
|
||||
}
|
||||
} else {
|
||||
@ -148,20 +147,17 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
if (src2.code() > src3.code()) {
|
||||
if (src3.code() > src4.code()) {
|
||||
if (src4.code() > src5.code()) {
|
||||
stm(db_w, sp,
|
||||
src1.bit() | src2.bit() | src3.bit() | src4.bit() | src5.bit(),
|
||||
cond);
|
||||
stm(db_w, sp, {src1, src2, src3, src4, src5}, cond);
|
||||
} else {
|
||||
stm(db_w, sp, src1.bit() | src2.bit() | src3.bit() | src4.bit(),
|
||||
cond);
|
||||
stm(db_w, sp, {src1, src2, src3, src4}, cond);
|
||||
str(src5, MemOperand(sp, 4, NegPreIndex), cond);
|
||||
}
|
||||
} else {
|
||||
stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
|
||||
stm(db_w, sp, {src1, src2, src3}, cond);
|
||||
Push(src4, src5, cond);
|
||||
}
|
||||
} else {
|
||||
stm(db_w, sp, src1.bit() | src2.bit(), cond);
|
||||
stm(db_w, sp, {src1, src2}, cond);
|
||||
Push(src3, src4, src5, cond);
|
||||
}
|
||||
} else {
|
||||
@ -182,7 +178,7 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
void Pop(Register src1, Register src2, Condition cond = al) {
|
||||
DCHECK(src1 != src2);
|
||||
if (src1.code() > src2.code()) {
|
||||
ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
|
||||
ldm(ia_w, sp, {src1, src2}, cond);
|
||||
} else {
|
||||
ldr(src2, MemOperand(sp, 4, PostIndex), cond);
|
||||
ldr(src1, MemOperand(sp, 4, PostIndex), cond);
|
||||
@ -194,10 +190,10 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
DCHECK(!AreAliased(src1, src2, src3));
|
||||
if (src1.code() > src2.code()) {
|
||||
if (src2.code() > src3.code()) {
|
||||
ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
|
||||
ldm(ia_w, sp, {src1, src2, src3}, cond);
|
||||
} else {
|
||||
ldr(src3, MemOperand(sp, 4, PostIndex), cond);
|
||||
ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
|
||||
ldm(ia_w, sp, {src1, src2}, cond);
|
||||
}
|
||||
} else {
|
||||
Pop(src2, src3, cond);
|
||||
@ -212,15 +208,14 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
if (src1.code() > src2.code()) {
|
||||
if (src2.code() > src3.code()) {
|
||||
if (src3.code() > src4.code()) {
|
||||
ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit() | src4.bit(),
|
||||
cond);
|
||||
ldm(ia_w, sp, {src1, src2, src3, src4}, cond);
|
||||
} else {
|
||||
ldr(src4, MemOperand(sp, 4, PostIndex), cond);
|
||||
ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
|
||||
ldm(ia_w, sp, {src1, src2, src3}, cond);
|
||||
}
|
||||
} else {
|
||||
Pop(src3, src4, cond);
|
||||
ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
|
||||
ldm(ia_w, sp, {src1, src2}, cond);
|
||||
}
|
||||
} else {
|
||||
Pop(src2, src3, src4, cond);
|
||||
|
@ -6,8 +6,6 @@
|
||||
#define V8_CODEGEN_ARM_REGISTER_ARM_H_
|
||||
|
||||
#include "src/codegen/register-base.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/codegen/reglist.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -62,40 +60,6 @@ namespace internal {
|
||||
// leave it alone. Adjust the value of kR9Available accordingly:
|
||||
const int kR9Available = 1; // 1 if available to us, 0 if reserved
|
||||
|
||||
// Register list in load/store instructions
|
||||
// Note that the bit values must match those used in actual instruction encoding
|
||||
|
||||
// Caller-saved/arguments registers
|
||||
const RegList kJSCallerSaved = 1 << 0 | // r0 a1
|
||||
1 << 1 | // r1 a2
|
||||
1 << 2 | // r2 a3
|
||||
1 << 3; // r3 a4
|
||||
|
||||
const int kNumJSCallerSaved = 4;
|
||||
|
||||
// Callee-saved registers preserved when switching from C to JavaScript
|
||||
const RegList kCalleeSaved = 1 << 4 | // r4 v1
|
||||
1 << 5 | // r5 v2
|
||||
1 << 6 | // r6 v3
|
||||
1 << 7 | // r7 v4 (cp in JavaScript code)
|
||||
1 << 8 | // r8 v5 (pp in JavaScript code)
|
||||
kR9Available << 9 | // r9 v6
|
||||
1 << 10 | // r10 v7
|
||||
1 << 11; // r11 v8 (fp in JavaScript code)
|
||||
|
||||
// When calling into C++ (only for C++ calls that can't cause a GC).
|
||||
// The call code will take care of lr, fp, etc.
|
||||
const RegList kCallerSaved = 1 << 0 | // r0
|
||||
1 << 1 | // r1
|
||||
1 << 2 | // r2
|
||||
1 << 3 | // r3
|
||||
1 << 9; // r9
|
||||
|
||||
const int kNumCalleeSaved = 7 + kR9Available;
|
||||
|
||||
// Double registers d8 to d15 are callee-saved.
|
||||
const int kNumDoubleCalleeSaved = 8;
|
||||
|
||||
enum RegisterCode {
|
||||
#define REGISTER_CODE(R) kRegCode_##R,
|
||||
GENERAL_REGISTERS(REGISTER_CODE)
|
||||
@ -357,6 +321,7 @@ constexpr Register kWasmCompileLazyFuncIndexRegister = r4;
|
||||
|
||||
// Give alias names to registers
|
||||
constexpr Register cp = r7; // JavaScript context pointer.
|
||||
constexpr Register r11 = fp;
|
||||
constexpr Register kRootRegister = r10; // Roots array pointer.
|
||||
|
||||
constexpr DoubleRegister kFPReturnRegister0 = d0;
|
||||
|
56
src/codegen/arm/reglist-arm.h
Normal file
56
src/codegen/arm/reglist-arm.h
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_CODEGEN_ARM_REGLIST_ARM_H_
|
||||
#define V8_CODEGEN_ARM_REGLIST_ARM_H_
|
||||
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/reglist-base.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
using RegList = RegListBase<Register>;
|
||||
using DoubleRegList = RegListBase<DoubleRegister>;
|
||||
ASSERT_TRIVIALLY_COPYABLE(RegList);
|
||||
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
|
||||
|
||||
// Register list in load/store instructions
|
||||
// Note that the bit values must match those used in actual instruction encoding
|
||||
|
||||
// Caller-saved/arguments registers
|
||||
const RegList kJSCallerSaved = {r0, // r0 a1
|
||||
r1, // r1 a2
|
||||
r2, // r2 a3
|
||||
r3}; // r3 a4
|
||||
|
||||
const int kNumJSCallerSaved = 4;
|
||||
|
||||
// Callee-saved registers preserved when switching from C to JavaScript
|
||||
const RegList kCalleeSaved = {r4, // r4 v1
|
||||
r5, // r5 v2
|
||||
r6, // r6 v3
|
||||
r7, // r7 v4 (cp in JavaScript code)
|
||||
r8, // r8 v5 (pp in JavaScript code)
|
||||
kR9Available ? r9 : Register::no_reg(), // r9 v6
|
||||
r10, // r10 v7
|
||||
r11}; // r11 v8 (fp in JavaScript code)
|
||||
|
||||
// When calling into C++ (only for C++ calls that can't cause a GC).
|
||||
// The call code will take care of lr, fp, etc.
|
||||
const RegList kCallerSaved = {r0, // r0
|
||||
r1, // r1
|
||||
r2, // r2
|
||||
r3, // r3
|
||||
r9}; // r9
|
||||
|
||||
const int kNumCalleeSaved = 7 + kR9Available;
|
||||
|
||||
// Double registers d8 to d15 are callee-saved.
|
||||
const int kNumDoubleCalleeSaved = 8;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_CODEGEN_ARM_REGLIST_ARM_H_
|
@ -54,12 +54,12 @@ inline bool CPURegister::IsSP() const {
|
||||
inline void CPURegList::Combine(const CPURegList& other) {
|
||||
DCHECK(other.type() == type_);
|
||||
DCHECK(other.RegisterSizeInBits() == size_);
|
||||
list_ |= other.list();
|
||||
list_ |= other.list_;
|
||||
}
|
||||
|
||||
inline void CPURegList::Remove(const CPURegList& other) {
|
||||
if (other.type() == type_) {
|
||||
list_ &= ~other.list();
|
||||
list_ &= ~other.list_;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,18 +228,18 @@ bool AreAliased(const CPURegister& reg1, const CPURegister& reg2,
|
||||
int number_of_valid_regs = 0;
|
||||
int number_of_valid_fpregs = 0;
|
||||
|
||||
RegList unique_regs = 0;
|
||||
RegList unique_fpregs = 0;
|
||||
uint64_t unique_regs = 0;
|
||||
uint64_t unique_fpregs = 0;
|
||||
|
||||
const CPURegister regs[] = {reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8};
|
||||
|
||||
for (unsigned i = 0; i < arraysize(regs); i++) {
|
||||
if (regs[i].IsRegister()) {
|
||||
number_of_valid_regs++;
|
||||
unique_regs |= regs[i].bit();
|
||||
unique_regs |= (uint64_t{1} << regs[i].code());
|
||||
} else if (regs[i].IsVRegister()) {
|
||||
number_of_valid_fpregs++;
|
||||
unique_fpregs |= regs[i].bit();
|
||||
unique_fpregs |= (uint64_t{1} << regs[i].code());
|
||||
} else {
|
||||
DCHECK(!regs[i].is_valid());
|
||||
}
|
||||
|
@ -25,20 +25,21 @@ template <typename DerivedDescriptor>
|
||||
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
|
||||
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
|
||||
RegList allocatable_regs = data->allocatable_registers();
|
||||
if (argc >= 1) DCHECK(allocatable_regs | x0.bit());
|
||||
if (argc >= 2) DCHECK(allocatable_regs | x1.bit());
|
||||
if (argc >= 3) DCHECK(allocatable_regs | x2.bit());
|
||||
if (argc >= 4) DCHECK(allocatable_regs | x3.bit());
|
||||
if (argc >= 5) DCHECK(allocatable_regs | x4.bit());
|
||||
if (argc >= 6) DCHECK(allocatable_regs | x5.bit());
|
||||
if (argc >= 7) DCHECK(allocatable_regs | x6.bit());
|
||||
if (argc >= 8) DCHECK(allocatable_regs | x7.bit());
|
||||
if (argc >= 1) DCHECK(allocatable_regs.has(x0));
|
||||
if (argc >= 2) DCHECK(allocatable_regs.has(x1));
|
||||
if (argc >= 3) DCHECK(allocatable_regs.has(x2));
|
||||
if (argc >= 4) DCHECK(allocatable_regs.has(x3));
|
||||
if (argc >= 5) DCHECK(allocatable_regs.has(x4));
|
||||
if (argc >= 6) DCHECK(allocatable_regs.has(x5));
|
||||
if (argc >= 7) DCHECK(allocatable_regs.has(x6));
|
||||
if (argc >= 8) DCHECK(allocatable_regs.has(x7));
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
// static
|
||||
constexpr auto WriteBarrierDescriptor::registers() {
|
||||
return RegisterArray(x1, x5, x4, x2, x0, x3);
|
||||
// TODO(leszeks): Remove x7 which is just there for padding.
|
||||
return RegisterArray(x1, x5, x4, x2, x0, x3, kContextRegister, x7);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -3134,9 +3134,9 @@ void TurboAssembler::LoadExternalPointerField(Register destination,
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
if (registers.is_empty()) return;
|
||||
ASM_CODE_COMMENT(this);
|
||||
CPURegList regs(CPURegister::kRegister, kXRegSizeInBits, registers);
|
||||
CPURegList regs(kXRegSizeInBits, registers);
|
||||
// If we were saving LR, we might need to sign it.
|
||||
DCHECK(!regs.IncludesAliasOf(lr));
|
||||
regs.Align();
|
||||
@ -3144,9 +3144,9 @@ void TurboAssembler::MaybeSaveRegisters(RegList registers) {
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
if (registers.is_empty()) return;
|
||||
ASM_CODE_COMMENT(this);
|
||||
CPURegList regs(CPURegister::kRegister, kXRegSizeInBits, registers);
|
||||
CPURegList regs(kXRegSizeInBits, registers);
|
||||
// If we were saving LR, we might need to sign it.
|
||||
DCHECK(!regs.IncludesAliasOf(lr));
|
||||
regs.Align();
|
||||
@ -3346,7 +3346,7 @@ void TurboAssembler::Abort(AbortReason reason) {
|
||||
|
||||
// We need some scratch registers for the MacroAssembler, so make sure we have
|
||||
// some. This is safe here because Abort never returns.
|
||||
RegList old_tmp_list = TmpList()->list();
|
||||
uint64_t old_tmp_list = TmpList()->bits();
|
||||
TmpList()->Combine(MacroAssembler::DefaultTmpList());
|
||||
|
||||
if (should_abort_hard()) {
|
||||
@ -3371,7 +3371,7 @@ void TurboAssembler::Abort(AbortReason reason) {
|
||||
Call(BUILTIN_CODE(isolate(), Abort), RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
TmpList()->set_list(old_tmp_list);
|
||||
TmpList()->set_bits(old_tmp_list);
|
||||
}
|
||||
|
||||
void MacroAssembler::LoadNativeContextSlot(Register dst, int index) {
|
||||
@ -3421,8 +3421,8 @@ void TurboAssembler::PrintfNoPreserve(const char* format,
|
||||
// Override the TurboAssembler's scratch register list. The lists will be
|
||||
// reset automatically at the end of the UseScratchRegisterScope.
|
||||
UseScratchRegisterScope temps(this);
|
||||
TmpList()->set_list(tmp_list.list());
|
||||
FPTmpList()->set_list(fp_tmp_list.list());
|
||||
TmpList()->set_bits(tmp_list.bits());
|
||||
FPTmpList()->set_bits(fp_tmp_list.bits());
|
||||
|
||||
// Copies of the printf vararg registers that we can pop from.
|
||||
CPURegList pcs_varargs = kPCSVarargs;
|
||||
@ -3570,10 +3570,10 @@ void TurboAssembler::Printf(const char* format, CPURegister arg0,
|
||||
ASM_CODE_COMMENT(this);
|
||||
// Printf is expected to preserve all registers, so make sure that none are
|
||||
// available as scratch registers until we've preserved them.
|
||||
RegList old_tmp_list = TmpList()->list();
|
||||
RegList old_fp_tmp_list = FPTmpList()->list();
|
||||
TmpList()->set_list(0);
|
||||
FPTmpList()->set_list(0);
|
||||
uint64_t old_tmp_list = TmpList()->bits();
|
||||
uint64_t old_fp_tmp_list = FPTmpList()->bits();
|
||||
TmpList()->set_bits(0);
|
||||
FPTmpList()->set_bits(0);
|
||||
|
||||
CPURegList saved_registers = kCallerSaved;
|
||||
saved_registers.Align();
|
||||
@ -3589,8 +3589,8 @@ void TurboAssembler::Printf(const char* format, CPURegister arg0,
|
||||
CPURegList fp_tmp_list = kCallerSavedV;
|
||||
tmp_list.Remove(arg0, arg1, arg2, arg3);
|
||||
fp_tmp_list.Remove(arg0, arg1, arg2, arg3);
|
||||
TmpList()->set_list(tmp_list.list());
|
||||
FPTmpList()->set_list(fp_tmp_list.list());
|
||||
TmpList()->set_bits(tmp_list.bits());
|
||||
FPTmpList()->set_bits(fp_tmp_list.bits());
|
||||
|
||||
{
|
||||
UseScratchRegisterScope temps(this);
|
||||
@ -3636,13 +3636,13 @@ void TurboAssembler::Printf(const char* format, CPURegister arg0,
|
||||
PopCPURegList(kCallerSavedV);
|
||||
PopCPURegList<kDontLoadLR>(saved_registers);
|
||||
|
||||
TmpList()->set_list(old_tmp_list);
|
||||
FPTmpList()->set_list(old_fp_tmp_list);
|
||||
TmpList()->set_bits(old_tmp_list);
|
||||
FPTmpList()->set_bits(old_fp_tmp_list);
|
||||
}
|
||||
|
||||
UseScratchRegisterScope::~UseScratchRegisterScope() {
|
||||
available_->set_list(old_available_);
|
||||
availablefp_->set_list(old_availablefp_);
|
||||
available_->set_bits(old_available_);
|
||||
availablefp_->set_bits(old_availablefp_);
|
||||
}
|
||||
|
||||
Register UseScratchRegisterScope::AcquireSameSizeAs(const Register& reg) {
|
||||
|
@ -1755,16 +1755,20 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
|
||||
// For the 'lr_mode' template argument of the following methods, see
|
||||
// PushCPURegList/PopCPURegList.
|
||||
template <StoreLRMode lr_mode = kDontStoreLR>
|
||||
inline void PushSizeRegList(
|
||||
RegList registers, unsigned reg_size,
|
||||
CPURegister::RegisterType type = CPURegister::kRegister) {
|
||||
PushCPURegList<lr_mode>(CPURegList(type, reg_size, registers));
|
||||
inline void PushSizeRegList(RegList registers, unsigned reg_size) {
|
||||
PushCPURegList<lr_mode>(CPURegList(reg_size, registers));
|
||||
}
|
||||
template <StoreLRMode lr_mode = kDontStoreLR>
|
||||
inline void PushSizeRegList(DoubleRegList registers, unsigned reg_size) {
|
||||
PushCPURegList<lr_mode>(CPURegList(reg_size, registers));
|
||||
}
|
||||
template <LoadLRMode lr_mode = kDontLoadLR>
|
||||
inline void PopSizeRegList(
|
||||
RegList registers, unsigned reg_size,
|
||||
CPURegister::RegisterType type = CPURegister::kRegister) {
|
||||
PopCPURegList<lr_mode>(CPURegList(type, reg_size, registers));
|
||||
inline void PopSizeRegList(RegList registers, unsigned reg_size) {
|
||||
PopCPURegList<lr_mode>(CPURegList(reg_size, registers));
|
||||
}
|
||||
template <LoadLRMode lr_mode = kDontLoadLR>
|
||||
inline void PopSizeRegList(DoubleRegList registers, unsigned reg_size) {
|
||||
PopCPURegList<lr_mode>(CPURegList(reg_size, registers));
|
||||
}
|
||||
template <StoreLRMode lr_mode = kDontStoreLR>
|
||||
inline void PushXRegList(RegList regs) {
|
||||
@ -1780,23 +1784,23 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
|
||||
inline void PopWRegList(RegList regs) {
|
||||
PopSizeRegList(regs, kWRegSizeInBits);
|
||||
}
|
||||
inline void PushQRegList(RegList regs) {
|
||||
PushSizeRegList(regs, kQRegSizeInBits, CPURegister::kVRegister);
|
||||
inline void PushQRegList(DoubleRegList regs) {
|
||||
PushSizeRegList(regs, kQRegSizeInBits);
|
||||
}
|
||||
inline void PopQRegList(RegList regs) {
|
||||
PopSizeRegList(regs, kQRegSizeInBits, CPURegister::kVRegister);
|
||||
inline void PopQRegList(DoubleRegList regs) {
|
||||
PopSizeRegList(regs, kQRegSizeInBits);
|
||||
}
|
||||
inline void PushDRegList(RegList regs) {
|
||||
PushSizeRegList(regs, kDRegSizeInBits, CPURegister::kVRegister);
|
||||
inline void PushDRegList(DoubleRegList regs) {
|
||||
PushSizeRegList(regs, kDRegSizeInBits);
|
||||
}
|
||||
inline void PopDRegList(RegList regs) {
|
||||
PopSizeRegList(regs, kDRegSizeInBits, CPURegister::kVRegister);
|
||||
inline void PopDRegList(DoubleRegList regs) {
|
||||
PopSizeRegList(regs, kDRegSizeInBits);
|
||||
}
|
||||
inline void PushSRegList(RegList regs) {
|
||||
PushSizeRegList(regs, kSRegSizeInBits, CPURegister::kVRegister);
|
||||
inline void PushSRegList(DoubleRegList regs) {
|
||||
PushSizeRegList(regs, kSRegSizeInBits);
|
||||
}
|
||||
inline void PopSRegList(RegList regs) {
|
||||
PopSizeRegList(regs, kSRegSizeInBits, CPURegister::kVRegister);
|
||||
inline void PopSRegList(DoubleRegList regs) {
|
||||
PopSizeRegList(regs, kSRegSizeInBits);
|
||||
}
|
||||
|
||||
// Push the specified register 'count' times.
|
||||
@ -2154,8 +2158,8 @@ class V8_NODISCARD UseScratchRegisterScope {
|
||||
explicit UseScratchRegisterScope(TurboAssembler* tasm)
|
||||
: available_(tasm->TmpList()),
|
||||
availablefp_(tasm->FPTmpList()),
|
||||
old_available_(available_->list()),
|
||||
old_availablefp_(availablefp_->list()) {
|
||||
old_available_(available_->bits()),
|
||||
old_availablefp_(availablefp_->bits()) {
|
||||
DCHECK_EQ(available_->type(), CPURegister::kRegister);
|
||||
DCHECK_EQ(availablefp_->type(), CPURegister::kVRegister);
|
||||
}
|
||||
@ -2205,8 +2209,8 @@ class V8_NODISCARD UseScratchRegisterScope {
|
||||
CPURegList* availablefp_; // kVRegister
|
||||
|
||||
// The state of the available lists at the start of this scope.
|
||||
RegList old_available_; // kRegister
|
||||
RegList old_availablefp_; // kVRegister
|
||||
uint64_t old_available_; // kRegister
|
||||
uint64_t old_availablefp_; // kVRegister
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -7,8 +7,6 @@
|
||||
|
||||
#include "src/codegen/arm64/utils-arm64.h"
|
||||
#include "src/codegen/register-base.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/codegen/reglist.h"
|
||||
#include "src/common/globals.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -80,8 +78,6 @@ namespace internal {
|
||||
R(d25) R(d26) R(d27) R(d28)
|
||||
// clang-format on
|
||||
|
||||
constexpr int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte;
|
||||
|
||||
// Some CPURegister methods can return Register and VRegister types, so we
|
||||
// need to declare them in advance.
|
||||
class Register;
|
||||
@ -244,19 +240,6 @@ class Register : public CPURegister {
|
||||
return Register::Create(code, kXRegSizeInBits);
|
||||
}
|
||||
|
||||
// Copied from RegisterBase since there's no CPURegister::from_code.
|
||||
static constexpr Register FirstOf(RegList list) {
|
||||
DCHECK_NE(kEmptyRegList, list);
|
||||
return from_code(base::bits::CountTrailingZerosNonZero(list));
|
||||
}
|
||||
|
||||
static constexpr Register TakeFirst(RegList* list) {
|
||||
RegList value = *list;
|
||||
Register result = FirstOf(value);
|
||||
result.RemoveFrom(list);
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char* GetSpecialRegisterName(int code) {
|
||||
return (code == kSPRegInternalCode) ? "sp" : "UNKNOWN";
|
||||
}
|
||||
@ -563,150 +546,6 @@ using FloatRegister = VRegister;
|
||||
using DoubleRegister = VRegister;
|
||||
using Simd128Register = VRegister;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Lists of registers.
|
||||
class V8_EXPORT_PRIVATE CPURegList {
|
||||
public:
|
||||
template <typename... CPURegisters>
|
||||
explicit CPURegList(CPURegister reg0, CPURegisters... regs)
|
||||
: list_(CPURegister::ListOf(reg0, regs...)),
|
||||
size_(reg0.SizeInBits()),
|
||||
type_(reg0.type()) {
|
||||
DCHECK(AreSameSizeAndType(reg0, regs...));
|
||||
DCHECK(is_valid());
|
||||
}
|
||||
|
||||
CPURegList(CPURegister::RegisterType type, int size, RegList list)
|
||||
: list_(list), size_(size), type_(type) {
|
||||
DCHECK(is_valid());
|
||||
}
|
||||
|
||||
CPURegList(CPURegister::RegisterType type, int size, int first_reg,
|
||||
int last_reg)
|
||||
: size_(size), type_(type) {
|
||||
DCHECK(
|
||||
((type == CPURegister::kRegister) && (last_reg < kNumberOfRegisters)) ||
|
||||
((type == CPURegister::kVRegister) &&
|
||||
(last_reg < kNumberOfVRegisters)));
|
||||
DCHECK(last_reg >= first_reg);
|
||||
list_ = (1ULL << (last_reg + 1)) - 1;
|
||||
list_ &= ~((1ULL << first_reg) - 1);
|
||||
DCHECK(is_valid());
|
||||
}
|
||||
|
||||
CPURegister::RegisterType type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
RegList list() const {
|
||||
return list_;
|
||||
}
|
||||
|
||||
inline void set_list(RegList new_list) {
|
||||
list_ = new_list;
|
||||
DCHECK(is_valid());
|
||||
}
|
||||
|
||||
// Combine another CPURegList into this one. Registers that already exist in
|
||||
// this list are left unchanged. The type and size of the registers in the
|
||||
// 'other' list must match those in this list.
|
||||
void Combine(const CPURegList& other);
|
||||
|
||||
// Remove every register in the other CPURegList from this one. Registers that
|
||||
// do not exist in this list are ignored. The type of the registers in the
|
||||
// 'other' list must match those in this list.
|
||||
void Remove(const CPURegList& other);
|
||||
|
||||
// Variants of Combine and Remove which take CPURegisters.
|
||||
void Combine(const CPURegister& other);
|
||||
void Remove(const CPURegister& other1, const CPURegister& other2 = NoCPUReg,
|
||||
const CPURegister& other3 = NoCPUReg,
|
||||
const CPURegister& other4 = NoCPUReg);
|
||||
|
||||
// Variants of Combine and Remove which take a single register by its code;
|
||||
// the type and size of the register is inferred from this list.
|
||||
void Combine(int code);
|
||||
void Remove(int code);
|
||||
|
||||
// Align the list to 16 bytes.
|
||||
void Align();
|
||||
|
||||
CPURegister PopLowestIndex();
|
||||
CPURegister PopHighestIndex();
|
||||
|
||||
// AAPCS64 callee-saved registers.
|
||||
static CPURegList GetCalleeSaved(int size = kXRegSizeInBits);
|
||||
static CPURegList GetCalleeSavedV(int size = kDRegSizeInBits);
|
||||
|
||||
// AAPCS64 caller-saved registers. Note that this includes lr.
|
||||
// TODO(all): Determine how we handle d8-d15 being callee-saved, but the top
|
||||
// 64-bits being caller-saved.
|
||||
static CPURegList GetCallerSaved(int size = kXRegSizeInBits);
|
||||
static CPURegList GetCallerSavedV(int size = kDRegSizeInBits);
|
||||
|
||||
bool IsEmpty() const {
|
||||
return list_ == 0;
|
||||
}
|
||||
|
||||
bool IncludesAliasOf(const CPURegister& other1,
|
||||
const CPURegister& other2 = NoCPUReg,
|
||||
const CPURegister& other3 = NoCPUReg,
|
||||
const CPURegister& other4 = NoCPUReg) const {
|
||||
RegList list = 0;
|
||||
if (!other1.IsNone() && (other1.type() == type_)) list |= other1.bit();
|
||||
if (!other2.IsNone() && (other2.type() == type_)) list |= other2.bit();
|
||||
if (!other3.IsNone() && (other3.type() == type_)) list |= other3.bit();
|
||||
if (!other4.IsNone() && (other4.type() == type_)) list |= other4.bit();
|
||||
return (list_ & list) != 0;
|
||||
}
|
||||
|
||||
int Count() const {
|
||||
return CountSetBits(list_, kRegListSizeInBits);
|
||||
}
|
||||
|
||||
int RegisterSizeInBits() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
int RegisterSizeInBytes() const {
|
||||
int size_in_bits = RegisterSizeInBits();
|
||||
DCHECK_EQ(size_in_bits % kBitsPerByte, 0);
|
||||
return size_in_bits / kBitsPerByte;
|
||||
}
|
||||
|
||||
int TotalSizeInBytes() const {
|
||||
return RegisterSizeInBytes() * Count();
|
||||
}
|
||||
|
||||
private:
|
||||
RegList list_;
|
||||
int size_;
|
||||
CPURegister::RegisterType type_;
|
||||
|
||||
bool is_valid() const {
|
||||
constexpr RegList kValidRegisters{0x8000000ffffffff};
|
||||
constexpr RegList kValidVRegisters{0x0000000ffffffff};
|
||||
switch (type_) {
|
||||
case CPURegister::kRegister:
|
||||
return (list_ & kValidRegisters) == list_;
|
||||
case CPURegister::kVRegister:
|
||||
return (list_ & kValidVRegisters) == list_;
|
||||
case CPURegister::kNoRegister:
|
||||
return list_ == 0;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// AAPCS64 callee-saved registers.
|
||||
#define kCalleeSaved CPURegList::GetCalleeSaved()
|
||||
#define kCalleeSavedV CPURegList::GetCalleeSavedV()
|
||||
|
||||
// AAPCS64 caller-saved registers. Note that this includes lr.
|
||||
#define kCallerSaved CPURegList::GetCallerSaved()
|
||||
#define kCallerSavedV CPURegList::GetCallerSavedV()
|
||||
|
||||
// Define a {RegisterName} method for {Register} and {VRegister}.
|
||||
DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
|
||||
DEFINE_REGISTER_NAMES(VRegister, VECTOR_REGISTERS)
|
||||
|
176
src/codegen/arm64/reglist-arm64.h
Normal file
176
src/codegen/arm64/reglist-arm64.h
Normal file
@ -0,0 +1,176 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_CODEGEN_ARM64_REGLIST_ARM64_H_
|
||||
#define V8_CODEGEN_ARM64_REGLIST_ARM64_H_
|
||||
|
||||
#include "src/codegen/arm64/utils-arm64.h"
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/reglist-base.h"
|
||||
#include "src/common/globals.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
using RegList = RegListBase<Register>;
|
||||
using DoubleRegList = RegListBase<DoubleRegister>;
|
||||
ASSERT_TRIVIALLY_COPYABLE(RegList);
|
||||
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
|
||||
|
||||
constexpr int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Lists of registers.
|
||||
class V8_EXPORT_PRIVATE CPURegList {
|
||||
public:
|
||||
template <typename... CPURegisters>
|
||||
explicit CPURegList(CPURegister reg0, CPURegisters... regs)
|
||||
: list_(base::fold(
|
||||
[](uint64_t acc, CPURegister v) {
|
||||
if (!v.is_valid()) return acc;
|
||||
return acc | (uint64_t{1} << v.code());
|
||||
},
|
||||
0, reg0, regs...)),
|
||||
size_(reg0.SizeInBits()),
|
||||
type_(reg0.type()) {
|
||||
DCHECK(AreSameSizeAndType(reg0, regs...));
|
||||
DCHECK(is_valid());
|
||||
}
|
||||
|
||||
CPURegList(int size, RegList list)
|
||||
: list_(list.bits()), size_(size), type_(CPURegister::kRegister) {
|
||||
DCHECK(is_valid());
|
||||
}
|
||||
|
||||
CPURegList(int size, DoubleRegList list)
|
||||
: list_(list.bits()), size_(size), type_(CPURegister::kVRegister) {
|
||||
DCHECK(is_valid());
|
||||
}
|
||||
|
||||
CPURegList(CPURegister::RegisterType type, int size, int first_reg,
|
||||
int last_reg)
|
||||
: size_(size), type_(type) {
|
||||
DCHECK(
|
||||
((type == CPURegister::kRegister) && (last_reg < kNumberOfRegisters)) ||
|
||||
((type == CPURegister::kVRegister) &&
|
||||
(last_reg < kNumberOfVRegisters)));
|
||||
DCHECK(last_reg >= first_reg);
|
||||
list_ = (1ULL << (last_reg + 1)) - 1;
|
||||
list_ &= ~((1ULL << first_reg) - 1);
|
||||
DCHECK(is_valid());
|
||||
}
|
||||
|
||||
CPURegister::RegisterType type() const { return type_; }
|
||||
|
||||
uint64_t bits() const { return list_; }
|
||||
|
||||
inline void set_bits(uint64_t new_bits) {
|
||||
list_ = new_bits;
|
||||
DCHECK(is_valid());
|
||||
}
|
||||
|
||||
// Combine another CPURegList into this one. Registers that already exist in
|
||||
// this list are left unchanged. The type and size of the registers in the
|
||||
// 'other' list must match those in this list.
|
||||
void Combine(const CPURegList& other);
|
||||
|
||||
// Remove every register in the other CPURegList from this one. Registers that
|
||||
// do not exist in this list are ignored. The type of the registers in the
|
||||
// 'other' list must match those in this list.
|
||||
void Remove(const CPURegList& other);
|
||||
|
||||
// Variants of Combine and Remove which take CPURegisters.
|
||||
void Combine(const CPURegister& other);
|
||||
void Remove(const CPURegister& other1, const CPURegister& other2 = NoCPUReg,
|
||||
const CPURegister& other3 = NoCPUReg,
|
||||
const CPURegister& other4 = NoCPUReg);
|
||||
|
||||
// Variants of Combine and Remove which take a single register by its code;
|
||||
// the type and size of the register is inferred from this list.
|
||||
void Combine(int code);
|
||||
void Remove(int code);
|
||||
|
||||
// Align the list to 16 bytes.
|
||||
void Align();
|
||||
|
||||
CPURegister PopLowestIndex();
|
||||
CPURegister PopHighestIndex();
|
||||
|
||||
// AAPCS64 callee-saved registers.
|
||||
static CPURegList GetCalleeSaved(int size = kXRegSizeInBits);
|
||||
static CPURegList GetCalleeSavedV(int size = kDRegSizeInBits);
|
||||
|
||||
// AAPCS64 caller-saved registers. Note that this includes lr.
|
||||
// TODO(all): Determine how we handle d8-d15 being callee-saved, but the top
|
||||
// 64-bits being caller-saved.
|
||||
static CPURegList GetCallerSaved(int size = kXRegSizeInBits);
|
||||
static CPURegList GetCallerSavedV(int size = kDRegSizeInBits);
|
||||
|
||||
bool IsEmpty() const { return list_ == 0; }
|
||||
|
||||
bool IncludesAliasOf(const CPURegister& other1,
|
||||
const CPURegister& other2 = NoCPUReg,
|
||||
const CPURegister& other3 = NoCPUReg,
|
||||
const CPURegister& other4 = NoCPUReg) const {
|
||||
uint64_t list = 0;
|
||||
if (!other1.IsNone() && (other1.type() == type_)) {
|
||||
list |= (uint64_t{1} << other1.code());
|
||||
}
|
||||
if (!other2.IsNone() && (other2.type() == type_)) {
|
||||
list |= (uint64_t{1} << other2.code());
|
||||
}
|
||||
if (!other3.IsNone() && (other3.type() == type_)) {
|
||||
list |= (uint64_t{1} << other3.code());
|
||||
}
|
||||
if (!other4.IsNone() && (other4.type() == type_)) {
|
||||
list |= (uint64_t{1} << other4.code());
|
||||
}
|
||||
return (list_ & list) != 0;
|
||||
}
|
||||
|
||||
int Count() const { return CountSetBits(list_, kRegListSizeInBits); }
|
||||
|
||||
int RegisterSizeInBits() const { return size_; }
|
||||
|
||||
int RegisterSizeInBytes() const {
|
||||
int size_in_bits = RegisterSizeInBits();
|
||||
DCHECK_EQ(size_in_bits % kBitsPerByte, 0);
|
||||
return size_in_bits / kBitsPerByte;
|
||||
}
|
||||
|
||||
int TotalSizeInBytes() const { return RegisterSizeInBytes() * Count(); }
|
||||
|
||||
private:
|
||||
uint64_t list_;
|
||||
int size_;
|
||||
CPURegister::RegisterType type_;
|
||||
|
||||
bool is_valid() const {
|
||||
constexpr uint64_t kValidRegisters{0x8000000ffffffff};
|
||||
constexpr uint64_t kValidVRegisters{0x0000000ffffffff};
|
||||
switch (type_) {
|
||||
case CPURegister::kRegister:
|
||||
return (list_ & kValidRegisters) == list_;
|
||||
case CPURegister::kVRegister:
|
||||
return (list_ & kValidVRegisters) == list_;
|
||||
case CPURegister::kNoRegister:
|
||||
return list_ == 0;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// AAPCS64 callee-saved registers.
|
||||
#define kCalleeSaved CPURegList::GetCalleeSaved()
|
||||
#define kCalleeSavedV CPURegList::GetCalleeSavedV()
|
||||
|
||||
// AAPCS64 caller-saved registers. Note that this includes lr.
|
||||
#define kCallerSaved CPURegList::GetCallerSaved()
|
||||
#define kCallerSavedV CPURegList::GetCallerSavedV()
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_CODEGEN_ARM64_REGLIST_ARM64_H_
|
@ -24,8 +24,8 @@ void StaticCallInterfaceDescriptor<DerivedDescriptor>::
|
||||
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data,
|
||||
int nof_expected_args) {
|
||||
RegList allocatable_regs = data->allocatable_registers();
|
||||
if (nof_expected_args >= 1) DCHECK(allocatable_regs | esi.bit());
|
||||
if (nof_expected_args >= 2) DCHECK(allocatable_regs | edi.bit());
|
||||
if (nof_expected_args >= 1) DCHECK(allocatable_regs.has(esi));
|
||||
if (nof_expected_args >= 2) DCHECK(allocatable_regs.has(edi));
|
||||
// Additional arguments are passed on the stack.
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
@ -428,22 +428,14 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
ASM_CODE_COMMENT(this);
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
push(Register::from_code(i));
|
||||
}
|
||||
for (Register reg : registers) {
|
||||
push(reg);
|
||||
}
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
ASM_CODE_COMMENT(this);
|
||||
for (int i = Register::kNumRegisters - 1; i >= 0; --i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
pop(Register::from_code(i));
|
||||
}
|
||||
for (Register reg : base::Reversed(registers)) {
|
||||
pop(reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,6 @@
|
||||
#define V8_CODEGEN_IA32_REGISTER_IA32_H_
|
||||
|
||||
#include "src/codegen/register-base.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/codegen/reglist.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -113,14 +111,6 @@ constexpr DoubleRegister no_dreg = DoubleRegister::no_reg();
|
||||
// Note that the bit values must match those used in actual instruction encoding
|
||||
constexpr int kNumRegs = 8;
|
||||
|
||||
// Caller-saved registers
|
||||
constexpr RegList kJSCallerSaved =
|
||||
Register::ListOf(eax, ecx, edx,
|
||||
ebx, // used as caller-saved register in JavaScript code
|
||||
edi); // callee function
|
||||
|
||||
constexpr int kNumJSCallerSaved = 5;
|
||||
|
||||
// Define {RegisterName} methods for the register types.
|
||||
DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
|
||||
DEFINE_REGISTER_NAMES(XMMRegister, DOUBLE_REGISTERS)
|
||||
|
30
src/codegen/ia32/reglist-ia32.h
Normal file
30
src/codegen/ia32/reglist-ia32.h
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_CODEGEN_IA32_REGLIST_IA32_H_
|
||||
#define V8_CODEGEN_IA32_REGLIST_IA32_H_
|
||||
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/reglist-base.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
using RegList = RegListBase<Register>;
|
||||
using DoubleRegList = RegListBase<DoubleRegister>;
|
||||
ASSERT_TRIVIALLY_COPYABLE(RegList);
|
||||
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
|
||||
|
||||
// Caller-saved registers
|
||||
constexpr RegList kJSCallerSaved = {
|
||||
eax, ecx, edx,
|
||||
ebx, // used as caller-saved register in JavaScript code
|
||||
edi}; // callee function
|
||||
|
||||
constexpr int kNumJSCallerSaved = 5;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_CODEGEN_IA32_REGLIST_IA32_H_
|
@ -217,24 +217,24 @@ constexpr Register WriteBarrierDescriptor::ValueRegister() {
|
||||
constexpr RegList WriteBarrierDescriptor::ComputeSavedRegisters(
|
||||
Register object, Register slot_address) {
|
||||
DCHECK(!AreAliased(object, slot_address));
|
||||
RegList saved_registers = 0;
|
||||
RegList saved_registers;
|
||||
#if V8_TARGET_ARCH_X64
|
||||
// Only push clobbered registers.
|
||||
if (object != ObjectRegister()) saved_registers |= ObjectRegister().bit();
|
||||
if (object != ObjectRegister()) saved_registers.set(ObjectRegister());
|
||||
if (slot_address != no_reg && slot_address != SlotAddressRegister()) {
|
||||
saved_registers |= SlotAddressRegister().bit();
|
||||
saved_registers.set(SlotAddressRegister());
|
||||
}
|
||||
#elif V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_LOONG64 || \
|
||||
V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_MIPS
|
||||
if (object != ObjectRegister()) saved_registers |= ObjectRegister().bit();
|
||||
if (object != ObjectRegister()) saved_registers.set(ObjectRegister());
|
||||
// The slot address is always clobbered.
|
||||
saved_registers |= SlotAddressRegister().bit();
|
||||
saved_registers.set(SlotAddressRegister());
|
||||
#else
|
||||
// TODO(cbruni): Enable callee-saved registers for other platforms.
|
||||
// This is a temporary workaround to prepare code for callee-saved registers.
|
||||
constexpr auto allocated_registers = registers();
|
||||
for (size_t i = 0; i < allocated_registers.size(); ++i) {
|
||||
saved_registers |= allocated_registers[i].bit();
|
||||
saved_registers.set(allocated_registers[i]);
|
||||
}
|
||||
#endif
|
||||
return saved_registers;
|
||||
|
@ -19,16 +19,16 @@ void CallInterfaceDescriptorData::InitializeRegisters(
|
||||
#ifdef DEBUG
|
||||
{
|
||||
// Make sure that the registers are all valid, and don't alias each other.
|
||||
RegList reglist = 0;
|
||||
RegList reglist;
|
||||
for (int i = 0; i < register_parameter_count; ++i) {
|
||||
Register reg = registers[i];
|
||||
DCHECK(reg.is_valid());
|
||||
DCHECK_EQ(reglist & reg.bit(), 0);
|
||||
DCHECK(!reglist.has(reg));
|
||||
DCHECK_NE(reg, kRootRegister);
|
||||
#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
|
||||
DCHECK_NE(reg, kPtrComprCageBaseRegister);
|
||||
#endif
|
||||
reglist = CombineRegLists(reglist, reg.bit());
|
||||
reglist.set(reg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -145,8 +145,8 @@ void WriteBarrierDescriptor::Verify(CallInterfaceDescriptorData* data) {
|
||||
DCHECK_EQ(ObjectRegister(), kJSFunctionRegister);
|
||||
// We need a certain set of registers by default:
|
||||
RegList allocatable_regs = data->allocatable_registers();
|
||||
DCHECK(allocatable_regs | kContextRegister.bit());
|
||||
DCHECK(allocatable_regs | kReturnRegister0.bit());
|
||||
DCHECK(allocatable_regs.has(kContextRegister));
|
||||
DCHECK(allocatable_regs.has(kReturnRegister0));
|
||||
VerifyArgumentRegisterCount(data, 4);
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
@ -213,11 +213,11 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
|
||||
StackArgumentOrder stack_order() const { return stack_order_; }
|
||||
|
||||
void RestrictAllocatableRegisters(const Register* registers, size_t num) {
|
||||
DCHECK_EQ(allocatable_registers_, 0);
|
||||
DCHECK(allocatable_registers_.is_empty());
|
||||
for (size_t i = 0; i < num; ++i) {
|
||||
allocatable_registers_ |= registers[i].bit();
|
||||
allocatable_registers_.set(registers[i]);
|
||||
}
|
||||
DCHECK_GT(NumRegs(allocatable_registers_), 0);
|
||||
DCHECK(!allocatable_registers_.is_empty());
|
||||
}
|
||||
|
||||
RegList allocatable_registers() const { return allocatable_registers_; }
|
||||
@ -249,7 +249,7 @@ class V8_EXPORT_PRIVATE CallInterfaceDescriptorData {
|
||||
|
||||
// Specifying the set of registers that could be used by the register
|
||||
// allocator. Currently, it's only used by RecordWrite code stub.
|
||||
RegList allocatable_registers_ = 0;
|
||||
RegList allocatable_registers_;
|
||||
|
||||
// |registers_params_| defines registers that are used for parameter passing.
|
||||
// |machine_types_| defines machine types for resulting values and incomping
|
||||
|
@ -167,7 +167,7 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
|
||||
Assembler::Assembler(const AssemblerOptions& options,
|
||||
std::unique_ptr<AssemblerBuffer> buffer)
|
||||
: AssemblerBase(options, std::move(buffer)),
|
||||
scratch_register_list_(t7.bit() | t6.bit()) {
|
||||
scratch_register_list_({t7, t6}) {
|
||||
reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
|
||||
|
||||
last_trampoline_pool_end_ = 0;
|
||||
|
@ -1093,11 +1093,11 @@ class V8_EXPORT_PRIVATE V8_NODISCARD UseScratchRegisterScope {
|
||||
void Include(const RegList& list) { *available_ |= list; }
|
||||
void Exclude(const RegList& list) { *available_ &= ~list; }
|
||||
void Include(const Register& reg1, const Register& reg2 = no_reg) {
|
||||
RegList list(reg1.bit() | reg2.bit());
|
||||
RegList list({reg1, reg2});
|
||||
Include(list);
|
||||
}
|
||||
void Exclude(const Register& reg1, const Register& reg2 = no_reg) {
|
||||
RegList list(reg1.bit() | reg2.bit());
|
||||
RegList list({reg1, reg2});
|
||||
Exclude(list);
|
||||
}
|
||||
|
||||
|
@ -24,14 +24,14 @@ template <typename DerivedDescriptor>
|
||||
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
|
||||
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
|
||||
RegList allocatable_regs = data->allocatable_registers();
|
||||
if (argc >= 1) DCHECK(allocatable_regs | a0.bit());
|
||||
if (argc >= 2) DCHECK(allocatable_regs | a1.bit());
|
||||
if (argc >= 3) DCHECK(allocatable_regs | a2.bit());
|
||||
if (argc >= 4) DCHECK(allocatable_regs | a3.bit());
|
||||
if (argc >= 5) DCHECK(allocatable_regs | a4.bit());
|
||||
if (argc >= 6) DCHECK(allocatable_regs | a5.bit());
|
||||
if (argc >= 7) DCHECK(allocatable_regs | a6.bit());
|
||||
if (argc >= 8) DCHECK(allocatable_regs | a7.bit());
|
||||
if (argc >= 1) DCHECK(allocatable_regs.has(a0));
|
||||
if (argc >= 2) DCHECK(allocatable_regs.has(a1));
|
||||
if (argc >= 3) DCHECK(allocatable_regs.has(a2));
|
||||
if (argc >= 4) DCHECK(allocatable_regs.has(a3));
|
||||
if (argc >= 5) DCHECK(allocatable_regs.has(a4));
|
||||
if (argc >= 6) DCHECK(allocatable_regs.has(a5));
|
||||
if (argc >= 7) DCHECK(allocatable_regs.has(a6));
|
||||
if (argc >= 8) DCHECK(allocatable_regs.has(a7));
|
||||
// Additional arguments are passed on the stack.
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
@ -51,22 +51,13 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
|
||||
Register exclusion2,
|
||||
Register exclusion3) const {
|
||||
int bytes = 0;
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
bytes += NumRegs(list) * kPointerSize;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
bytes += list.Count() * kPointerSize;
|
||||
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
|
||||
bytes += kCallerSavedFPU.Count() * kDoubleSize;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
@ -76,24 +67,15 @@ int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
|
||||
Register exclusion2, Register exclusion3) {
|
||||
ASM_CODE_COMMENT(this);
|
||||
int bytes = 0;
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
MultiPush(list);
|
||||
bytes += NumRegs(list) * kPointerSize;
|
||||
bytes += list.Count() * kPointerSize;
|
||||
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
MultiPushFPU(kCallerSavedFPU);
|
||||
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
|
||||
bytes += kCallerSavedFPU.Count() * kDoubleSize;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
@ -105,23 +87,13 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
|
||||
int bytes = 0;
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
MultiPopFPU(kCallerSavedFPU);
|
||||
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
|
||||
bytes += kCallerSavedFPU.Count() * kDoubleSize;
|
||||
}
|
||||
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
MultiPop(list);
|
||||
bytes += NumRegs(list) * kPointerSize;
|
||||
bytes += list.Count() * kPointerSize;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
@ -193,25 +165,13 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
RegList regs = 0;
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
regs |= Register::from_code(i).bit();
|
||||
}
|
||||
}
|
||||
MultiPush(regs);
|
||||
if (registers.is_empty()) return;
|
||||
MultiPush(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
RegList regs = 0;
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
regs |= Register::from_code(i).bit();
|
||||
}
|
||||
}
|
||||
MultiPop(regs);
|
||||
if (registers.is_empty()) return;
|
||||
MultiPop(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object, Operand offset,
|
||||
@ -4101,19 +4061,13 @@ void TurboAssembler::CheckPageFlag(const Register& object, int mask,
|
||||
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
|
||||
Register reg4, Register reg5,
|
||||
Register reg6) {
|
||||
RegList regs = 0;
|
||||
if (reg1.is_valid()) regs |= reg1.bit();
|
||||
if (reg2.is_valid()) regs |= reg2.bit();
|
||||
if (reg3.is_valid()) regs |= reg3.bit();
|
||||
if (reg4.is_valid()) regs |= reg4.bit();
|
||||
if (reg5.is_valid()) regs |= reg5.bit();
|
||||
if (reg6.is_valid()) regs |= reg6.bit();
|
||||
RegList regs = {reg1, reg2, reg3, reg4, reg5, reg6};
|
||||
|
||||
const RegisterConfiguration* config = RegisterConfiguration::Default();
|
||||
for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
|
||||
int code = config->GetAllocatableGeneralCode(i);
|
||||
Register candidate = Register::from_code(code);
|
||||
if (regs & candidate.bit()) continue;
|
||||
if (regs.has(candidate)) continue;
|
||||
return candidate;
|
||||
}
|
||||
UNREACHABLE();
|
||||
|
@ -7,8 +7,6 @@
|
||||
|
||||
#include "src/codegen/loong64/constants-loong64.h"
|
||||
#include "src/codegen/register-base.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/codegen/reglist.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -49,74 +47,6 @@ namespace internal {
|
||||
// encoding.
|
||||
const int kNumRegs = 32;
|
||||
|
||||
const RegList kJSCallerSaved = 1 << 4 | // a0
|
||||
1 << 5 | // a1
|
||||
1 << 6 | // a2
|
||||
1 << 7 | // a3
|
||||
1 << 8 | // a4
|
||||
1 << 9 | // a5
|
||||
1 << 10 | // a6
|
||||
1 << 11 | // a7
|
||||
1 << 12 | // t0
|
||||
1 << 13 | // t1
|
||||
1 << 14 | // t2
|
||||
1 << 15 | // t3
|
||||
1 << 16 | // t4
|
||||
1 << 17 | // t5
|
||||
1 << 20; // t8
|
||||
|
||||
const int kNumJSCallerSaved = 15;
|
||||
|
||||
// Callee-saved registers preserved when switching from C to JavaScript.
|
||||
const RegList kCalleeSaved = 1 << 22 | // fp
|
||||
1 << 23 | // s0
|
||||
1 << 24 | // s1
|
||||
1 << 25 | // s2
|
||||
1 << 26 | // s3
|
||||
1 << 27 | // s4
|
||||
1 << 28 | // s5
|
||||
1 << 29 | // s6 (roots in Javascript code)
|
||||
1 << 30 | // s7 (cp in Javascript code)
|
||||
1 << 31; // s8
|
||||
|
||||
const int kNumCalleeSaved = 10;
|
||||
|
||||
const RegList kCalleeSavedFPU = 1 << 24 | // f24
|
||||
1 << 25 | // f25
|
||||
1 << 26 | // f26
|
||||
1 << 27 | // f27
|
||||
1 << 28 | // f28
|
||||
1 << 29 | // f29
|
||||
1 << 30 | // f30
|
||||
1 << 31; // f31
|
||||
|
||||
const int kNumCalleeSavedFPU = 8;
|
||||
|
||||
const RegList kCallerSavedFPU = 1 << 0 | // f0
|
||||
1 << 1 | // f1
|
||||
1 << 2 | // f2
|
||||
1 << 3 | // f3
|
||||
1 << 4 | // f4
|
||||
1 << 5 | // f5
|
||||
1 << 6 | // f6
|
||||
1 << 7 | // f7
|
||||
1 << 8 | // f8
|
||||
1 << 9 | // f9
|
||||
1 << 10 | // f10
|
||||
1 << 11 | // f11
|
||||
1 << 12 | // f12
|
||||
1 << 13 | // f13
|
||||
1 << 14 | // f14
|
||||
1 << 15 | // f15
|
||||
1 << 16 | // f16
|
||||
1 << 17 | // f17
|
||||
1 << 18 | // f18
|
||||
1 << 19 | // f19
|
||||
1 << 20 | // f20
|
||||
1 << 21 | // f21
|
||||
1 << 22 | // f22
|
||||
1 << 23; // f23
|
||||
|
||||
// CPU Registers.
|
||||
//
|
||||
// 1) We would prefer to use an enum, but enum values are assignment-
|
||||
|
50
src/codegen/loong64/reglist-loong64.h
Normal file
50
src/codegen/loong64/reglist-loong64.h
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can b in the
|
||||
// LICENSE file.
|
||||
|
||||
#ifndef V8_CODEGEN_LOONG64_REGLIST_LOONG64_H_
|
||||
#define V8_CODEGEN_LOONG64_REGLIST_LOONG64_H_
|
||||
|
||||
#include "src/codegen/loong64/constants-loong64.h"
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/reglist-base.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
using RegList = RegListBase<Register>;
|
||||
using DoubleRegList = RegListBase<DoubleRegister>;
|
||||
ASSERT_TRIVIALLY_COPYABLE(RegList);
|
||||
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
|
||||
|
||||
const RegList kJSCallerSaved = {a0, a1, a2, a3, a4, a5, a6, a7,
|
||||
t0, t1, t2, t3, t4, t5, t8};
|
||||
|
||||
const int kNumJSCallerSaved = 15;
|
||||
|
||||
// Callee-saved registers preserved when switching from C to JavaScript.
|
||||
const RegList kCalleeSaved = {fp, // fp
|
||||
s0, // s0
|
||||
s1, // s1
|
||||
s2, // s2
|
||||
s3, // s3
|
||||
s4, // s4
|
||||
s5, // s5
|
||||
s6, // s6 (roots in Javascript code)
|
||||
s7, // s7 (cp in Javascript code)
|
||||
s8}; // s8
|
||||
|
||||
const int kNumCalleeSaved = 10;
|
||||
|
||||
const RegList kCalleeSavedFPU = {f24, f25, f26, f27, f28, f29, f30, f31};
|
||||
|
||||
const int kNumCalleeSavedFPU = 8;
|
||||
|
||||
const RegList kCallerSavedFPU = {f0, f1, f2, f3, f4, f5, f6, f7,
|
||||
f8, f9, f10, f11, f12, f13, f14, f15,
|
||||
f16, f17, f18, f19, f20, f21, f22, f23};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_CODEGEN_LOONG64_REGLIST_LOONG64_H_
|
@ -290,8 +290,7 @@ const Instr kLwSwOffsetMask = kImm16Mask;
|
||||
|
||||
Assembler::Assembler(const AssemblerOptions& options,
|
||||
std::unique_ptr<AssemblerBuffer> buffer)
|
||||
: AssemblerBase(options, std::move(buffer)),
|
||||
scratch_register_list_(at.bit()) {
|
||||
: AssemblerBase(options, std::move(buffer)), scratch_register_list_({at}) {
|
||||
reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
|
||||
|
||||
last_trampoline_pool_end_ = 0;
|
||||
|
@ -1905,11 +1905,11 @@ class V8_EXPORT_PRIVATE V8_NODISCARD UseScratchRegisterScope {
|
||||
void Include(const RegList& list) { *available_ |= list; }
|
||||
void Exclude(const RegList& list) { *available_ &= ~list; }
|
||||
void Include(const Register& reg1, const Register& reg2 = no_reg) {
|
||||
RegList list(reg1.bit() | reg2.bit());
|
||||
RegList list({reg1, reg2});
|
||||
Include(list);
|
||||
}
|
||||
void Exclude(const Register& reg1, const Register& reg2 = no_reg) {
|
||||
RegList list(reg1.bit() | reg2.bit());
|
||||
RegList list({reg1, reg2});
|
||||
Exclude(list);
|
||||
}
|
||||
|
||||
|
@ -24,10 +24,10 @@ template <typename DerivedDescriptor>
|
||||
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
|
||||
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
|
||||
RegList allocatable_regs = data->allocatable_registers();
|
||||
if (argc >= 1) DCHECK(allocatable_regs | a0.bit());
|
||||
if (argc >= 2) DCHECK(allocatable_regs | a1.bit());
|
||||
if (argc >= 3) DCHECK(allocatable_regs | a2.bit());
|
||||
if (argc >= 4) DCHECK(allocatable_regs | a3.bit());
|
||||
if (argc >= 1) DCHECK(allocatable_regs.has(a0));
|
||||
if (argc >= 2) DCHECK(allocatable_regs.has(a1));
|
||||
if (argc >= 3) DCHECK(allocatable_regs.has(a2));
|
||||
if (argc >= 4) DCHECK(allocatable_regs.has(a3));
|
||||
// Additional arguments are passed on the stack.
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
@ -51,22 +51,13 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
|
||||
Register exclusion2,
|
||||
Register exclusion3) const {
|
||||
int bytes = 0;
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
bytes += NumRegs(list) * kPointerSize;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
bytes += list.Count() * kPointerSize;
|
||||
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
|
||||
bytes += kCallerSavedFPU.Count() * kDoubleSize;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
@ -76,24 +67,15 @@ int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
|
||||
Register exclusion2, Register exclusion3) {
|
||||
ASM_CODE_COMMENT(this);
|
||||
int bytes = 0;
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
MultiPush(list);
|
||||
bytes += NumRegs(list) * kPointerSize;
|
||||
bytes += list.Count() * kPointerSize;
|
||||
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
MultiPushFPU(kCallerSavedFPU);
|
||||
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
|
||||
bytes += kCallerSavedFPU.Count() * kDoubleSize;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
@ -105,23 +87,13 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
|
||||
int bytes = 0;
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
MultiPopFPU(kCallerSavedFPU);
|
||||
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
|
||||
bytes += kCallerSavedFPU.Count() * kDoubleSize;
|
||||
}
|
||||
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
MultiPop(list);
|
||||
bytes += NumRegs(list) * kPointerSize;
|
||||
bytes += list.Count() * kPointerSize;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
@ -215,25 +187,13 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
RegList regs = 0;
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
regs |= Register::from_code(i).bit();
|
||||
}
|
||||
}
|
||||
MultiPush(regs);
|
||||
if (registers.is_empty()) return;
|
||||
MultiPush(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
RegList regs = 0;
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
regs |= Register::from_code(i).bit();
|
||||
}
|
||||
}
|
||||
MultiPop(regs);
|
||||
if (registers.is_empty()) return;
|
||||
MultiPop(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object,
|
||||
@ -5576,19 +5536,13 @@ void TurboAssembler::CheckPageFlag(Register object, Register scratch, int mask,
|
||||
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
|
||||
Register reg4, Register reg5,
|
||||
Register reg6) {
|
||||
RegList regs = 0;
|
||||
if (reg1.is_valid()) regs |= reg1.bit();
|
||||
if (reg2.is_valid()) regs |= reg2.bit();
|
||||
if (reg3.is_valid()) regs |= reg3.bit();
|
||||
if (reg4.is_valid()) regs |= reg4.bit();
|
||||
if (reg5.is_valid()) regs |= reg5.bit();
|
||||
if (reg6.is_valid()) regs |= reg6.bit();
|
||||
RegList regs = {reg1, reg2, reg3, reg4, reg5, reg6};
|
||||
|
||||
const RegisterConfiguration* config = RegisterConfiguration::Default();
|
||||
for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
|
||||
int code = config->GetAllocatableGeneralCode(i);
|
||||
Register candidate = Register::from_code(code);
|
||||
if (regs & candidate.bit()) continue;
|
||||
if (regs.has(candidate)) continue;
|
||||
return candidate;
|
||||
}
|
||||
UNREACHABLE();
|
||||
|
@ -7,8 +7,6 @@
|
||||
|
||||
#include "src/codegen/mips/constants-mips.h"
|
||||
#include "src/codegen/register-base.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/codegen/reglist.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -48,66 +46,10 @@ namespace internal {
|
||||
// encoding.
|
||||
const int kNumRegs = 32;
|
||||
|
||||
const RegList kJSCallerSaved = 1 << 2 | // v0
|
||||
1 << 3 | // v1
|
||||
1 << 4 | // a0
|
||||
1 << 5 | // a1
|
||||
1 << 6 | // a2
|
||||
1 << 7 | // a3
|
||||
1 << 8 | // t0
|
||||
1 << 9 | // t1
|
||||
1 << 10 | // t2
|
||||
1 << 11 | // t3
|
||||
1 << 12 | // t4
|
||||
1 << 13 | // t5
|
||||
1 << 14 | // t6
|
||||
1 << 15; // t7
|
||||
|
||||
const int kNumJSCallerSaved = 14;
|
||||
|
||||
// Callee-saved registers preserved when switching from C to JavaScript.
|
||||
const RegList kCalleeSaved = 1 << 16 | // s0
|
||||
1 << 17 | // s1
|
||||
1 << 18 | // s2
|
||||
1 << 19 | // s3
|
||||
1 << 20 | // s4
|
||||
1 << 21 | // s5
|
||||
1 << 22 | // s6 (roots in Javascript code)
|
||||
1 << 23 | // s7 (cp in Javascript code)
|
||||
1 << 30; // fp/s8
|
||||
|
||||
const int kNumCalleeSaved = 9;
|
||||
|
||||
const RegList kCalleeSavedFPU = 1 << 20 | // f20
|
||||
1 << 22 | // f22
|
||||
1 << 24 | // f24
|
||||
1 << 26 | // f26
|
||||
1 << 28 | // f28
|
||||
1 << 30; // f30
|
||||
|
||||
const int kNumCalleeSavedFPU = 6;
|
||||
|
||||
const RegList kCallerSavedFPU = 1 << 0 | // f0
|
||||
1 << 2 | // f2
|
||||
1 << 4 | // f4
|
||||
1 << 6 | // f6
|
||||
1 << 8 | // f8
|
||||
1 << 10 | // f10
|
||||
1 << 12 | // f12
|
||||
1 << 14 | // f14
|
||||
1 << 16 | // f16
|
||||
1 << 18; // f18
|
||||
|
||||
// Number of registers for which space is reserved in safepoints. Must be a
|
||||
// multiple of 8.
|
||||
const int kNumSafepointRegisters = 24;
|
||||
|
||||
// Define the list of registers actually saved at safepoints.
|
||||
// Note that the number of saved registers may be smaller than the reserved
|
||||
// space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters.
|
||||
const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved;
|
||||
const int kNumSafepointSavedRegisters = kNumJSCallerSaved + kNumCalleeSaved;
|
||||
|
||||
const int kUndefIndex = -1;
|
||||
// Map with indexes on stack that corresponds to codes of saved registers.
|
||||
const int kSafepointRegisterStackIndexMap[kNumRegs] = {kUndefIndex, // zero_reg
|
||||
|
57
src/codegen/mips/reglist-mips.h
Normal file
57
src/codegen/mips/reglist-mips.h
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_CODEGEN_MIPS_REGLIST_MIPS_H_
|
||||
#define V8_CODEGEN_MIPS_REGLIST_MIPS_H_
|
||||
|
||||
#include "src/codegen/mips/constants-mips.h"
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/reglist-base.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
using RegList = RegListBase<Register>;
|
||||
using DoubleRegList = RegListBase<DoubleRegister>;
|
||||
ASSERT_TRIVIALLY_COPYABLE(RegList);
|
||||
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
|
||||
|
||||
const RegList kJSCallerSaved = {v0, v1, a0, a1, a2, a3, t0,
|
||||
t1, t2, t3, t4, t5, t6, t7}
|
||||
|
||||
const int kNumJSCallerSaved = 14;
|
||||
|
||||
// Callee-saved registers preserved when switching from C to JavaScript.
|
||||
const RegList kCalleeSaved = {s0, // s0
|
||||
s1, // s1
|
||||
s2, // s2
|
||||
s3, // s3
|
||||
s4, // s4
|
||||
s5, // s5
|
||||
s6, // s6 (roots in Javascript code)
|
||||
s7, // s7 (cp in Javascript code)
|
||||
fp}; // fp/s8
|
||||
|
||||
const int kNumCalleeSaved = 9;
|
||||
|
||||
const RegList kCalleeSavedFPU = {f20, f22, f24, f26, f28, f30};
|
||||
|
||||
const int kNumCalleeSavedFPU = 6;
|
||||
|
||||
const RegList kCallerSavedFPU = {f0, f2, f4, f6, f8, f10, f12, f14, f16, f18};
|
||||
|
||||
// Number of registers for which space is reserved in safepoints. Must be a
|
||||
// multiple of 8.
|
||||
const int kNumSafepointRegisters = 24;
|
||||
|
||||
// Define the list of registers actually saved at safepoints.
|
||||
// Note that the number of saved registers may be smaller than the reserved
|
||||
// space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters.
|
||||
const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved;
|
||||
const int kNumSafepointSavedRegisters = kNumJSCallerSaved + kNumCalleeSaved;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_CODEGEN_MIPS_REGLIST_MIPS_H_
|
@ -265,7 +265,7 @@ const Instr kLwSwOffsetMask = kImm16Mask;
|
||||
Assembler::Assembler(const AssemblerOptions& options,
|
||||
std::unique_ptr<AssemblerBuffer> buffer)
|
||||
: AssemblerBase(options, std::move(buffer)),
|
||||
scratch_register_list_(at.bit() | s0.bit()) {
|
||||
scratch_register_list_({at, s0}) {
|
||||
if (CpuFeatures::IsSupported(MIPS_SIMD)) {
|
||||
EnableCpuFeature(MIPS_SIMD);
|
||||
}
|
||||
|
@ -1935,11 +1935,11 @@ class V8_EXPORT_PRIVATE V8_NODISCARD UseScratchRegisterScope {
|
||||
void Include(const RegList& list) { *available_ |= list; }
|
||||
void Exclude(const RegList& list) { *available_ &= ~list; }
|
||||
void Include(const Register& reg1, const Register& reg2 = no_reg) {
|
||||
RegList list(reg1.bit() | reg2.bit());
|
||||
RegList list({reg1, reg2});
|
||||
Include(list);
|
||||
}
|
||||
void Exclude(const Register& reg1, const Register& reg2 = no_reg) {
|
||||
RegList list(reg1.bit() | reg2.bit());
|
||||
RegList list({reg1, reg2});
|
||||
Exclude(list);
|
||||
}
|
||||
|
||||
|
@ -24,14 +24,14 @@ template <typename DerivedDescriptor>
|
||||
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
|
||||
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
|
||||
RegList allocatable_regs = data->allocatable_registers();
|
||||
if (argc >= 1) DCHECK(allocatable_regs | a0.bit());
|
||||
if (argc >= 2) DCHECK(allocatable_regs | a1.bit());
|
||||
if (argc >= 3) DCHECK(allocatable_regs | a2.bit());
|
||||
if (argc >= 4) DCHECK(allocatable_regs | a3.bit());
|
||||
if (argc >= 5) DCHECK(allocatable_regs | a4.bit());
|
||||
if (argc >= 6) DCHECK(allocatable_regs | a5.bit());
|
||||
if (argc >= 7) DCHECK(allocatable_regs | a6.bit());
|
||||
if (argc >= 8) DCHECK(allocatable_regs | a7.bit());
|
||||
if (argc >= 1) DCHECK(allocatable_regs.has(a0));
|
||||
if (argc >= 2) DCHECK(allocatable_regs.has(a1));
|
||||
if (argc >= 3) DCHECK(allocatable_regs.has(a2));
|
||||
if (argc >= 4) DCHECK(allocatable_regs.has(a3));
|
||||
if (argc >= 5) DCHECK(allocatable_regs.has(a4));
|
||||
if (argc >= 6) DCHECK(allocatable_regs.has(a5));
|
||||
if (argc >= 7) DCHECK(allocatable_regs.has(a6));
|
||||
if (argc >= 8) DCHECK(allocatable_regs.has(a7));
|
||||
// Additional arguments are passed on the stack.
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
@ -51,22 +51,12 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
|
||||
Register exclusion2,
|
||||
Register exclusion3) const {
|
||||
int bytes = 0;
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
bytes += NumRegs(list) * kPointerSize;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
bytes += list.Count() * kPointerSize;
|
||||
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
|
||||
bytes += kCallerSavedFPU.Count() * kDoubleSize;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
@ -76,24 +66,14 @@ int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
|
||||
Register exclusion2, Register exclusion3) {
|
||||
ASM_CODE_COMMENT(this);
|
||||
int bytes = 0;
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
MultiPush(list);
|
||||
bytes += NumRegs(list) * kPointerSize;
|
||||
bytes += list.Count() * kPointerSize;
|
||||
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
MultiPushFPU(kCallerSavedFPU);
|
||||
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
|
||||
bytes += kCallerSavedFPU.Count() * kDoubleSize;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
@ -105,23 +85,13 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
|
||||
int bytes = 0;
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
MultiPopFPU(kCallerSavedFPU);
|
||||
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
|
||||
bytes += kCallerSavedFPU.Count() * kDoubleSize;
|
||||
}
|
||||
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
MultiPop(list);
|
||||
bytes += NumRegs(list) * kPointerSize;
|
||||
bytes += list.Count() * kPointerSize;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
@ -213,25 +183,13 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
RegList regs = 0;
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
regs |= Register::from_code(i).bit();
|
||||
}
|
||||
}
|
||||
MultiPush(regs);
|
||||
if (registers.is_empty()) return;
|
||||
MultiPush(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
RegList regs = 0;
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
regs |= Register::from_code(i).bit();
|
||||
}
|
||||
}
|
||||
MultiPop(regs);
|
||||
if (registers.is_empty()) return;
|
||||
MultiPop(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object,
|
||||
@ -6121,19 +6079,13 @@ void TurboAssembler::CheckPageFlag(Register object, Register scratch, int mask,
|
||||
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
|
||||
Register reg4, Register reg5,
|
||||
Register reg6) {
|
||||
RegList regs = 0;
|
||||
if (reg1.is_valid()) regs |= reg1.bit();
|
||||
if (reg2.is_valid()) regs |= reg2.bit();
|
||||
if (reg3.is_valid()) regs |= reg3.bit();
|
||||
if (reg4.is_valid()) regs |= reg4.bit();
|
||||
if (reg5.is_valid()) regs |= reg5.bit();
|
||||
if (reg6.is_valid()) regs |= reg6.bit();
|
||||
RegList regs = {reg1, reg2, reg3, reg4, reg5, reg6};
|
||||
|
||||
const RegisterConfiguration* config = RegisterConfiguration::Default();
|
||||
for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
|
||||
int code = config->GetAllocatableGeneralCode(i);
|
||||
Register candidate = Register::from_code(code);
|
||||
if (regs & candidate.bit()) continue;
|
||||
if (regs.has(candidate)) continue;
|
||||
return candidate;
|
||||
}
|
||||
UNREACHABLE();
|
||||
|
@ -7,8 +7,6 @@
|
||||
|
||||
#include "src/codegen/mips64/constants-mips64.h"
|
||||
#include "src/codegen/register-base.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/codegen/reglist.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -47,56 +45,6 @@ namespace internal {
|
||||
// encoding.
|
||||
const int kNumRegs = 32;
|
||||
|
||||
const RegList kJSCallerSaved = 1 << 2 | // v0
|
||||
1 << 3 | // v1
|
||||
1 << 4 | // a0
|
||||
1 << 5 | // a1
|
||||
1 << 6 | // a2
|
||||
1 << 7 | // a3
|
||||
1 << 8 | // a4
|
||||
1 << 9 | // a5
|
||||
1 << 10 | // a6
|
||||
1 << 11 | // a7
|
||||
1 << 12 | // t0
|
||||
1 << 13 | // t1
|
||||
1 << 14 | // t2
|
||||
1 << 15; // t3
|
||||
|
||||
const int kNumJSCallerSaved = 14;
|
||||
|
||||
// Callee-saved registers preserved when switching from C to JavaScript.
|
||||
const RegList kCalleeSaved = 1 << 16 | // s0
|
||||
1 << 17 | // s1
|
||||
1 << 18 | // s2
|
||||
1 << 19 | // s3
|
||||
1 << 20 | // s4
|
||||
1 << 21 | // s5
|
||||
1 << 22 | // s6 (roots in Javascript code)
|
||||
1 << 23 | // s7 (cp in Javascript code)
|
||||
1 << 30; // fp/s8
|
||||
|
||||
const int kNumCalleeSaved = 9;
|
||||
|
||||
const RegList kCalleeSavedFPU = 1 << 20 | // f20
|
||||
1 << 22 | // f22
|
||||
1 << 24 | // f24
|
||||
1 << 26 | // f26
|
||||
1 << 28 | // f28
|
||||
1 << 30; // f30
|
||||
|
||||
const int kNumCalleeSavedFPU = 6;
|
||||
|
||||
const RegList kCallerSavedFPU = 1 << 0 | // f0
|
||||
1 << 2 | // f2
|
||||
1 << 4 | // f4
|
||||
1 << 6 | // f6
|
||||
1 << 8 | // f8
|
||||
1 << 10 | // f10
|
||||
1 << 12 | // f12
|
||||
1 << 14 | // f14
|
||||
1 << 16 | // f16
|
||||
1 << 18; // f18
|
||||
|
||||
// Number of registers for which space is reserved in safepoints. Must be a
|
||||
// multiple of 8.
|
||||
const int kNumSafepointRegisters = 24;
|
||||
|
57
src/codegen/mips64/reglist-mips64.h
Normal file
57
src/codegen/mips64/reglist-mips64.h
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_CODEGEN_MIPS64_REGLIST_MIPS64_H_
|
||||
#define V8_CODEGEN_MIPS64_REGLIST_MIPS64_H_
|
||||
|
||||
#include "src/codegen/mips64/constants-mips64.h"
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/reglist-base.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
using RegList = RegListBase<Register>;
|
||||
using DoubleRegList = RegListBase<DoubleRegister>;
|
||||
ASSERT_TRIVIALLY_COPYABLE(RegList);
|
||||
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
|
||||
|
||||
const RegList kJSCallerSaved = {v0, v1, a0, a1, a2, a3, a4,
|
||||
a5, a6, a7, t0, t1, t2, t3};
|
||||
|
||||
const int kNumJSCallerSaved = 14;
|
||||
|
||||
// Callee-saved registers preserved when switching from C to JavaScript.
|
||||
const RegList kCalleeSaved = {s0, // s0
|
||||
s1, // s1
|
||||
s2, // s2
|
||||
s3, // s3
|
||||
s4, // s4
|
||||
s5, // s5
|
||||
s6, // s6 (roots in Javascript code)
|
||||
s7, // s7 (cp in Javascript code)
|
||||
fp}; // fp/s8
|
||||
|
||||
const int kNumCalleeSaved = 9;
|
||||
|
||||
const RegList kCalleeSavedFPU = {f20, f22, f24, f26, f28, f30};
|
||||
|
||||
const int kNumCalleeSavedFPU = 6;
|
||||
|
||||
const RegList kCallerSavedFPU = {f0, f2, f4, f6, f8, f10, f12, f14, f16, f18};
|
||||
|
||||
// Number of registers for which space is reserved in safepoints. Must be a
|
||||
// multiple of 8.
|
||||
const int kNumSafepointRegisters = 24;
|
||||
|
||||
// Define the list of registers actually saved at safepoints.
|
||||
// Note that the number of saved registers may be smaller than the reserved
|
||||
// space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters.
|
||||
const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved;
|
||||
const int kNumSafepointSavedRegisters = kNumJSCallerSaved + kNumCalleeSaved;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_CODEGEN_MIPS64_REGLIST_MIPS64_H_
|
@ -226,7 +226,7 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
|
||||
Assembler::Assembler(const AssemblerOptions& options,
|
||||
std::unique_ptr<AssemblerBuffer> buffer)
|
||||
: AssemblerBase(options, std::move(buffer)),
|
||||
scratch_register_list_(ip.bit()),
|
||||
scratch_register_list_({ip}),
|
||||
constant_pool_builder_(kLoadPtrMaxReachBits, kLoadDoubleMaxReachBits) {
|
||||
reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
|
||||
|
||||
@ -2109,11 +2109,7 @@ UseScratchRegisterScope::~UseScratchRegisterScope() {
|
||||
Register UseScratchRegisterScope::Acquire() {
|
||||
RegList* available = assembler_->GetScratchRegisterList();
|
||||
DCHECK_NOT_NULL(available);
|
||||
DCHECK_NE(*available, 0);
|
||||
int index = static_cast<int>(base::bits::CountTrailingZeros32(*available));
|
||||
Register reg = Register::from_code(index);
|
||||
*available &= ~reg.bit();
|
||||
return reg;
|
||||
return available->PopFront();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -24,14 +24,14 @@ template <typename DerivedDescriptor>
|
||||
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
|
||||
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
|
||||
RegList allocatable_regs = data->allocatable_registers();
|
||||
if (argc >= 1) DCHECK(allocatable_regs | r3.bit());
|
||||
if (argc >= 2) DCHECK(allocatable_regs | r4.bit());
|
||||
if (argc >= 3) DCHECK(allocatable_regs | r5.bit());
|
||||
if (argc >= 4) DCHECK(allocatable_regs | r6.bit());
|
||||
if (argc >= 5) DCHECK(allocatable_regs | r7.bit());
|
||||
if (argc >= 6) DCHECK(allocatable_regs | r8.bit());
|
||||
if (argc >= 7) DCHECK(allocatable_regs | r9.bit());
|
||||
if (argc >= 8) DCHECK(allocatable_regs | r10.bit());
|
||||
if (argc >= 1) DCHECK(allocatable_regs.has(r3));
|
||||
if (argc >= 2) DCHECK(allocatable_regs.has(r4));
|
||||
if (argc >= 3) DCHECK(allocatable_regs.has(r5));
|
||||
if (argc >= 4) DCHECK(allocatable_regs.has(r6));
|
||||
if (argc >= 5) DCHECK(allocatable_regs.has(r7));
|
||||
if (argc >= 6) DCHECK(allocatable_regs.has(r8));
|
||||
if (argc >= 7) DCHECK(allocatable_regs.has(r9));
|
||||
if (argc >= 8) DCHECK(allocatable_regs.has(r10));
|
||||
// Additional arguments are passed on the stack.
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
@ -58,19 +58,10 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
|
||||
Register exclusion2,
|
||||
Register exclusion3) const {
|
||||
int bytes = 0;
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
bytes += NumRegs(list) * kSystemPointerSize;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
bytes += list.Count() * kSystemPointerSize;
|
||||
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
bytes += kStackSavedSavedFPSizeInBytes;
|
||||
@ -82,20 +73,11 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
|
||||
int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
|
||||
Register exclusion2, Register exclusion3) {
|
||||
int bytes = 0;
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
MultiPush(list);
|
||||
bytes += NumRegs(list) * kSystemPointerSize;
|
||||
bytes += list.Count() * kSystemPointerSize;
|
||||
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
MultiPushF64AndV128(kCallerSavedDoubles, kCallerSavedDoubles);
|
||||
@ -113,20 +95,10 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
|
||||
bytes += kStackSavedSavedFPSizeInBytes;
|
||||
}
|
||||
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
MultiPop(list);
|
||||
bytes += NumRegs(list) * kSystemPointerSize;
|
||||
bytes += list.Count() * kSystemPointerSize;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
@ -507,14 +479,14 @@ void TurboAssembler::MultiPushF64AndV128(RegList dregs, RegList simd_regs,
|
||||
// We still need to allocate empty space on the stack even if we
|
||||
// are not pushing Simd registers (see kFixedFrameSizeFromFp).
|
||||
addi(sp, sp,
|
||||
Operand(-static_cast<int8_t>(NumRegs(simd_regs)) * kSimd128Size));
|
||||
Operand(-static_cast<int8_t>(simd_regs.Count()) * kSimd128Size));
|
||||
bind(&simd_pushed);
|
||||
} else {
|
||||
if (CpuFeatures::SupportsWasmSimd128()) {
|
||||
MultiPushV128(simd_regs);
|
||||
} else {
|
||||
addi(sp, sp,
|
||||
Operand(-static_cast<int8_t>(NumRegs(simd_regs)) * kSimd128Size));
|
||||
Operand(-static_cast<int8_t>(simd_regs.Count()) * kSimd128Size));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -535,14 +507,14 @@ void TurboAssembler::MultiPopF64AndV128(RegList dregs, RegList simd_regs,
|
||||
b(&simd_popped);
|
||||
bind(&pop_empty_simd);
|
||||
addi(sp, sp,
|
||||
Operand(static_cast<int8_t>(NumRegs(simd_regs)) * kSimd128Size));
|
||||
Operand(static_cast<int8_t>(simd_regs.Count()) * kSimd128Size));
|
||||
bind(&simd_popped);
|
||||
} else {
|
||||
if (CpuFeatures::SupportsWasmSimd128()) {
|
||||
MultiPopV128(simd_regs);
|
||||
} else {
|
||||
addi(sp, sp,
|
||||
Operand(static_cast<int8_t>(NumRegs(simd_regs)) * kSimd128Size));
|
||||
Operand(static_cast<int8_t>(simd_regs.Count()) * kSimd128Size));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -687,25 +659,13 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
RegList regs = 0;
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
regs |= Register::from_code(i).bit();
|
||||
}
|
||||
}
|
||||
MultiPush(regs);
|
||||
if (registers.is_empty()) return;
|
||||
MultiPush(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
RegList regs = 0;
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
regs |= Register::from_code(i).bit();
|
||||
}
|
||||
}
|
||||
MultiPop(regs);
|
||||
if (registers.is_empty()) return;
|
||||
MultiPop(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object,
|
||||
@ -3405,19 +3365,13 @@ void TurboAssembler::StoreF32LE(DoubleRegister dst, const MemOperand& mem,
|
||||
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
|
||||
Register reg4, Register reg5,
|
||||
Register reg6) {
|
||||
RegList regs = 0;
|
||||
if (reg1.is_valid()) regs |= reg1.bit();
|
||||
if (reg2.is_valid()) regs |= reg2.bit();
|
||||
if (reg3.is_valid()) regs |= reg3.bit();
|
||||
if (reg4.is_valid()) regs |= reg4.bit();
|
||||
if (reg5.is_valid()) regs |= reg5.bit();
|
||||
if (reg6.is_valid()) regs |= reg6.bit();
|
||||
RegList regs = {reg1, reg2, reg3, reg4, reg5, reg6};
|
||||
|
||||
const RegisterConfiguration* config = RegisterConfiguration::Default();
|
||||
for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
|
||||
int code = config->GetAllocatableGeneralCode(i);
|
||||
Register candidate = Register::from_code(code);
|
||||
if (regs & candidate.bit()) continue;
|
||||
if (regs.has(candidate)) continue;
|
||||
return candidate;
|
||||
}
|
||||
UNREACHABLE();
|
||||
|
@ -6,8 +6,6 @@
|
||||
#define V8_CODEGEN_PPC_REGISTER_PPC_H_
|
||||
|
||||
#include "src/codegen/register-base.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/codegen/reglist.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -62,84 +60,6 @@ namespace internal {
|
||||
V(cr8) V(cr9) V(cr10) V(cr11) V(cr12) V(cr15)
|
||||
// clang-format on
|
||||
|
||||
// Register list in load/store instructions
|
||||
// Note that the bit values must match those used in actual instruction encoding
|
||||
|
||||
// Caller-saved/arguments registers
|
||||
const RegList kJSCallerSaved = 1 << 3 | // r3 a1
|
||||
1 << 4 | // r4 a2
|
||||
1 << 5 | // r5 a3
|
||||
1 << 6 | // r6 a4
|
||||
1 << 7 | // r7 a5
|
||||
1 << 8 | // r8 a6
|
||||
1 << 9 | // r9 a7
|
||||
1 << 10 | // r10 a8
|
||||
1 << 11;
|
||||
|
||||
const int kNumJSCallerSaved = 9;
|
||||
|
||||
// Return the code of the n-th caller-saved register available to JavaScript
|
||||
// e.g. JSCallerSavedReg(0) returns r0.code() == 0
|
||||
int JSCallerSavedCode(int n);
|
||||
|
||||
// Callee-saved registers preserved when switching from C to JavaScript
|
||||
const RegList kCalleeSaved = 1 << 14 | // r14
|
||||
1 << 15 | // r15
|
||||
1 << 16 | // r16
|
||||
1 << 17 | // r17
|
||||
1 << 18 | // r18
|
||||
1 << 19 | // r19
|
||||
1 << 20 | // r20
|
||||
1 << 21 | // r21
|
||||
1 << 22 | // r22
|
||||
1 << 23 | // r23
|
||||
1 << 24 | // r24
|
||||
1 << 25 | // r25
|
||||
1 << 26 | // r26
|
||||
1 << 27 | // r27
|
||||
1 << 28 | // r28
|
||||
1 << 29 | // r29
|
||||
1 << 30 | // r20
|
||||
1 << 31; // r31
|
||||
|
||||
const int kNumCalleeSaved = 18;
|
||||
|
||||
const RegList kCallerSavedDoubles = 1 << 0 | // d0
|
||||
1 << 1 | // d1
|
||||
1 << 2 | // d2
|
||||
1 << 3 | // d3
|
||||
1 << 4 | // d4
|
||||
1 << 5 | // d5
|
||||
1 << 6 | // d6
|
||||
1 << 7 | // d7
|
||||
1 << 8 | // d8
|
||||
1 << 9 | // d9
|
||||
1 << 10 | // d10
|
||||
1 << 11 | // d11
|
||||
1 << 12 | // d12
|
||||
1 << 13; // d13
|
||||
|
||||
const int kNumCallerSavedDoubles = 14;
|
||||
|
||||
const RegList kCalleeSavedDoubles = 1 << 14 | // d14
|
||||
1 << 15 | // d15
|
||||
1 << 16 | // d16
|
||||
1 << 17 | // d17
|
||||
1 << 18 | // d18
|
||||
1 << 19 | // d19
|
||||
1 << 20 | // d20
|
||||
1 << 21 | // d21
|
||||
1 << 22 | // d22
|
||||
1 << 23 | // d23
|
||||
1 << 24 | // d24
|
||||
1 << 25 | // d25
|
||||
1 << 26 | // d26
|
||||
1 << 27 | // d27
|
||||
1 << 28 | // d28
|
||||
1 << 29 | // d29
|
||||
1 << 30 | // d30
|
||||
1 << 31; // d31
|
||||
|
||||
const int kNumCalleeSavedDoubles = 18;
|
||||
|
||||
// The following constants describe the stack frame linkage area as
|
||||
|
59
src/codegen/ppc/reglist-ppc.h
Normal file
59
src/codegen/ppc/reglist-ppc.h
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_CODEGEN_PPC_REGLIST_PPC_H_
|
||||
#define V8_CODEGEN_PPC_REGLIST_PPC_H_
|
||||
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/reglist-base.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
using RegList = RegListBase<Register>;
|
||||
using DoubleRegList = RegListBase<DoubleRegister>;
|
||||
ASSERT_TRIVIALLY_COPYABLE(RegList);
|
||||
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
|
||||
|
||||
// Register list in load/store instructions
|
||||
// Note that the bit values must match those used in actual instruction encoding
|
||||
|
||||
// Caller-saved/arguments registers
|
||||
const RegList kJSCallerSaved = {r3, // a1
|
||||
r4, // a2
|
||||
r5, // a3
|
||||
r6, // a4
|
||||
r7, // a5
|
||||
r8, // a6
|
||||
r9, // a7
|
||||
r10, // a8
|
||||
r11};
|
||||
|
||||
const int kNumJSCallerSaved = 9;
|
||||
|
||||
// Return the code of the n-th caller-saved register available to JavaScript
|
||||
// e.g. JSCallerSavedReg(0) returns r0.code() == 0
|
||||
int JSCallerSavedCode(int n);
|
||||
|
||||
// Callee-saved registers preserved when switching from C to JavaScript
|
||||
const RegList kCalleeSaved = {r14, r15, r16, r17, r18, r19, r20, r21, r22,
|
||||
r23, r24, r25, r26, r27, r28, r29, r30, r31};
|
||||
|
||||
const int kNumCalleeSaved = 18;
|
||||
|
||||
const RegList kCallerSavedDoubles = {d0, d1, d2, d3, d4, d5, d6,
|
||||
d7, d8, d9, d10, d11, d12, d13};
|
||||
|
||||
const int kNumCallerSavedDoubles = 14;
|
||||
|
||||
const RegList kCalleeSavedDoubles = {d14, d15, d16, d17, d18, d19,
|
||||
d20, d21, d22, d23, d24, d25,
|
||||
d26, d27, d28, d29, d30, d31};
|
||||
|
||||
const int kNumCalleeSavedDoubles = 18;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_CODEGEN_PPC_REGLIST_PPC_H_
|
34
src/codegen/register-arch.h
Normal file
34
src/codegen/register-arch.h
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_CODEGEN_REGISTER_ARCH_H_
|
||||
#define V8_CODEGEN_REGISTER_ARCH_H_
|
||||
|
||||
#include "src/codegen/register-base.h"
|
||||
|
||||
#if V8_TARGET_ARCH_IA32
|
||||
#include "src/codegen/ia32/register-ia32.h"
|
||||
#elif V8_TARGET_ARCH_X64
|
||||
#include "src/codegen/x64/register-x64.h"
|
||||
#elif V8_TARGET_ARCH_ARM64
|
||||
#include "src/codegen/arm64/register-arm64.h"
|
||||
#elif V8_TARGET_ARCH_ARM
|
||||
#include "src/codegen/arm/register-arm.h"
|
||||
#elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
|
||||
#include "src/codegen/ppc/register-ppc.h"
|
||||
#elif V8_TARGET_ARCH_MIPS
|
||||
#include "src/codegen/mips/register-mips.h"
|
||||
#elif V8_TARGET_ARCH_MIPS64
|
||||
#include "src/codegen/mips64/register-mips64.h"
|
||||
#elif V8_TARGET_ARCH_LOONG64
|
||||
#include "src/codegen/loong64/register-loong64.h"
|
||||
#elif V8_TARGET_ARCH_S390
|
||||
#include "src/codegen/s390/register-s390.h"
|
||||
#elif V8_TARGET_ARCH_RISCV64
|
||||
#include "src/codegen/riscv64/register-riscv64.h"
|
||||
#else
|
||||
#error Unknown architecture.
|
||||
#endif
|
||||
|
||||
#endif // V8_CODEGEN_REGISTER_ARCH_H_
|
@ -7,7 +7,6 @@
|
||||
|
||||
#include "src/base/bits.h"
|
||||
#include "src/base/bounds.h"
|
||||
#include "src/codegen/reglist.h"
|
||||
#include "src/common/globals.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -39,11 +38,6 @@ class RegisterBase {
|
||||
return SubType{code};
|
||||
}
|
||||
|
||||
template <typename... Register>
|
||||
static constexpr RegList ListOf(Register... regs) {
|
||||
return CombineRegLists(regs.bit()...);
|
||||
}
|
||||
|
||||
constexpr bool is_valid() const { return reg_code_ != kCode_no_reg; }
|
||||
|
||||
constexpr int8_t code() const {
|
||||
@ -51,34 +45,6 @@ class RegisterBase {
|
||||
return reg_code_;
|
||||
}
|
||||
|
||||
constexpr RegList bit() const {
|
||||
return is_valid() ? RegList{1} << code() : RegList{};
|
||||
}
|
||||
|
||||
static constexpr SubType FirstOf(RegList list) {
|
||||
DCHECK_NE(kEmptyRegList, list);
|
||||
return SubType::from_code(base::bits::CountTrailingZerosNonZero(list));
|
||||
}
|
||||
|
||||
static constexpr SubType TakeFirst(RegList* list) {
|
||||
RegList value = *list;
|
||||
SubType result = FirstOf(value);
|
||||
result.RemoveFrom(list);
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr bool IsIn(RegList list) const { return list & bit(); }
|
||||
|
||||
constexpr void InsertInto(RegList* list) const {
|
||||
DCHECK(!IsIn(*list));
|
||||
*list |= bit();
|
||||
}
|
||||
|
||||
constexpr void RemoveFrom(RegList* list) const {
|
||||
DCHECK(IsIn(*list));
|
||||
*list ^= bit();
|
||||
}
|
||||
|
||||
inline constexpr bool operator==(SubType other) const {
|
||||
return reg_code_ == other.reg_code_;
|
||||
}
|
||||
|
@ -190,13 +190,13 @@ const RegisterConfiguration* RegisterConfiguration::Default() {
|
||||
|
||||
const RegisterConfiguration* RegisterConfiguration::RestrictGeneralRegisters(
|
||||
RegList registers) {
|
||||
int num = NumRegs(registers);
|
||||
int num = registers.Count();
|
||||
std::unique_ptr<int[]> codes{new int[num]};
|
||||
std::unique_ptr<char const* []> names { new char const*[num] };
|
||||
int counter = 0;
|
||||
for (int i = 0; i < Default()->num_allocatable_general_registers(); ++i) {
|
||||
auto reg = Register::from_code(Default()->GetAllocatableGeneralCode(i));
|
||||
if (reg.bit() & registers) {
|
||||
if (registers.has(reg)) {
|
||||
DCHECK(counter < num);
|
||||
codes[counter] = reg.code();
|
||||
names[counter] = RegisterName(Register::from_code(i));
|
||||
|
@ -14,17 +14,6 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// An architecture independent representation of the sets of registers available
|
||||
// for instruction creation.
|
||||
enum class AliasingKind {
|
||||
// Registers alias a single register of every other size (e.g. Intel).
|
||||
kOverlap,
|
||||
// Registers alias two registers of the next smaller size (e.g. ARM).
|
||||
kCombine,
|
||||
// SIMD128 Registers are independent of every other size (e.g Riscv)
|
||||
kIndependent
|
||||
};
|
||||
|
||||
class V8_EXPORT_PRIVATE RegisterConfiguration {
|
||||
public:
|
||||
// Architecture independent maxes.
|
||||
|
@ -5,41 +5,12 @@
|
||||
#ifndef V8_CODEGEN_REGISTER_H_
|
||||
#define V8_CODEGEN_REGISTER_H_
|
||||
|
||||
#include "src/codegen/register-base.h"
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/reglist.h"
|
||||
|
||||
#if V8_TARGET_ARCH_IA32
|
||||
#include "src/codegen/ia32/register-ia32.h"
|
||||
#elif V8_TARGET_ARCH_X64
|
||||
#include "src/codegen/x64/register-x64.h"
|
||||
#elif V8_TARGET_ARCH_ARM64
|
||||
#include "src/codegen/arm64/register-arm64.h"
|
||||
#elif V8_TARGET_ARCH_ARM
|
||||
#include "src/codegen/arm/register-arm.h"
|
||||
#elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
|
||||
#include "src/codegen/ppc/register-ppc.h"
|
||||
#elif V8_TARGET_ARCH_MIPS
|
||||
#include "src/codegen/mips/register-mips.h"
|
||||
#elif V8_TARGET_ARCH_MIPS64
|
||||
#include "src/codegen/mips64/register-mips64.h"
|
||||
#elif V8_TARGET_ARCH_LOONG64
|
||||
#include "src/codegen/loong64/register-loong64.h"
|
||||
#elif V8_TARGET_ARCH_S390
|
||||
#include "src/codegen/s390/register-s390.h"
|
||||
#elif V8_TARGET_ARCH_RISCV64
|
||||
#include "src/codegen/riscv64/register-riscv64.h"
|
||||
#else
|
||||
#error Unknown architecture.
|
||||
#endif
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
#define LIST_REG(V) V,
|
||||
static constexpr RegList kAllocatableGeneralRegisters = Register::ListOf(
|
||||
ALLOCATABLE_GENERAL_REGISTERS(LIST_REG) Register::no_reg());
|
||||
#undef LIST_REG
|
||||
|
||||
constexpr int AddArgumentPaddingSlots(int argument_count) {
|
||||
return argument_count + ArgumentPaddingSlots(argument_count);
|
||||
}
|
||||
@ -62,36 +33,13 @@ template <typename RegType, typename... RegTypes,
|
||||
base::is_same<Register, RegType, RegTypes...>::value ||
|
||||
base::is_same<DoubleRegister, RegType, RegTypes...>::value>::type>
|
||||
inline constexpr bool AreAliased(RegType first_reg, RegTypes... regs) {
|
||||
int num_different_regs = NumRegs(RegType::ListOf(first_reg, regs...));
|
||||
int num_different_regs = RegListBase<RegType>{first_reg, regs...}.Count();
|
||||
int num_given_regs =
|
||||
base::fold(CountIfValidRegisterFunctor{}, 0, first_reg, regs...);
|
||||
return num_different_regs < num_given_regs;
|
||||
}
|
||||
#endif
|
||||
|
||||
class RegListIterator {
|
||||
public:
|
||||
class Iterator {
|
||||
public:
|
||||
explicit Iterator(RegList list) : list_(list) {}
|
||||
Register operator*() { return Register::FirstOf(list_); }
|
||||
void operator++() { Register::FirstOf(list_).RemoveFrom(&list_); }
|
||||
bool operator!=(const Iterator& other) const {
|
||||
return list_ != other.list_;
|
||||
}
|
||||
|
||||
private:
|
||||
RegList list_;
|
||||
};
|
||||
|
||||
explicit RegListIterator(RegList list) : list_(list) {}
|
||||
Iterator begin() const { return Iterator(list_); }
|
||||
Iterator end() const { return Iterator(kEmptyRegList); }
|
||||
|
||||
private:
|
||||
RegList list_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
232
src/codegen/reglist-base.h
Normal file
232
src/codegen/reglist-base.h
Normal file
@ -0,0 +1,232 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_CODEGEN_REGLIST_BASE_H_
|
||||
#define V8_CODEGEN_REGLIST_BASE_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
|
||||
#include "src/base/bits.h"
|
||||
#include "src/base/iterator.h"
|
||||
#include "src/base/template-utils.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class Register;
|
||||
|
||||
template <typename RegisterT>
|
||||
class RegListBase {
|
||||
using num_registers_sized_storage_t = typename std::conditional<
|
||||
RegisterT::kNumRegisters <= 16, uint16_t,
|
||||
typename std::conditional<RegisterT::kNumRegisters <= 32, uint32_t,
|
||||
uint64_t>::type>::type;
|
||||
STATIC_ASSERT(RegisterT::kNumRegisters <= 64);
|
||||
|
||||
public:
|
||||
class Iterator;
|
||||
class ReverseIterator;
|
||||
|
||||
#ifdef V8_TARGET_ARCH_ARM64
|
||||
// On ARM64 the sp register has the special value 63 (kSPRegInternalCode)
|
||||
using storage_t = typename std::conditional<
|
||||
std::is_same<RegisterT, v8::internal::Register>::value, uint64_t,
|
||||
num_registers_sized_storage_t>::type;
|
||||
#else
|
||||
using storage_t = num_registers_sized_storage_t;
|
||||
#endif
|
||||
|
||||
constexpr RegListBase() = default;
|
||||
constexpr RegListBase(std::initializer_list<RegisterT> regs) {
|
||||
for (RegisterT reg : regs) {
|
||||
set(reg);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void set(RegisterT reg) {
|
||||
if (!reg.is_valid()) return;
|
||||
regs_ |= storage_t{1} << reg.code();
|
||||
}
|
||||
|
||||
constexpr void clear(RegisterT reg) {
|
||||
if (!reg.is_valid()) return;
|
||||
regs_ &= ~(storage_t{1} << reg.code());
|
||||
}
|
||||
|
||||
constexpr bool has(RegisterT reg) const {
|
||||
if (!reg.is_valid()) return false;
|
||||
return (regs_ & (storage_t{1} << reg.code())) != 0;
|
||||
}
|
||||
|
||||
constexpr void clear(RegListBase other) { regs_ &= ~other.regs_; }
|
||||
|
||||
constexpr bool is_empty() const { return regs_ == 0; }
|
||||
|
||||
constexpr unsigned Count() const {
|
||||
return base::bits::CountPopulation(regs_);
|
||||
}
|
||||
|
||||
constexpr RegListBase operator&(const RegListBase other) const {
|
||||
return RegListBase(regs_ & other.regs_);
|
||||
}
|
||||
|
||||
constexpr RegListBase operator|(const RegListBase other) const {
|
||||
return RegListBase(regs_ | other.regs_);
|
||||
}
|
||||
|
||||
constexpr RegListBase operator^(const RegListBase other) const {
|
||||
return RegListBase(regs_ ^ other.regs_);
|
||||
}
|
||||
|
||||
constexpr RegListBase operator-(const RegListBase other) const {
|
||||
return RegListBase(regs_ & ~other.regs_);
|
||||
}
|
||||
|
||||
constexpr RegListBase operator|(const RegisterT reg) const {
|
||||
return *this | RegListBase{reg};
|
||||
}
|
||||
|
||||
constexpr RegListBase operator-(const RegisterT reg) const {
|
||||
return *this - RegListBase{reg};
|
||||
}
|
||||
|
||||
constexpr RegListBase& operator&=(const RegListBase other) {
|
||||
regs_ &= other.regs_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr RegListBase& operator|=(const RegListBase other) {
|
||||
regs_ |= other.regs_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr bool operator==(const RegListBase other) const {
|
||||
return regs_ == other.regs_;
|
||||
}
|
||||
constexpr bool operator!=(const RegListBase other) const {
|
||||
return regs_ != other.regs_;
|
||||
}
|
||||
|
||||
constexpr RegisterT first() const {
|
||||
DCHECK(!is_empty());
|
||||
int first_code = base::bits::CountTrailingZerosNonZero(regs_);
|
||||
return RegisterT::from_code(first_code);
|
||||
}
|
||||
|
||||
constexpr RegisterT last() const {
|
||||
DCHECK(!is_empty());
|
||||
int last_code =
|
||||
8 * sizeof(regs_) - 1 - base::bits::CountLeadingZeros(regs_);
|
||||
return RegisterT::from_code(last_code);
|
||||
}
|
||||
|
||||
constexpr RegisterT PopFirst() {
|
||||
RegisterT reg = first();
|
||||
clear(reg);
|
||||
return reg;
|
||||
}
|
||||
|
||||
constexpr storage_t bits() const { return regs_; }
|
||||
|
||||
inline Iterator begin() const;
|
||||
inline Iterator end() const;
|
||||
|
||||
inline ReverseIterator rbegin() const;
|
||||
inline ReverseIterator rend() const;
|
||||
|
||||
static RegListBase FromBits(storage_t bits) { return RegListBase(bits); }
|
||||
|
||||
template <storage_t bits>
|
||||
static constexpr RegListBase FromBits() {
|
||||
return RegListBase{bits};
|
||||
}
|
||||
|
||||
private:
|
||||
// Unchecked constructor. Only use for valid bits.
|
||||
explicit constexpr RegListBase(storage_t bits) : regs_(bits) {}
|
||||
|
||||
storage_t regs_ = 0;
|
||||
};
|
||||
|
||||
template <typename RegisterT>
|
||||
class RegListBase<RegisterT>::Iterator
|
||||
: public base::iterator<std::forward_iterator_tag, RegisterT> {
|
||||
public:
|
||||
RegisterT operator*() { return remaining_.first(); }
|
||||
Iterator& operator++() {
|
||||
remaining_.clear(remaining_.first());
|
||||
return *this;
|
||||
}
|
||||
bool operator==(Iterator other) { return remaining_ == other.remaining_; }
|
||||
bool operator!=(Iterator other) { return remaining_ != other.remaining_; }
|
||||
|
||||
private:
|
||||
explicit Iterator(RegListBase<RegisterT> remaining) : remaining_(remaining) {}
|
||||
friend class RegListBase;
|
||||
|
||||
RegListBase<RegisterT> remaining_;
|
||||
};
|
||||
|
||||
template <typename RegisterT>
|
||||
class RegListBase<RegisterT>::ReverseIterator
|
||||
: public base::iterator<std::forward_iterator_tag, RegisterT> {
|
||||
public:
|
||||
RegisterT operator*() { return remaining_.last(); }
|
||||
ReverseIterator& operator++() {
|
||||
remaining_.clear(remaining_.last());
|
||||
return *this;
|
||||
}
|
||||
bool operator==(ReverseIterator other) {
|
||||
return remaining_ == other.remaining_;
|
||||
}
|
||||
bool operator!=(ReverseIterator other) {
|
||||
return remaining_ != other.remaining_;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit ReverseIterator(RegListBase<RegisterT> remaining)
|
||||
: remaining_(remaining) {}
|
||||
friend class RegListBase;
|
||||
|
||||
RegListBase<RegisterT> remaining_;
|
||||
};
|
||||
|
||||
template <typename RegisterT>
|
||||
typename RegListBase<RegisterT>::Iterator RegListBase<RegisterT>::begin()
|
||||
const {
|
||||
return Iterator{*this};
|
||||
}
|
||||
template <typename RegisterT>
|
||||
typename RegListBase<RegisterT>::Iterator RegListBase<RegisterT>::end() const {
|
||||
return Iterator{RegListBase<RegisterT>{}};
|
||||
}
|
||||
|
||||
template <typename RegisterT>
|
||||
typename RegListBase<RegisterT>::ReverseIterator
|
||||
RegListBase<RegisterT>::rbegin() const {
|
||||
return ReverseIterator{*this};
|
||||
}
|
||||
template <typename RegisterT>
|
||||
typename RegListBase<RegisterT>::ReverseIterator RegListBase<RegisterT>::rend()
|
||||
const {
|
||||
return ReverseIterator{RegListBase<RegisterT>{}};
|
||||
}
|
||||
|
||||
template <typename RegisterT>
|
||||
inline std::ostream& operator<<(std::ostream& os,
|
||||
RegListBase<RegisterT> reglist) {
|
||||
os << "{";
|
||||
for (bool first = true; !reglist.is_empty(); first = false) {
|
||||
RegisterT reg = reglist.first();
|
||||
reglist.clear(reg);
|
||||
os << (first ? "" : ", ") << reg;
|
||||
}
|
||||
return os << "}";
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_CODEGEN_REGLIST_BASE_H_
|
@ -5,41 +5,39 @@
|
||||
#ifndef V8_CODEGEN_REGLIST_H_
|
||||
#define V8_CODEGEN_REGLIST_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "src/base/bits.h"
|
||||
#include "src/base/template-utils.h"
|
||||
#if V8_TARGET_ARCH_IA32
|
||||
#include "src/codegen/ia32/reglist-ia32.h"
|
||||
#elif V8_TARGET_ARCH_X64
|
||||
#include "src/codegen/x64/reglist-x64.h"
|
||||
#elif V8_TARGET_ARCH_ARM64
|
||||
#include "src/codegen/arm64/reglist-arm64.h"
|
||||
#elif V8_TARGET_ARCH_ARM
|
||||
#include "src/codegen/arm/reglist-arm.h"
|
||||
#elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
|
||||
#include "src/codegen/ppc/reglist-ppc.h"
|
||||
#elif V8_TARGET_ARCH_MIPS
|
||||
#include "src/codegen/mips/reglist-mips.h"
|
||||
#elif V8_TARGET_ARCH_MIPS64
|
||||
#include "src/codegen/mips64/reglist-mips64.h"
|
||||
#elif V8_TARGET_ARCH_LOONG64
|
||||
#include "src/codegen/loong64/reglist-loong64.h"
|
||||
#elif V8_TARGET_ARCH_S390
|
||||
#include "src/codegen/s390/reglist-s390.h"
|
||||
#elif V8_TARGET_ARCH_RISCV64
|
||||
#include "src/codegen/riscv64/reglist-riscv64.h"
|
||||
#else
|
||||
#error Unknown architecture.
|
||||
#endif
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// Register configurations.
|
||||
#if V8_TARGET_ARCH_ARM64
|
||||
using RegList = uint64_t;
|
||||
#else
|
||||
using RegList = uint32_t;
|
||||
#endif
|
||||
static constexpr RegList kEmptyRegList = {};
|
||||
|
||||
constexpr RegList kEmptyRegList = 0;
|
||||
|
||||
// Get the number of registers in a given register list.
|
||||
constexpr int NumRegs(RegList list) {
|
||||
return base::bits::CountPopulation(list);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
// Combine two RegLists by building the union of the contained registers.
|
||||
// TODO(clemensb): Replace by constexpr lambda once we have C++17.
|
||||
constexpr RegList CombineRegListsHelper(RegList list1, RegList list2) {
|
||||
return list1 | list2;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
// Combine several RegLists by building the union of the contained registers.
|
||||
template <typename... RegLists>
|
||||
constexpr RegList CombineRegLists(RegLists... lists) {
|
||||
return base::fold(detail::CombineRegListsHelper, 0, lists...);
|
||||
}
|
||||
#define LIST_REG(V) V,
|
||||
static constexpr RegList kAllocatableGeneralRegisters = {
|
||||
ALLOCATABLE_GENERAL_REGISTERS(LIST_REG) Register::no_reg()};
|
||||
#undef LIST_REG
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -214,7 +214,7 @@ Assembler::Assembler(const AssemblerOptions& options,
|
||||
std::unique_ptr<AssemblerBuffer> buffer)
|
||||
: AssemblerBase(options, std::move(buffer)),
|
||||
VU(this),
|
||||
scratch_register_list_(t3.bit() | t5.bit()),
|
||||
scratch_register_list_({t3, t5}),
|
||||
constpool_(this) {
|
||||
reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
|
||||
|
||||
|
@ -1796,11 +1796,11 @@ class V8_EXPORT_PRIVATE UseScratchRegisterScope {
|
||||
void Include(const RegList& list) { *available_ |= list; }
|
||||
void Exclude(const RegList& list) { *available_ &= ~list; }
|
||||
void Include(const Register& reg1, const Register& reg2 = no_reg) {
|
||||
RegList list(reg1.bit() | reg2.bit());
|
||||
RegList list({reg1, reg2});
|
||||
Include(list);
|
||||
}
|
||||
void Exclude(const Register& reg1, const Register& reg2 = no_reg) {
|
||||
RegList list(reg1.bit() | reg2.bit());
|
||||
RegList list({reg1, reg2});
|
||||
Exclude(list);
|
||||
}
|
||||
|
||||
|
@ -25,14 +25,14 @@ template <typename DerivedDescriptor>
|
||||
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
|
||||
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
|
||||
RegList allocatable_regs = data->allocatable_registers();
|
||||
if (argc >= 1) DCHECK(allocatable_regs | a0.bit());
|
||||
if (argc >= 2) DCHECK(allocatable_regs | a1.bit());
|
||||
if (argc >= 3) DCHECK(allocatable_regs | a2.bit());
|
||||
if (argc >= 4) DCHECK(allocatable_regs | a3.bit());
|
||||
if (argc >= 5) DCHECK(allocatable_regs | a4.bit());
|
||||
if (argc >= 6) DCHECK(allocatable_regs | a5.bit());
|
||||
if (argc >= 7) DCHECK(allocatable_regs | a6.bit());
|
||||
if (argc >= 8) DCHECK(allocatable_regs | a7.bit());
|
||||
if (argc >= 1) DCHECK(allocatable_regs.has(a0));
|
||||
if (argc >= 2) DCHECK(allocatable_regs.has(a1));
|
||||
if (argc >= 3) DCHECK(allocatable_regs.has(a2));
|
||||
if (argc >= 4) DCHECK(allocatable_regs.has(a3));
|
||||
if (argc >= 5) DCHECK(allocatable_regs.has(a4));
|
||||
if (argc >= 6) DCHECK(allocatable_regs.has(a5));
|
||||
if (argc >= 7) DCHECK(allocatable_regs.has(a6));
|
||||
if (argc >= 8) DCHECK(allocatable_regs.has(a7));
|
||||
// Additional arguments are passed on the stack.
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
@ -48,22 +48,13 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
|
||||
Register exclusion2,
|
||||
Register exclusion3) const {
|
||||
int bytes = 0;
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
bytes += NumRegs(list) * kSystemPointerSize;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
bytes += list.Count() * kSystemPointerSize;
|
||||
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
|
||||
bytes += kCallerSavedFPU.Count() * kDoubleSize;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
@ -72,24 +63,15 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
|
||||
int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
|
||||
Register exclusion2, Register exclusion3) {
|
||||
int bytes = 0;
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
MultiPush(list);
|
||||
bytes += NumRegs(list) * kSystemPointerSize;
|
||||
bytes += list.Count() * kSystemPointerSize;
|
||||
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
MultiPushFPU(kCallerSavedFPU);
|
||||
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
|
||||
bytes += kCallerSavedFPU.Count() * kDoubleSize;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
@ -100,23 +82,13 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
|
||||
int bytes = 0;
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
MultiPopFPU(kCallerSavedFPU);
|
||||
bytes += NumRegs(kCallerSavedFPU) * kDoubleSize;
|
||||
bytes += kCallerSavedFPU.Count() * kDoubleSize;
|
||||
}
|
||||
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
MultiPop(list);
|
||||
bytes += NumRegs(list) * kSystemPointerSize;
|
||||
bytes += list.Count() * kSystemPointerSize;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
@ -205,25 +177,13 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
RegList regs = 0;
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
regs |= Register::from_code(i).bit();
|
||||
}
|
||||
}
|
||||
MultiPush(regs);
|
||||
if (registers.is_empty()) return;
|
||||
MultiPush(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
RegList regs = 0;
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
regs |= Register::from_code(i).bit();
|
||||
}
|
||||
}
|
||||
MultiPop(regs);
|
||||
if (registers.is_empty()) return;
|
||||
MultiPop(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object,
|
||||
@ -1693,20 +1653,19 @@ void TurboAssembler::li(Register rd, Operand j, LiFlags mode) {
|
||||
}
|
||||
}
|
||||
|
||||
static RegList t_regs = Register::ListOf(t0, t1, t2, t3, t4, t5, t6);
|
||||
static RegList a_regs = Register::ListOf(a0, a1, a2, a3, a4, a5, a6, a7);
|
||||
static RegList s_regs =
|
||||
Register::ListOf(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11);
|
||||
static RegList t_regs = {t0, t1, t2, t3, t4, t5, t6};
|
||||
static RegList a_regs = {a0, a1, a2, a3, a4, a5, a6, a7};
|
||||
static RegList s_regs = {s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11};
|
||||
|
||||
void TurboAssembler::MultiPush(RegList regs) {
|
||||
int16_t num_to_push = base::bits::CountPopulation(regs);
|
||||
int16_t stack_offset = num_to_push * kSystemPointerSize;
|
||||
|
||||
#define TEST_AND_PUSH_REG(reg) \
|
||||
if ((regs & reg.bit()) != 0) { \
|
||||
if (regs.has(reg)) { \
|
||||
stack_offset -= kSystemPointerSize; \
|
||||
Sd(reg, MemOperand(sp, stack_offset)); \
|
||||
regs &= ~reg.bit(); \
|
||||
regs.clear(reg); \
|
||||
}
|
||||
|
||||
#define T_REGS(V) V(t6) V(t5) V(t4) V(t3) V(t2) V(t1) V(t0)
|
||||
@ -1746,10 +1705,10 @@ void TurboAssembler::MultiPop(RegList regs) {
|
||||
int16_t stack_offset = 0;
|
||||
|
||||
#define TEST_AND_POP_REG(reg) \
|
||||
if ((regs & reg.bit()) != 0) { \
|
||||
if (regs.has(reg)) { \
|
||||
Ld(reg, MemOperand(sp, stack_offset)); \
|
||||
stack_offset += kSystemPointerSize; \
|
||||
regs &= ~reg.bit(); \
|
||||
regs.clear(reg); \
|
||||
}
|
||||
|
||||
#define T_REGS(V) V(t0) V(t1) V(t2) V(t3) V(t4) V(t5) V(t6)
|
||||
@ -4993,19 +4952,13 @@ void TurboAssembler::CheckPageFlag(Register object, Register scratch, int mask,
|
||||
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
|
||||
Register reg4, Register reg5,
|
||||
Register reg6) {
|
||||
RegList regs = 0;
|
||||
if (reg1.is_valid()) regs |= reg1.bit();
|
||||
if (reg2.is_valid()) regs |= reg2.bit();
|
||||
if (reg3.is_valid()) regs |= reg3.bit();
|
||||
if (reg4.is_valid()) regs |= reg4.bit();
|
||||
if (reg5.is_valid()) regs |= reg5.bit();
|
||||
if (reg6.is_valid()) regs |= reg6.bit();
|
||||
RegList regs = {reg1, reg2, reg3, reg4, reg5, reg6};
|
||||
|
||||
const RegisterConfiguration* config = RegisterConfiguration::Default();
|
||||
for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
|
||||
int code = config->GetAllocatableGeneralCode(i);
|
||||
Register candidate = Register::from_code(code);
|
||||
if (regs & candidate.bit()) continue;
|
||||
if (regs.has(candidate)) continue;
|
||||
return candidate;
|
||||
}
|
||||
UNREACHABLE();
|
||||
|
@ -6,8 +6,6 @@
|
||||
#define V8_CODEGEN_RISCV64_REGISTER_RISCV64_H_
|
||||
|
||||
#include "src/codegen/register-base.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/codegen/reglist.h"
|
||||
#include "src/codegen/riscv64/constants-riscv64.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -123,7 +121,7 @@ const RegList kCalleeSavedFPU = 1 << 8 | // fs0
|
||||
1 << 26 | // fs10
|
||||
1 << 27; // fs11
|
||||
|
||||
const int kNumCalleeSavedFPU = NumRegs(kCalleeSavedFPU);
|
||||
const int kNumCalleeSavedFPU = kCalleeSavedFPU.Count();
|
||||
|
||||
const RegList kCallerSavedFPU = 1 << 0 | // ft0
|
||||
1 << 1 | // ft1
|
||||
@ -146,7 +144,7 @@ const RegList kCallerSavedFPU = 1 << 0 | // ft0
|
||||
1 << 30 | // ft10
|
||||
1 << 31; // ft11
|
||||
|
||||
const int kNumCallerSavedFPU = NumRegs(kCallerSavedFPU);
|
||||
const int kNumCallerSavedFPU = kCallerSavedFPU.Count();
|
||||
|
||||
// Number of registers for which space is reserved in safepoints. Must be a
|
||||
// multiple of 8.
|
||||
|
64
src/codegen/riscv64/reglist-riscv64.h
Normal file
64
src/codegen/riscv64/reglist-riscv64.h
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_CODEGEN_RISCV64_REGLIST_RISCV64_H_
|
||||
#define V8_CODEGEN_RISCV64_REGLIST_RISCV64_H_
|
||||
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/reglist-base.h"
|
||||
#include "src/codegen/riscv64/constants-riscv64.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
using RegList = RegListBase<Register>;
|
||||
using DoubleRegList = RegListBase<DoubleRegister>;
|
||||
ASSERT_TRIVIALLY_COPYABLE(RegList);
|
||||
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
|
||||
|
||||
const RegList kJSCallerSaved = {t0, t1, t2, a0, a1, a2, a3, a4, a5, a6, a7, t4};
|
||||
|
||||
const int kNumJSCallerSaved = 12;
|
||||
|
||||
// Callee-saved registers preserved when switching from C to JavaScript.
|
||||
const RegList kCalleeSaved = {fp, // fp/s0
|
||||
s1, // s1
|
||||
s2, // s2
|
||||
s3, // s3 scratch register
|
||||
s4, // s4 scratch register 2
|
||||
s5, // s5
|
||||
s6, // s6 (roots in Javascript code)
|
||||
s7, // s7 (cp in Javascript code)
|
||||
s8, // s8
|
||||
s9, // s9
|
||||
s10, // s10
|
||||
s11}; // s11
|
||||
|
||||
const int kNumCalleeSaved = 12;
|
||||
|
||||
const RegList kCalleeSavedFPU = {fs0, fs1, fs2, fs3, fs4, fs5,
|
||||
fs6, fs7, fs8, fs9, fs10, fs11};
|
||||
|
||||
const int kNumCalleeSavedFPU = kCalleeSavedFPU.Count();
|
||||
|
||||
const RegList kCallerSavedFPU = {ft0, ft1, ft2, ft3, ft4, ft5, ft6,
|
||||
ft7, fa0, fa1, fa2, fa3, fa4, fa5,
|
||||
fa6, fa7, ft8, ft9, ft10, ft11};
|
||||
|
||||
const int kNumCallerSavedFPU = kCallerSavedFPU.Count();
|
||||
|
||||
// Number of registers for which space is reserved in safepoints. Must be a
|
||||
// multiple of 8.
|
||||
const int kNumSafepointRegisters = 32;
|
||||
|
||||
// Define the list of registers actually saved at safepoints.
|
||||
// Note that the number of saved registers may be smaller than the reserved
|
||||
// space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters.
|
||||
const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved;
|
||||
const int kNumSafepointSavedRegisters = kNumJSCallerSaved + kNumCalleeSaved;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_CODEGEN_RISCV64_REGLIST_RISCV64_H_
|
@ -375,8 +375,7 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
|
||||
|
||||
Assembler::Assembler(const AssemblerOptions& options,
|
||||
std::unique_ptr<AssemblerBuffer> buffer)
|
||||
: AssemblerBase(options, std::move(buffer)),
|
||||
scratch_register_list_(ip.bit()) {
|
||||
: AssemblerBase(options, std::move(buffer)), scratch_register_list_({ip}) {
|
||||
reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
|
||||
last_bound_pos_ = 0;
|
||||
relocations_.reserve(128);
|
||||
@ -885,11 +884,7 @@ UseScratchRegisterScope::~UseScratchRegisterScope() {
|
||||
Register UseScratchRegisterScope::Acquire() {
|
||||
RegList* available = assembler_->GetScratchRegisterList();
|
||||
DCHECK_NOT_NULL(available);
|
||||
DCHECK_NE(*available, 0);
|
||||
int index = static_cast<int>(base::bits::CountTrailingZeros32(*available));
|
||||
Register reg = Register::from_code(index);
|
||||
*available &= ~reg.bit();
|
||||
return reg;
|
||||
return available->PopFront();
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -24,14 +24,14 @@ template <typename DerivedDescriptor>
|
||||
void StaticCallInterfaceDescriptor<DerivedDescriptor>::
|
||||
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
|
||||
RegList allocatable_regs = data->allocatable_registers();
|
||||
if (argc >= 1) DCHECK(allocatable_regs | r2.bit());
|
||||
if (argc >= 2) DCHECK(allocatable_regs | r3.bit());
|
||||
if (argc >= 3) DCHECK(allocatable_regs | r4.bit());
|
||||
if (argc >= 4) DCHECK(allocatable_regs | r5.bit());
|
||||
if (argc >= 5) DCHECK(allocatable_regs | r6.bit());
|
||||
if (argc >= 6) DCHECK(allocatable_regs | r7.bit());
|
||||
if (argc >= 7) DCHECK(allocatable_regs | r8.bit());
|
||||
if (argc >= 8) DCHECK(allocatable_regs | r9.bit());
|
||||
if (argc >= 1) DCHECK(allocatable_regs.has(r2));
|
||||
if (argc >= 2) DCHECK(allocatable_regs.has(r3));
|
||||
if (argc >= 3) DCHECK(allocatable_regs.has(r4));
|
||||
if (argc >= 4) DCHECK(allocatable_regs.has(r5));
|
||||
if (argc >= 5) DCHECK(allocatable_regs.has(r6));
|
||||
if (argc >= 6) DCHECK(allocatable_regs.has(r7));
|
||||
if (argc >= 7) DCHECK(allocatable_regs.has(r8));
|
||||
if (argc >= 8) DCHECK(allocatable_regs.has(r9));
|
||||
// Additional arguments are passed on the stack.
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
@ -284,19 +284,10 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
|
||||
Register exclusion2,
|
||||
Register exclusion3) const {
|
||||
int bytes = 0;
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
bytes += NumRegs(list) * kSystemPointerSize;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
bytes += list.Count() * kSystemPointerSize;
|
||||
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
bytes += kStackSavedSavedFPSizeInBytes;
|
||||
@ -308,20 +299,11 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
|
||||
int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
|
||||
Register exclusion2, Register exclusion3) {
|
||||
int bytes = 0;
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
MultiPush(list);
|
||||
bytes += NumRegs(list) * kSystemPointerSize;
|
||||
bytes += list.Count() * kSystemPointerSize;
|
||||
|
||||
if (fp_mode == SaveFPRegsMode::kSave) {
|
||||
MultiPushF64OrV128(kCallerSavedDoubles);
|
||||
@ -339,20 +321,10 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
|
||||
bytes += kStackSavedSavedFPSizeInBytes;
|
||||
}
|
||||
|
||||
RegList exclusions = 0;
|
||||
if (exclusion1 != no_reg) {
|
||||
exclusions |= exclusion1.bit();
|
||||
if (exclusion2 != no_reg) {
|
||||
exclusions |= exclusion2.bit();
|
||||
if (exclusion3 != no_reg) {
|
||||
exclusions |= exclusion3.bit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegList list = kJSCallerSaved & ~exclusions;
|
||||
RegList exclusions = {exclusion1, exclusion2, exclusion3};
|
||||
RegList list = kJSCallerSaved - exclusions;
|
||||
MultiPop(list);
|
||||
bytes += NumRegs(list) * kSystemPointerSize;
|
||||
bytes += list.Count() * kSystemPointerSize;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
@ -753,14 +725,14 @@ void TurboAssembler::MultiPushF64OrV128(RegList dregs, Register location) {
|
||||
MultiPushDoubles(dregs);
|
||||
// We still need to allocate empty space on the stack as if
|
||||
// Simd rgeisters were saved (see kFixedFrameSizeFromFp).
|
||||
lay(sp, MemOperand(sp, -(NumRegs(dregs) * kDoubleSize)));
|
||||
lay(sp, MemOperand(sp, -(dregs.Count() * kDoubleSize)));
|
||||
bind(&simd_pushed);
|
||||
} else {
|
||||
if (CpuFeatures::SupportsWasmSimd128()) {
|
||||
MultiPushV128(dregs);
|
||||
} else {
|
||||
MultiPushDoubles(dregs);
|
||||
lay(sp, MemOperand(sp, -(NumRegs(dregs) * kDoubleSize)));
|
||||
lay(sp, MemOperand(sp, -(dregs.Count() * kDoubleSize)));
|
||||
}
|
||||
}
|
||||
#else
|
||||
@ -783,14 +755,14 @@ void TurboAssembler::MultiPopF64OrV128(RegList dregs, Register location) {
|
||||
b(&simd_popped);
|
||||
bind(&pop_doubles);
|
||||
// Simd not supported, only pop double registers.
|
||||
lay(sp, MemOperand(sp, NumRegs(dregs) * kDoubleSize));
|
||||
lay(sp, MemOperand(sp, dregs.Count() * kDoubleSize));
|
||||
MultiPopDoubles(dregs);
|
||||
bind(&simd_popped);
|
||||
} else {
|
||||
if (CpuFeatures::SupportsWasmSimd128()) {
|
||||
MultiPopV128(dregs);
|
||||
} else {
|
||||
lay(sp, MemOperand(sp, NumRegs(dregs) * kDoubleSize));
|
||||
lay(sp, MemOperand(sp, dregs.Count() * kDoubleSize));
|
||||
MultiPopDoubles(dregs);
|
||||
}
|
||||
}
|
||||
@ -947,25 +919,13 @@ void MacroAssembler::RecordWriteField(Register object, int offset,
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
RegList regs = 0;
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
regs |= Register::from_code(i).bit();
|
||||
}
|
||||
}
|
||||
MultiPush(regs);
|
||||
if (registers.is_empty()) return;
|
||||
MultiPush(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
RegList regs = 0;
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
regs |= Register::from_code(i).bit();
|
||||
}
|
||||
}
|
||||
MultiPop(regs);
|
||||
if (registers.is_empty()) return;
|
||||
MultiPop(registers);
|
||||
}
|
||||
|
||||
void TurboAssembler::CallEphemeronKeyBarrier(Register object,
|
||||
@ -2455,19 +2415,13 @@ void TurboAssembler::CheckPageFlag(
|
||||
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
|
||||
Register reg4, Register reg5,
|
||||
Register reg6) {
|
||||
RegList regs = 0;
|
||||
if (reg1.is_valid()) regs |= reg1.bit();
|
||||
if (reg2.is_valid()) regs |= reg2.bit();
|
||||
if (reg3.is_valid()) regs |= reg3.bit();
|
||||
if (reg4.is_valid()) regs |= reg4.bit();
|
||||
if (reg5.is_valid()) regs |= reg5.bit();
|
||||
if (reg6.is_valid()) regs |= reg6.bit();
|
||||
RegList regs = {reg1, reg2, reg3, reg4, reg5, reg6};
|
||||
|
||||
const RegisterConfiguration* config = RegisterConfiguration::Default();
|
||||
for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
|
||||
int code = config->GetAllocatableGeneralCode(i);
|
||||
Register candidate = Register::from_code(code);
|
||||
if (regs & candidate.bit()) continue;
|
||||
if (regs.has(candidate)) continue;
|
||||
return candidate;
|
||||
}
|
||||
UNREACHABLE();
|
||||
|
@ -6,8 +6,6 @@
|
||||
#define V8_CODEGEN_S390_REGISTER_S390_H_
|
||||
|
||||
#include "src/codegen/register-base.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/codegen/reglist.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -37,56 +35,6 @@ namespace internal {
|
||||
V(cr8) V(cr9) V(cr10) V(cr11) V(cr12) V(cr15)
|
||||
// clang-format on
|
||||
|
||||
// Register list in load/store instructions
|
||||
// Note that the bit values must match those used in actual instruction encoding
|
||||
|
||||
// Caller-saved/arguments registers
|
||||
const RegList kJSCallerSaved = 1 << 1 | 1 << 2 | // r2 a1
|
||||
1 << 3 | // r3 a2
|
||||
1 << 4 | // r4 a3
|
||||
1 << 5; // r5 a4
|
||||
|
||||
const int kNumJSCallerSaved = 5;
|
||||
|
||||
// Callee-saved registers preserved when switching from C to JavaScript
|
||||
const RegList kCalleeSaved =
|
||||
1 << 6 | // r6 (argument passing in CEntryStub)
|
||||
// (HandleScope logic in MacroAssembler)
|
||||
1 << 7 | // r7 (argument passing in CEntryStub)
|
||||
// (HandleScope logic in MacroAssembler)
|
||||
1 << 8 | // r8 (argument passing in CEntryStub)
|
||||
// (HandleScope logic in MacroAssembler)
|
||||
1 << 9 | // r9 (HandleScope logic in MacroAssembler)
|
||||
1 << 10 | // r10 (Roots register in Javascript)
|
||||
1 << 11 | // r11 (fp in Javascript)
|
||||
1 << 12 | // r12 (ip in Javascript)
|
||||
1 << 13; // r13 (cp in Javascript)
|
||||
// 1 << 15; // r15 (sp in Javascript)
|
||||
|
||||
const int kNumCalleeSaved = 8;
|
||||
|
||||
const RegList kCallerSavedDoubles = 1 << 0 | // d0
|
||||
1 << 1 | // d1
|
||||
1 << 2 | // d2
|
||||
1 << 3 | // d3
|
||||
1 << 4 | // d4
|
||||
1 << 5 | // d5
|
||||
1 << 6 | // d6
|
||||
1 << 7; // d7
|
||||
|
||||
const int kNumCallerSavedDoubles = 8;
|
||||
|
||||
const RegList kCalleeSavedDoubles = 1 << 8 | // d8
|
||||
1 << 9 | // d9
|
||||
1 << 10 | // d10
|
||||
1 << 11 | // d11
|
||||
1 << 12 | // d12
|
||||
1 << 13 | // d12
|
||||
1 << 14 | // d12
|
||||
1 << 15; // d13
|
||||
|
||||
const int kNumCalleeSavedDoubles = 8;
|
||||
|
||||
// The following constants describe the stack frame linkage area as
|
||||
// defined by the ABI.
|
||||
|
||||
|
57
src/codegen/s390/reglist-s390.h
Normal file
57
src/codegen/s390/reglist-s390.h
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_CODEGEN_S390_REGLIST_S390_H_
|
||||
#define V8_CODEGEN_S390_REGLIST_S390_H_
|
||||
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/reglist-base.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
using RegList = RegListBase<Register>;
|
||||
using DoubleRegList = RegListBase<DoubleRegister>;
|
||||
ASSERT_TRIVIALLY_COPYABLE(RegList);
|
||||
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
|
||||
|
||||
// Register list in load/store instructions
|
||||
// Note that the bit values must match those used in actual instruction encoding
|
||||
|
||||
// Caller-saved/arguments registers
|
||||
const RegList kJSCallerSaved = {r1, r2, // r2 a1
|
||||
r3, // r3 a2
|
||||
r4, // r4 a3
|
||||
r5}; // r5 a4
|
||||
|
||||
const int kNumJSCallerSaved = 5;
|
||||
|
||||
// Callee-saved registers preserved when switching from C to JavaScript
|
||||
const RegList kCalleeSaved = {r6, // r6 (argument passing in CEntryStub)
|
||||
// (HandleScope logic in MacroAssembler)
|
||||
r7, // r7 (argument passing in CEntryStub)
|
||||
// (HandleScope logic in MacroAssembler)
|
||||
r8, // r8 (argument passing in CEntryStub)
|
||||
// (HandleScope logic in MacroAssembler)
|
||||
r9, // r9 (HandleScope logic in MacroAssembler)
|
||||
r10, // r10 (Roots register in Javascript)
|
||||
r11, // r11 (fp in Javascript)
|
||||
r12, // r12 (ip in Javascript)
|
||||
r13}; // r13 (cp in Javascript)
|
||||
// r15; // r15 (sp in Javascript)
|
||||
|
||||
const int kNumCalleeSaved = 8;
|
||||
|
||||
const RegList kCallerSavedDoubles = {d0, d1, d2, d3, d4, d5, d6, d7};
|
||||
|
||||
const int kNumCallerSavedDoubles = 8;
|
||||
|
||||
const RegList kCalleeSavedDoubles = {d8, d9, d10, d11, d12, d13, d14, d15};
|
||||
|
||||
const int kNumCalleeSavedDoubles = 8;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_CODEGEN_S390_REGLIST_S390_H_
|
@ -24,10 +24,10 @@ void StaticCallInterfaceDescriptor<DerivedDescriptor>::
|
||||
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data,
|
||||
int nof_expected_args) {
|
||||
RegList allocatable_regs = data->allocatable_registers();
|
||||
if (nof_expected_args >= 1) DCHECK(allocatable_regs | arg_reg_1.bit());
|
||||
if (nof_expected_args >= 2) DCHECK(allocatable_regs | arg_reg_2.bit());
|
||||
if (nof_expected_args >= 3) DCHECK(allocatable_regs | arg_reg_3.bit());
|
||||
if (nof_expected_args >= 4) DCHECK(allocatable_regs | arg_reg_4.bit());
|
||||
if (nof_expected_args >= 1) DCHECK(allocatable_regs.has(arg_reg_1));
|
||||
if (nof_expected_args >= 2) DCHECK(allocatable_regs.has(arg_reg_2));
|
||||
if (nof_expected_args >= 3) DCHECK(allocatable_regs.has(arg_reg_3));
|
||||
if (nof_expected_args >= 4) DCHECK(allocatable_regs.has(arg_reg_4));
|
||||
// Additional arguments are passed on the stack.
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
@ -442,22 +442,14 @@ void TurboAssembler::LoadExternalPointerField(
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeSaveRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
DCHECK_GT(NumRegs(registers), 0);
|
||||
for (int i = 0; i < Register::kNumRegisters; ++i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
pushq(Register::from_code(i));
|
||||
}
|
||||
for (Register reg : registers) {
|
||||
pushq(reg);
|
||||
}
|
||||
}
|
||||
|
||||
void TurboAssembler::MaybeRestoreRegisters(RegList registers) {
|
||||
if (registers == 0) return;
|
||||
DCHECK_GT(NumRegs(registers), 0);
|
||||
for (int i = Register::kNumRegisters - 1; i >= 0; --i) {
|
||||
if ((registers >> i) & 1u) {
|
||||
popq(Register::from_code(i));
|
||||
}
|
||||
for (Register reg : base::Reversed(registers)) {
|
||||
popq(reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,6 @@
|
||||
#define V8_CODEGEN_X64_REGISTER_X64_H_
|
||||
|
||||
#include "src/codegen/register-base.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/codegen/reglist.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -87,20 +85,6 @@ constexpr Register no_reg = Register::no_reg();
|
||||
|
||||
constexpr int kNumRegs = 16;
|
||||
|
||||
constexpr RegList kJSCallerSaved =
|
||||
Register::ListOf(rax, rcx, rdx,
|
||||
rbx, // used as a caller-saved register in JavaScript code
|
||||
rdi); // callee function
|
||||
|
||||
constexpr RegList kCallerSaved =
|
||||
#ifdef V8_TARGET_OS_WIN
|
||||
Register::ListOf(rax, rcx, rdx, r8, r9, r10, r11);
|
||||
#else
|
||||
Register::ListOf(rax, rcx, rdx, rdi, rsi, r8, r9, r10, r11);
|
||||
#endif // V8_TARGET_OS_WIN
|
||||
|
||||
constexpr int kNumJSCallerSaved = 5;
|
||||
|
||||
#ifdef V8_TARGET_OS_WIN
|
||||
// Windows calling convention
|
||||
constexpr Register arg_reg_1 = rcx;
|
||||
|
37
src/codegen/x64/reglist-x64.h
Normal file
37
src/codegen/x64/reglist-x64.h
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_CODEGEN_X64_REGLIST_X64_H_
|
||||
#define V8_CODEGEN_X64_REGLIST_X64_H_
|
||||
|
||||
#include "src/base/macros.h"
|
||||
#include "src/codegen/register-arch.h"
|
||||
#include "src/codegen/reglist-base.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
using RegList = RegListBase<Register>;
|
||||
using DoubleRegList = RegListBase<DoubleRegister>;
|
||||
ASSERT_TRIVIALLY_COPYABLE(RegList);
|
||||
ASSERT_TRIVIALLY_COPYABLE(DoubleRegList);
|
||||
|
||||
constexpr RegList kJSCallerSaved = {
|
||||
rax, rcx, rdx,
|
||||
rbx, // used as a caller-saved register in JavaScript code
|
||||
rdi}; // callee function
|
||||
|
||||
constexpr RegList kCallerSaved =
|
||||
#ifdef V8_TARGET_OS_WIN
|
||||
{rax, rcx, rdx, r8, r9, r10, r11};
|
||||
#else
|
||||
{rax, rcx, rdx, rdi, rsi, r8, r9, r10, r11};
|
||||
#endif // V8_TARGET_OS_WIN
|
||||
|
||||
constexpr int kNumJSCallerSaved = 5;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_CODEGEN_X64_REGLIST_X64_H_
|
@ -1719,6 +1719,17 @@ inline std::ostream& operator<<(std::ostream& os, ConcurrencyMode mode) {
|
||||
return os << ToString(mode);
|
||||
}
|
||||
|
||||
// An architecture independent representation of the sets of registers available
|
||||
// for instruction creation.
|
||||
enum class AliasingKind {
|
||||
// Registers alias a single register of every other size (e.g. Intel).
|
||||
kOverlap,
|
||||
// Registers alias two registers of the next smaller size (e.g. ARM).
|
||||
kCombine,
|
||||
// SIMD128 Registers are independent of every other size (e.g Riscv)
|
||||
kIndependent
|
||||
};
|
||||
|
||||
#define FOR_EACH_ISOLATE_ADDRESS_NAME(C) \
|
||||
C(Handler, handler) \
|
||||
C(CEntryFP, c_entry_fp) \
|
||||
|
@ -516,7 +516,7 @@ void CodeGenerator::AssembleDeconstructFrame() {
|
||||
|
||||
void CodeGenerator::AssemblePrepareTailCall() {
|
||||
if (frame_access_state()->has_frame()) {
|
||||
__ ldm(ia, fp, lr.bit() | fp.bit());
|
||||
__ ldm(ia, fp, {lr, fp});
|
||||
}
|
||||
frame_access_state()->SetFrameAccessToSP();
|
||||
}
|
||||
@ -3659,24 +3659,24 @@ void CodeGenerator::AssembleArchSelect(Instruction* instr,
|
||||
void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
auto call_descriptor = linkage()->GetIncomingDescriptor();
|
||||
|
||||
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (saves_fp != 0) {
|
||||
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (!saves_fp.is_empty()) {
|
||||
frame->AlignSavedCalleeRegisterSlots();
|
||||
}
|
||||
|
||||
if (saves_fp != 0) {
|
||||
if (!saves_fp.is_empty()) {
|
||||
// Save callee-saved FP registers.
|
||||
STATIC_ASSERT(DwVfpRegister::kNumRegisters == 32);
|
||||
uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
|
||||
uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
|
||||
DCHECK_EQ((last - first + 1), base::bits::CountPopulation(saves_fp));
|
||||
uint32_t last = base::bits::CountLeadingZeros32(saves_fp.bits()) - 1;
|
||||
uint32_t first = base::bits::CountTrailingZeros32(saves_fp.bits());
|
||||
DCHECK_EQ((last - first + 1), saves_fp.Count());
|
||||
frame->AllocateSavedCalleeRegisterSlots((last - first + 1) *
|
||||
(kDoubleSize / kSystemPointerSize));
|
||||
}
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
// Save callee-saved registers.
|
||||
frame->AllocateSavedCalleeRegisterSlots(base::bits::CountPopulation(saves));
|
||||
frame->AllocateSavedCalleeRegisterSlots(saves.Count());
|
||||
}
|
||||
}
|
||||
|
||||
@ -3734,7 +3734,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
}
|
||||
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
|
||||
if (required_slots > 0) {
|
||||
DCHECK(frame_access_state()->has_frame());
|
||||
@ -3773,25 +3773,21 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
|
||||
// Skip callee-saved and return slots, which are pushed below.
|
||||
required_slots -= base::bits::CountPopulation(saves);
|
||||
required_slots -= saves.Count();
|
||||
required_slots -= frame()->GetReturnSlotCount();
|
||||
required_slots -= 2 * base::bits::CountPopulation(saves_fp);
|
||||
required_slots -= 2 * saves_fp.Count();
|
||||
if (required_slots > 0) {
|
||||
__ AllocateStackSpace(required_slots * kSystemPointerSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (saves_fp != 0) {
|
||||
if (!saves_fp.is_empty()) {
|
||||
// Save callee-saved FP registers.
|
||||
STATIC_ASSERT(DwVfpRegister::kNumRegisters == 32);
|
||||
uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
|
||||
uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
|
||||
DCHECK_EQ((last - first + 1), base::bits::CountPopulation(saves_fp));
|
||||
__ vstm(db_w, sp, DwVfpRegister::from_code(first),
|
||||
DwVfpRegister::from_code(last));
|
||||
__ vstm(db_w, sp, saves_fp.first(), saves_fp.last());
|
||||
}
|
||||
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
// Save callee-saved registers.
|
||||
__ stm(db_w, sp, saves);
|
||||
}
|
||||
@ -3812,18 +3808,15 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
|
||||
// Restore registers.
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
__ ldm(ia_w, sp, saves);
|
||||
}
|
||||
|
||||
// Restore FP registers.
|
||||
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (saves_fp != 0) {
|
||||
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (!saves_fp.is_empty()) {
|
||||
STATIC_ASSERT(DwVfpRegister::kNumRegisters == 32);
|
||||
uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
|
||||
uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
|
||||
__ vldm(ia_w, sp, DwVfpRegister::from_code(first),
|
||||
DwVfpRegister::from_code(last));
|
||||
__ vldm(ia_w, sp, saves_fp.first(), saves_fp.last());
|
||||
}
|
||||
|
||||
unwinding_info_writer_.MarkBlockWillExit();
|
||||
@ -3868,7 +3861,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
if (drop_jsargs) {
|
||||
// Get the actual argument count.
|
||||
__ ldr(argc_reg, MemOperand(fp, StandardFrameConstants::kArgCOffset));
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
|
||||
}
|
||||
AssembleDeconstructFrame();
|
||||
}
|
||||
@ -3878,7 +3871,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
// The number of arguments without the receiver is
|
||||
// max(argc_reg, parameter_slots-1), and the receiver is added in
|
||||
// DropArguments().
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
|
||||
if (parameter_slots > 1) {
|
||||
__ cmp(argc_reg, Operand(parameter_slots));
|
||||
__ mov(argc_reg, Operand(parameter_slots), LeaveCC, lt);
|
||||
|
@ -3005,17 +3005,17 @@ void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
auto call_descriptor = linkage()->GetIncomingDescriptor();
|
||||
|
||||
// Save FP registers.
|
||||
CPURegList saves_fp = CPURegList(CPURegister::kVRegister, kDRegSizeInBits,
|
||||
call_descriptor->CalleeSavedFPRegisters());
|
||||
CPURegList saves_fp =
|
||||
CPURegList(kDRegSizeInBits, call_descriptor->CalleeSavedFPRegisters());
|
||||
int saved_count = saves_fp.Count();
|
||||
if (saved_count != 0) {
|
||||
DCHECK(saves_fp.list() == CPURegList::GetCalleeSavedV().list());
|
||||
DCHECK(saves_fp.bits() == CPURegList::GetCalleeSavedV().bits());
|
||||
frame->AllocateSavedCalleeRegisterSlots(saved_count *
|
||||
(kDoubleSize / kSystemPointerSize));
|
||||
}
|
||||
|
||||
CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
|
||||
call_descriptor->CalleeSavedRegisters());
|
||||
CPURegList saves =
|
||||
CPURegList(kXRegSizeInBits, call_descriptor->CalleeSavedRegisters());
|
||||
saved_count = saves.Count();
|
||||
if (saved_count != 0) {
|
||||
frame->AllocateSavedCalleeRegisterSlots(saved_count);
|
||||
@ -3032,11 +3032,11 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
int required_slots =
|
||||
frame()->GetTotalFrameSlotCount() - frame()->GetFixedSlotCount();
|
||||
|
||||
CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
|
||||
call_descriptor->CalleeSavedRegisters());
|
||||
CPURegList saves =
|
||||
CPURegList(kXRegSizeInBits, call_descriptor->CalleeSavedRegisters());
|
||||
DCHECK_EQ(saves.Count() % 2, 0);
|
||||
CPURegList saves_fp = CPURegList(CPURegister::kVRegister, kDRegSizeInBits,
|
||||
call_descriptor->CalleeSavedFPRegisters());
|
||||
CPURegList saves_fp =
|
||||
CPURegList(kDRegSizeInBits, call_descriptor->CalleeSavedFPRegisters());
|
||||
DCHECK_EQ(saves_fp.Count() % 2, 0);
|
||||
// The number of return slots should be even after aligning the Frame.
|
||||
const int returns = frame()->GetReturnSlotCount();
|
||||
@ -3191,7 +3191,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
|
||||
// Save FP registers.
|
||||
DCHECK_IMPLIES(saves_fp.Count() != 0,
|
||||
saves_fp.list() == CPURegList::GetCalleeSavedV().list());
|
||||
saves_fp.bits() == CPURegList::GetCalleeSavedV().bits());
|
||||
__ PushCPURegList(saves_fp);
|
||||
|
||||
// Save registers.
|
||||
@ -3211,13 +3211,13 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
}
|
||||
|
||||
// Restore registers.
|
||||
CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
|
||||
call_descriptor->CalleeSavedRegisters());
|
||||
CPURegList saves =
|
||||
CPURegList(kXRegSizeInBits, call_descriptor->CalleeSavedRegisters());
|
||||
__ PopCPURegList<TurboAssembler::kAuthLR>(saves);
|
||||
|
||||
// Restore fp registers.
|
||||
CPURegList saves_fp = CPURegList(CPURegister::kVRegister, kDRegSizeInBits,
|
||||
call_descriptor->CalleeSavedFPRegisters());
|
||||
CPURegList saves_fp =
|
||||
CPURegList(kDRegSizeInBits, call_descriptor->CalleeSavedFPRegisters());
|
||||
__ PopCPURegList(saves_fp);
|
||||
|
||||
unwinding_info_writer_.MarkBlockWillExit();
|
||||
@ -3261,7 +3261,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
}
|
||||
if (drop_jsargs) {
|
||||
// Get the actual argument count.
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
|
||||
__ Ldr(argc_reg, MemOperand(fp, StandardFrameConstants::kArgCOffset));
|
||||
}
|
||||
AssembleDeconstructFrame();
|
||||
@ -3271,7 +3271,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
// We must pop all arguments from the stack (including the receiver). This
|
||||
// number of arguments is given by max(1 + argc_reg, parameter_slots).
|
||||
Label argc_reg_has_final_count;
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
|
||||
if (parameter_slots > 1) {
|
||||
__ Cmp(argc_reg, Operand(parameter_slots));
|
||||
__ B(&argc_reg_has_final_count, ge);
|
||||
|
@ -3999,14 +3999,9 @@ void CodeGenerator::AssembleArchSelect(Instruction* instr,
|
||||
void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
auto call_descriptor = linkage()->GetIncomingDescriptor();
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) { // Save callee-saved registers.
|
||||
if (!saves.is_empty()) { // Save callee-saved registers.
|
||||
DCHECK(!info()->is_osr());
|
||||
int pushed = 0;
|
||||
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
|
||||
if (!((1 << i) & saves)) continue;
|
||||
++pushed;
|
||||
}
|
||||
frame->AllocateSavedCalleeRegisterSlots(pushed);
|
||||
frame->AllocateSavedCalleeRegisterSlots(saves.Count());
|
||||
}
|
||||
}
|
||||
|
||||
@ -4096,17 +4091,17 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
|
||||
// Skip callee-saved and return slots, which are created below.
|
||||
required_slots -= base::bits::CountPopulation(saves);
|
||||
required_slots -= saves.Count();
|
||||
required_slots -= frame()->GetReturnSlotCount();
|
||||
if (required_slots > 0) {
|
||||
__ AllocateStackSpace(required_slots * kSystemPointerSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (saves != 0) { // Save callee-saved registers.
|
||||
if (!saves.is_empty()) { // Save callee-saved registers.
|
||||
DCHECK(!info()->is_osr());
|
||||
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
|
||||
if (((1 << i) & saves)) __ push(Register::from_code(i));
|
||||
for (Register reg : base::Reversed(saves)) {
|
||||
__ push(reg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4121,14 +4116,13 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
// Restore registers.
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
const int returns = frame()->GetReturnSlotCount();
|
||||
if (returns != 0) {
|
||||
__ add(esp, Immediate(returns * kSystemPointerSize));
|
||||
}
|
||||
for (int i = 0; i < Register::kNumRegisters; i++) {
|
||||
if (!((1 << i) & saves)) continue;
|
||||
__ pop(Register::from_code(i));
|
||||
for (Register reg : saves) {
|
||||
__ pop(reg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4172,7 +4166,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
if (drop_jsargs) {
|
||||
// Get the actual argument count.
|
||||
__ mov(argc_reg, Operand(ebp, StandardFrameConstants::kArgCOffset));
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
|
||||
}
|
||||
AssembleDeconstructFrame();
|
||||
}
|
||||
@ -4185,8 +4179,8 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
Label mismatch_return;
|
||||
Register scratch_reg = edx;
|
||||
DCHECK_NE(argc_reg, scratch_reg);
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & scratch_reg.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(scratch_reg));
|
||||
__ cmp(argc_reg, Immediate(parameter_slots));
|
||||
__ j(greater, &mismatch_return, Label::kNear);
|
||||
__ Ret(parameter_slots * kSystemPointerSize, scratch_reg);
|
||||
@ -4204,16 +4198,15 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
__ ret(static_cast<int>(pop_size));
|
||||
} else {
|
||||
Register scratch_reg = ecx;
|
||||
DCHECK_EQ(0u,
|
||||
call_descriptor->CalleeSavedRegisters() & scratch_reg.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(scratch_reg));
|
||||
CHECK_LE(pop_size, static_cast<size_t>(std::numeric_limits<int>::max()));
|
||||
__ Ret(static_cast<int>(pop_size), scratch_reg);
|
||||
}
|
||||
} else {
|
||||
Register pop_reg = g.ToRegister(additional_pop_count);
|
||||
Register scratch_reg = pop_reg == ecx ? edx : ecx;
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & scratch_reg.bit());
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & pop_reg.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(scratch_reg));
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(pop_reg));
|
||||
int pop_size = static_cast<int>(parameter_slots * kSystemPointerSize);
|
||||
__ PopReturnAddressTo(scratch_reg);
|
||||
__ lea(esp, Operand(esp, pop_reg, times_system_pointer_size,
|
||||
|
@ -2181,7 +2181,7 @@ void CodeGenerator::AssembleArchSelect(Instruction* instr,
|
||||
void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
auto call_descriptor = linkage()->GetIncomingDescriptor();
|
||||
|
||||
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (saves_fpu != 0) {
|
||||
int count = base::bits::CountPopulation(saves_fpu);
|
||||
DCHECK_EQ(kNumCalleeSavedFPU, count);
|
||||
@ -2190,8 +2190,8 @@ void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
}
|
||||
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) {
|
||||
int count = base::bits::CountPopulation(saves);
|
||||
if (!saves.is_empty()) {
|
||||
int count = saves.Count();
|
||||
frame->AllocateSavedCalleeRegisterSlots(count);
|
||||
}
|
||||
}
|
||||
@ -2249,7 +2249,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
}
|
||||
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
|
||||
if (required_slots > 0) {
|
||||
DCHECK(frame_access_state()->has_frame());
|
||||
@ -2293,7 +2293,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
const int returns = frame()->GetReturnSlotCount();
|
||||
|
||||
// Skip callee-saved and return slots, which are pushed below.
|
||||
required_slots -= base::bits::CountPopulation(saves);
|
||||
required_slots -= saves.Count();
|
||||
required_slots -= base::bits::CountPopulation(saves_fpu);
|
||||
required_slots -= returns;
|
||||
if (required_slots > 0) {
|
||||
@ -2306,7 +2306,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
DCHECK_EQ(kNumCalleeSavedFPU, base::bits::CountPopulation(saves_fpu));
|
||||
}
|
||||
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
// Save callee-saved registers.
|
||||
__ MultiPush(saves);
|
||||
}
|
||||
@ -2327,12 +2327,12 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
|
||||
// Restore GP registers.
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
__ MultiPop(saves);
|
||||
}
|
||||
|
||||
// Restore FPU registers.
|
||||
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (saves_fpu != 0) {
|
||||
__ MultiPopFPU(saves_fpu);
|
||||
}
|
||||
|
@ -3934,7 +3934,7 @@ void CodeGenerator::AssembleArchSelect(Instruction* instr,
|
||||
void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
auto call_descriptor = linkage()->GetIncomingDescriptor();
|
||||
|
||||
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (saves_fpu != 0) {
|
||||
frame->AlignSavedCalleeRegisterSlots();
|
||||
}
|
||||
@ -3947,8 +3947,8 @@ void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
}
|
||||
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) {
|
||||
int count = base::bits::CountPopulation(saves);
|
||||
if (!saves.is_empty()) {
|
||||
int count = saves.Count();
|
||||
frame->AllocateSavedCalleeRegisterSlots(count);
|
||||
}
|
||||
}
|
||||
@ -4005,7 +4005,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
}
|
||||
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
|
||||
if (required_slots > 0) {
|
||||
DCHECK(frame_access_state()->has_frame());
|
||||
@ -4046,7 +4046,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
const int returns = frame()->GetReturnSlotCount();
|
||||
|
||||
// Skip callee-saved and return slots, which are pushed below.
|
||||
required_slots -= base::bits::CountPopulation(saves);
|
||||
required_slots -= saves.Count();
|
||||
required_slots -= 2 * base::bits::CountPopulation(saves_fpu);
|
||||
required_slots -= returns;
|
||||
if (required_slots > 0) {
|
||||
@ -4058,7 +4058,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
__ MultiPushFPU(saves_fpu);
|
||||
}
|
||||
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
// Save callee-saved registers.
|
||||
__ MultiPush(saves);
|
||||
}
|
||||
@ -4079,12 +4079,12 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
|
||||
// Restore GP registers.
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
__ MultiPop(saves);
|
||||
}
|
||||
|
||||
// Restore FPU registers.
|
||||
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (saves_fpu != 0) {
|
||||
__ MultiPopFPU(saves_fpu);
|
||||
}
|
||||
|
@ -4139,7 +4139,7 @@ void CodeGenerator::AssembleArchSelect(Instruction* instr,
|
||||
void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
auto call_descriptor = linkage()->GetIncomingDescriptor();
|
||||
|
||||
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (saves_fpu != 0) {
|
||||
int count = base::bits::CountPopulation(saves_fpu);
|
||||
DCHECK_EQ(kNumCalleeSavedFPU, count);
|
||||
@ -4148,8 +4148,8 @@ void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
}
|
||||
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) {
|
||||
int count = base::bits::CountPopulation(saves);
|
||||
if (!saves.is_empty()) {
|
||||
int count = saves.Count();
|
||||
frame->AllocateSavedCalleeRegisterSlots(count);
|
||||
}
|
||||
}
|
||||
@ -4207,7 +4207,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
}
|
||||
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
|
||||
if (required_slots > 0) {
|
||||
DCHECK(frame_access_state()->has_frame());
|
||||
@ -4248,7 +4248,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
const int returns = frame()->GetReturnSlotCount();
|
||||
|
||||
// Skip callee-saved and return slots, which are pushed below.
|
||||
required_slots -= base::bits::CountPopulation(saves);
|
||||
required_slots -= saves.Count();
|
||||
required_slots -= base::bits::CountPopulation(saves_fpu);
|
||||
required_slots -= returns;
|
||||
if (required_slots > 0) {
|
||||
@ -4261,7 +4261,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
DCHECK_EQ(kNumCalleeSavedFPU, base::bits::CountPopulation(saves_fpu));
|
||||
}
|
||||
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
// Save callee-saved registers.
|
||||
__ MultiPush(saves);
|
||||
}
|
||||
@ -4282,12 +4282,12 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
|
||||
// Restore GP registers.
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
__ MultiPop(saves);
|
||||
}
|
||||
|
||||
// Restore FPU registers.
|
||||
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (saves_fpu != 0) {
|
||||
__ MultiPopFPU(saves_fpu);
|
||||
}
|
||||
|
@ -3983,10 +3983,10 @@ void CodeGenerator::AssembleArchSelect(Instruction* instr,
|
||||
|
||||
void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
auto call_descriptor = linkage()->GetIncomingDescriptor();
|
||||
const RegList double_saves = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList double_saves = call_descriptor->CalleeSavedFPRegisters();
|
||||
|
||||
// Save callee-saved Double registers.
|
||||
if (double_saves != 0) {
|
||||
if (double_ !saves.is_empty()) {
|
||||
frame->AlignSavedCalleeRegisterSlots();
|
||||
DCHECK_EQ(kNumCalleeSavedDoubles,
|
||||
base::bits::CountPopulation(double_saves));
|
||||
@ -3994,11 +3994,11 @@ void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
(kDoubleSize / kSystemPointerSize));
|
||||
}
|
||||
// Save callee-saved registers.
|
||||
const RegList saves = FLAG_enable_embedded_constant_pool
|
||||
? call_descriptor->CalleeSavedRegisters() &
|
||||
~kConstantPoolRegister.bit()
|
||||
: call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) {
|
||||
const RegList saves =
|
||||
FLAG_enable_embedded_constant_pool
|
||||
? call_descriptor->CalleeSavedRegisters() - kConstantPoolRegister
|
||||
: call_descriptor->CalleeSavedRegisters();
|
||||
if (!saves.is_empty()) {
|
||||
// register save area does not include the fp or constant pool pointer.
|
||||
const int num_saves =
|
||||
kNumCalleeSaved - 1 - (FLAG_enable_embedded_constant_pool ? 1 : 0);
|
||||
@ -4068,11 +4068,11 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
required_slots -= osr_helper()->UnoptimizedFrameSlots();
|
||||
}
|
||||
|
||||
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
const RegList saves = FLAG_enable_embedded_constant_pool
|
||||
? call_descriptor->CalleeSavedRegisters() &
|
||||
~kConstantPoolRegister.bit()
|
||||
: call_descriptor->CalleeSavedRegisters();
|
||||
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
const RegList saves =
|
||||
FLAG_enable_embedded_constant_pool
|
||||
? call_descriptor->CalleeSavedRegisters() - kConstantPoolRegister
|
||||
: call_descriptor->CalleeSavedRegisters();
|
||||
|
||||
if (required_slots > 0) {
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
@ -4112,21 +4112,20 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
|
||||
// Skip callee-saved and return slots, which are pushed below.
|
||||
required_slots -= base::bits::CountPopulation(saves);
|
||||
required_slots -= saves.Count();
|
||||
required_slots -= frame()->GetReturnSlotCount();
|
||||
required_slots -= (kDoubleSize / kSystemPointerSize) *
|
||||
base::bits::CountPopulation(saves_fp);
|
||||
required_slots -= (kDoubleSize / kSystemPointerSize) * saves_fp.Count();
|
||||
__ AddS64(sp, sp, Operand(-required_slots * kSystemPointerSize), r0);
|
||||
}
|
||||
|
||||
// Save callee-saved Double registers.
|
||||
if (saves_fp != 0) {
|
||||
if (!saves_fp.is_empty()) {
|
||||
__ MultiPushDoubles(saves_fp);
|
||||
DCHECK_EQ(kNumCalleeSavedDoubles, base::bits::CountPopulation(saves_fp));
|
||||
DCHECK_EQ(kNumCalleeSavedDoubles, saves_fp.Count());
|
||||
}
|
||||
|
||||
// Save callee-saved registers.
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
__ MultiPush(saves);
|
||||
// register save area does not include the fp or constant pool pointer.
|
||||
}
|
||||
@ -4146,24 +4145,24 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
}
|
||||
|
||||
// Restore registers.
|
||||
const RegList saves = FLAG_enable_embedded_constant_pool
|
||||
? call_descriptor->CalleeSavedRegisters() &
|
||||
~kConstantPoolRegister.bit()
|
||||
: call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) {
|
||||
const RegList saves =
|
||||
FLAG_enable_embedded_constant_pool
|
||||
? call_descriptor->CalleeSavedRegisters() - kConstantPoolRegister
|
||||
: call_descriptor->CalleeSavedRegisters();
|
||||
if (!saves.is_empty()) {
|
||||
__ MultiPop(saves);
|
||||
}
|
||||
|
||||
// Restore double registers.
|
||||
const RegList double_saves = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (double_saves != 0) {
|
||||
const DoubleRegList double_saves = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (double_ !saves.is_empty()) {
|
||||
__ MultiPopDoubles(double_saves);
|
||||
}
|
||||
|
||||
unwinding_info_writer_.MarkBlockWillExit();
|
||||
|
||||
// We might need r6 for scratch.
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & r6.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(r6));
|
||||
PPCOperandConverter g(this, nullptr);
|
||||
const int parameter_slots =
|
||||
static_cast<int>(call_descriptor->ParameterSlotCount());
|
||||
@ -4204,7 +4203,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
}
|
||||
if (drop_jsargs) {
|
||||
// Get the actual argument count.
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
|
||||
__ LoadU64(argc_reg, MemOperand(fp, StandardFrameConstants::kArgCOffset));
|
||||
}
|
||||
AssembleDeconstructFrame();
|
||||
|
@ -3850,7 +3850,7 @@ void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {
|
||||
void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
auto call_descriptor = linkage()->GetIncomingDescriptor();
|
||||
|
||||
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (saves_fpu != 0) {
|
||||
int count = base::bits::CountPopulation(saves_fpu);
|
||||
DCHECK_EQ(kNumCalleeSavedFPU, count);
|
||||
@ -3859,8 +3859,8 @@ void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
}
|
||||
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) {
|
||||
int count = base::bits::CountPopulation(saves);
|
||||
if (!saves.is_empty()) {
|
||||
int count = saves.Count();
|
||||
frame->AllocateSavedCalleeRegisterSlots(count);
|
||||
}
|
||||
}
|
||||
@ -3911,7 +3911,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
}
|
||||
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
|
||||
if (required_slots > 0) {
|
||||
DCHECK(frame_access_state()->has_frame());
|
||||
@ -3951,7 +3951,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
const int returns = frame()->GetReturnSlotCount();
|
||||
|
||||
// Skip callee-saved and return slots, which are pushed below.
|
||||
required_slots -= base::bits::CountPopulation(saves);
|
||||
required_slots -= saves.Count();
|
||||
required_slots -= base::bits::CountPopulation(saves_fpu);
|
||||
required_slots -= returns;
|
||||
if (required_slots > 0) {
|
||||
@ -3964,7 +3964,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
DCHECK_EQ(kNumCalleeSavedFPU, base::bits::CountPopulation(saves_fpu));
|
||||
}
|
||||
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
// Save callee-saved registers.
|
||||
__ MultiPush(saves);
|
||||
}
|
||||
@ -3985,12 +3985,12 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
|
||||
// Restore GP registers.
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
__ MultiPop(saves);
|
||||
}
|
||||
|
||||
// Restore FPU registers.
|
||||
const RegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList saves_fpu = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (saves_fpu != 0) {
|
||||
__ MultiPopFPU(saves_fpu);
|
||||
}
|
||||
|
@ -3359,10 +3359,10 @@ void CodeGenerator::AssembleArchSelect(Instruction* instr,
|
||||
|
||||
void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
auto call_descriptor = linkage()->GetIncomingDescriptor();
|
||||
const RegList double_saves = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList double_saves = call_descriptor->CalleeSavedFPRegisters();
|
||||
|
||||
// Save callee-saved Double registers.
|
||||
if (double_saves != 0) {
|
||||
if (double_ !saves.is_empty()) {
|
||||
frame->AlignSavedCalleeRegisterSlots();
|
||||
DCHECK_EQ(kNumCalleeSavedDoubles,
|
||||
base::bits::CountPopulation(double_saves));
|
||||
@ -3371,7 +3371,7 @@ void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
}
|
||||
// Save callee-saved registers.
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
// register save area does not include the fp or constant pool pointer.
|
||||
const int num_saves = kNumCalleeSaved - 1;
|
||||
frame->AllocateSavedCalleeRegisterSlots(num_saves);
|
||||
@ -3433,7 +3433,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
required_slots -= osr_helper()->UnoptimizedFrameSlots();
|
||||
}
|
||||
|
||||
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
|
||||
if (required_slots > 0) {
|
||||
@ -3473,21 +3473,20 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
|
||||
// Skip callee-saved and return slots, which are pushed below.
|
||||
required_slots -= base::bits::CountPopulation(saves);
|
||||
required_slots -= saves.Count();
|
||||
required_slots -= frame()->GetReturnSlotCount();
|
||||
required_slots -= (kDoubleSize / kSystemPointerSize) *
|
||||
base::bits::CountPopulation(saves_fp);
|
||||
required_slots -= (kDoubleSize / kSystemPointerSize) * saves_fp.Count();
|
||||
__ lay(sp, MemOperand(sp, -required_slots * kSystemPointerSize));
|
||||
}
|
||||
|
||||
// Save callee-saved Double registers.
|
||||
if (saves_fp != 0) {
|
||||
if (!saves_fp.is_empty()) {
|
||||
__ MultiPushDoubles(saves_fp);
|
||||
DCHECK_EQ(kNumCalleeSavedDoubles, base::bits::CountPopulation(saves_fp));
|
||||
DCHECK_EQ(kNumCalleeSavedDoubles, saves_fp.Count());
|
||||
}
|
||||
|
||||
// Save callee-saved registers.
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
__ MultiPush(saves);
|
||||
// register save area does not include the fp or constant pool pointer.
|
||||
}
|
||||
@ -3508,20 +3507,20 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
|
||||
// Restore registers.
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
__ MultiPop(saves);
|
||||
}
|
||||
|
||||
// Restore double registers.
|
||||
const RegList double_saves = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (double_saves != 0) {
|
||||
const DoubleRegList double_saves = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (double_ !saves.is_empty()) {
|
||||
__ MultiPopDoubles(double_saves);
|
||||
}
|
||||
|
||||
unwinding_info_writer_.MarkBlockWillExit();
|
||||
|
||||
// We might need r3 for scratch.
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & r5.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(r5));
|
||||
S390OperandConverter g(this, nullptr);
|
||||
const int parameter_slots =
|
||||
static_cast<int>(call_descriptor->ParameterSlotCount());
|
||||
@ -3562,7 +3561,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
}
|
||||
if (drop_jsargs) {
|
||||
// Get the actual argument count.
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
|
||||
__ LoadU64(argc_reg, MemOperand(fp, StandardFrameConstants::kArgCOffset));
|
||||
}
|
||||
AssembleDeconstructFrame();
|
||||
|
@ -1076,8 +1076,9 @@ void AdjustStackPointerForTailCall(Instruction* instr,
|
||||
// value before frame construction.
|
||||
// See also: AssembleConstructFrame.
|
||||
DCHECK(!info->is_osr());
|
||||
DCHECK_EQ(linkage->GetIncomingDescriptor()->CalleeSavedRegisters(), 0);
|
||||
DCHECK_EQ(linkage->GetIncomingDescriptor()->CalleeSavedFPRegisters(), 0);
|
||||
DCHECK(linkage->GetIncomingDescriptor()->CalleeSavedRegisters().is_empty());
|
||||
DCHECK(
|
||||
linkage->GetIncomingDescriptor()->CalleeSavedFPRegisters().is_empty());
|
||||
DCHECK_EQ(state->frame()->GetReturnSlotCount(), 0);
|
||||
stack_slot_delta = (state->frame()->GetTotalFrameSlotCount() -
|
||||
kReturnAddressStackSlotCount) *
|
||||
@ -4580,22 +4581,16 @@ static const int kQuadWordSize = 16;
|
||||
void CodeGenerator::FinishFrame(Frame* frame) {
|
||||
CallDescriptor* call_descriptor = linkage()->GetIncomingDescriptor();
|
||||
|
||||
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (saves_fp != 0) { // Save callee-saved XMM registers.
|
||||
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (!saves_fp.is_empty()) { // Save callee-saved XMM registers.
|
||||
frame->AlignSavedCalleeRegisterSlots();
|
||||
const uint32_t saves_fp_count = base::bits::CountPopulation(saves_fp);
|
||||
const uint32_t saves_fp_count = saves_fp.Count();
|
||||
frame->AllocateSavedCalleeRegisterSlots(
|
||||
saves_fp_count * (kQuadWordSize / kSystemPointerSize));
|
||||
}
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) { // Save callee-saved registers.
|
||||
int count = 0;
|
||||
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
|
||||
if (((1 << i) & saves)) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
frame->AllocateSavedCalleeRegisterSlots(count);
|
||||
if (!saves.is_empty()) { // Save callee-saved registers.
|
||||
frame->AllocateSavedCalleeRegisterSlots(saves.Count());
|
||||
}
|
||||
}
|
||||
|
||||
@ -4654,7 +4649,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
}
|
||||
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
|
||||
if (required_slots > 0) {
|
||||
DCHECK(frame_access_state()->has_frame());
|
||||
@ -4692,34 +4687,30 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
|
||||
// Skip callee-saved and return slots, which are created below.
|
||||
required_slots -= base::bits::CountPopulation(saves);
|
||||
required_slots -= base::bits::CountPopulation(saves_fp) *
|
||||
(kQuadWordSize / kSystemPointerSize);
|
||||
required_slots -= saves.Count();
|
||||
required_slots -= saves_fp.Count() * (kQuadWordSize / kSystemPointerSize);
|
||||
required_slots -= frame()->GetReturnSlotCount();
|
||||
if (required_slots > 0) {
|
||||
__ AllocateStackSpace(required_slots * kSystemPointerSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (saves_fp != 0) { // Save callee-saved XMM registers.
|
||||
const uint32_t saves_fp_count = base::bits::CountPopulation(saves_fp);
|
||||
if (!saves_fp.is_empty()) { // Save callee-saved XMM registers.
|
||||
const uint32_t saves_fp_count = saves_fp.Count();
|
||||
const int stack_size = saves_fp_count * kQuadWordSize;
|
||||
// Adjust the stack pointer.
|
||||
__ AllocateStackSpace(stack_size);
|
||||
// Store the registers on the stack.
|
||||
int slot_idx = 0;
|
||||
for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
|
||||
if (!((1 << i) & saves_fp)) continue;
|
||||
__ Movdqu(Operand(rsp, kQuadWordSize * slot_idx),
|
||||
XMMRegister::from_code(i));
|
||||
for (XMMRegister reg : saves_fp) {
|
||||
__ Movdqu(Operand(rsp, kQuadWordSize * slot_idx), reg);
|
||||
slot_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
if (saves != 0) { // Save callee-saved registers.
|
||||
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
|
||||
if (!((1 << i) & saves)) continue;
|
||||
__ pushq(Register::from_code(i));
|
||||
if (!saves.is_empty()) { // Save callee-saved registers.
|
||||
for (Register reg : base::Reversed(saves)) {
|
||||
__ pushq(reg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4734,26 +4725,23 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
|
||||
// Restore registers.
|
||||
const RegList saves = call_descriptor->CalleeSavedRegisters();
|
||||
if (saves != 0) {
|
||||
if (!saves.is_empty()) {
|
||||
const int returns = frame()->GetReturnSlotCount();
|
||||
if (returns != 0) {
|
||||
__ addq(rsp, Immediate(returns * kSystemPointerSize));
|
||||
}
|
||||
for (int i = 0; i < Register::kNumRegisters; i++) {
|
||||
if (!((1 << i) & saves)) continue;
|
||||
__ popq(Register::from_code(i));
|
||||
for (Register reg : saves) {
|
||||
__ popq(reg);
|
||||
}
|
||||
}
|
||||
const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (saves_fp != 0) {
|
||||
const uint32_t saves_fp_count = base::bits::CountPopulation(saves_fp);
|
||||
const DoubleRegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
|
||||
if (!saves_fp.is_empty()) {
|
||||
const uint32_t saves_fp_count = saves_fp.Count();
|
||||
const int stack_size = saves_fp_count * kQuadWordSize;
|
||||
// Load the registers from the stack.
|
||||
int slot_idx = 0;
|
||||
for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
|
||||
if (!((1 << i) & saves_fp)) continue;
|
||||
__ Movdqu(XMMRegister::from_code(i),
|
||||
Operand(rsp, kQuadWordSize * slot_idx));
|
||||
for (XMMRegister reg : saves_fp) {
|
||||
__ Movdqu(reg, Operand(rsp, kQuadWordSize * slot_idx));
|
||||
slot_idx++;
|
||||
}
|
||||
// Adjust the stack pointer.
|
||||
@ -4799,7 +4787,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
}
|
||||
if (drop_jsargs) {
|
||||
// Get the actual argument count.
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
|
||||
__ movq(argc_reg, Operand(rbp, StandardFrameConstants::kArgCOffset));
|
||||
}
|
||||
AssembleDeconstructFrame();
|
||||
@ -4813,8 +4801,8 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
Label mismatch_return;
|
||||
Register scratch_reg = r10;
|
||||
DCHECK_NE(argc_reg, scratch_reg);
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & scratch_reg.bit());
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & argc_reg.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(scratch_reg));
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(argc_reg));
|
||||
__ cmpq(argc_reg, Immediate(parameter_slots));
|
||||
__ j(greater, &mismatch_return, Label::kNear);
|
||||
__ Ret(parameter_slots * kSystemPointerSize, scratch_reg);
|
||||
@ -4825,7 +4813,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
__ Ret();
|
||||
} else if (additional_pop_count->IsImmediate()) {
|
||||
Register scratch_reg = r10;
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & scratch_reg.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(scratch_reg));
|
||||
int additional_count = g.ToConstant(additional_pop_count).ToInt32();
|
||||
size_t pop_size = (parameter_slots + additional_count) * kSystemPointerSize;
|
||||
CHECK_LE(pop_size, static_cast<size_t>(std::numeric_limits<int>::max()));
|
||||
@ -4833,8 +4821,8 @@ void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
|
||||
} else {
|
||||
Register pop_reg = g.ToRegister(additional_pop_count);
|
||||
Register scratch_reg = pop_reg == r10 ? rcx : r10;
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & scratch_reg.bit());
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & pop_reg.bit());
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(scratch_reg));
|
||||
DCHECK(!call_descriptor->CalleeSavedRegisters().has(pop_reg));
|
||||
int pop_size = static_cast<int>(parameter_slots * kSystemPointerSize);
|
||||
__ PopReturnAddressTo(scratch_reg);
|
||||
__ leaq(rsp, Operand(rsp, pop_reg, times_system_pointer_size,
|
||||
|
@ -19,7 +19,8 @@ namespace {
|
||||
// ===========================================================================
|
||||
// == ia32 ===================================================================
|
||||
// ===========================================================================
|
||||
#define CALLEE_SAVE_REGISTERS esi.bit() | edi.bit() | ebx.bit()
|
||||
#define CALLEE_SAVE_REGISTERS esi, edi, ebx
|
||||
#define CALLEE_SAVE_FP_REGISTERS
|
||||
|
||||
#elif V8_TARGET_ARCH_X64
|
||||
// ===========================================================================
|
||||
@ -32,21 +33,17 @@ namespace {
|
||||
#define PARAM_REGISTERS rcx, rdx, r8, r9
|
||||
#define FP_PARAM_REGISTERS xmm0, xmm1, xmm2, xmm3
|
||||
#define FP_RETURN_REGISTER xmm0
|
||||
#define CALLEE_SAVE_REGISTERS \
|
||||
rbx.bit() | rdi.bit() | rsi.bit() | r12.bit() | r13.bit() | r14.bit() | \
|
||||
r15.bit()
|
||||
#define CALLEE_SAVE_FP_REGISTERS \
|
||||
(1 << xmm6.code()) | (1 << xmm7.code()) | (1 << xmm8.code()) | \
|
||||
(1 << xmm9.code()) | (1 << xmm10.code()) | (1 << xmm11.code()) | \
|
||||
(1 << xmm12.code()) | (1 << xmm13.code()) | (1 << xmm14.code()) | \
|
||||
(1 << xmm15.code())
|
||||
#define CALLEE_SAVE_REGISTERS rbx, rdi, rsi, r12, r13, r14, r15
|
||||
#define CALLEE_SAVE_FP_REGISTERS \
|
||||
xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
|
||||
|
||||
#else // V8_TARGET_OS_WIN
|
||||
// == x64 other ==============================================================
|
||||
#define PARAM_REGISTERS rdi, rsi, rdx, rcx, r8, r9
|
||||
#define FP_PARAM_REGISTERS xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
|
||||
#define FP_RETURN_REGISTER xmm0
|
||||
#define CALLEE_SAVE_REGISTERS \
|
||||
rbx.bit() | r12.bit() | r13.bit() | r14.bit() | r15.bit()
|
||||
#define CALLEE_SAVE_REGISTERS rbx, r12, r13, r14, r15
|
||||
#define CALLEE_SAVE_FP_REGISTERS
|
||||
#endif // V8_TARGET_OS_WIN
|
||||
|
||||
#elif V8_TARGET_ARCH_ARM
|
||||
@ -54,12 +51,8 @@ namespace {
|
||||
// == arm ====================================================================
|
||||
// ===========================================================================
|
||||
#define PARAM_REGISTERS r0, r1, r2, r3
|
||||
#define CALLEE_SAVE_REGISTERS \
|
||||
r4.bit() | r5.bit() | r6.bit() | r7.bit() | r8.bit() | r9.bit() | r10.bit()
|
||||
#define CALLEE_SAVE_FP_REGISTERS \
|
||||
(1 << d8.code()) | (1 << d9.code()) | (1 << d10.code()) | \
|
||||
(1 << d11.code()) | (1 << d12.code()) | (1 << d13.code()) | \
|
||||
(1 << d14.code()) | (1 << d15.code())
|
||||
#define CALLEE_SAVE_REGISTERS r4, r5, r6, r7, r8, r9, r10
|
||||
#define CALLEE_SAVE_FP_REGISTERS d8, d9, d10, d11, d12, d13, d14, d15
|
||||
|
||||
#elif V8_TARGET_ARCH_ARM64
|
||||
// ===========================================================================
|
||||
@ -68,16 +61,9 @@ namespace {
|
||||
#define PARAM_REGISTERS x0, x1, x2, x3, x4, x5, x6, x7
|
||||
#define FP_PARAM_REGISTERS d0, d1, d2, d3, d4, d5, d6, d7
|
||||
#define FP_RETURN_REGISTER d0
|
||||
#define CALLEE_SAVE_REGISTERS \
|
||||
(1 << x19.code()) | (1 << x20.code()) | (1 << x21.code()) | \
|
||||
(1 << x22.code()) | (1 << x23.code()) | (1 << x24.code()) | \
|
||||
(1 << x25.code()) | (1 << x26.code()) | (1 << x27.code()) | \
|
||||
(1 << x28.code())
|
||||
#define CALLEE_SAVE_REGISTERS x19, x20, x21, x22, x23, x24, x25, x26, x27, x28
|
||||
|
||||
#define CALLEE_SAVE_FP_REGISTERS \
|
||||
(1 << d8.code()) | (1 << d9.code()) | (1 << d10.code()) | \
|
||||
(1 << d11.code()) | (1 << d12.code()) | (1 << d13.code()) | \
|
||||
(1 << d14.code()) | (1 << d15.code())
|
||||
#define CALLEE_SAVE_FP_REGISTERS d8, d9, d10, d11, d12, d13, d14, d15
|
||||
|
||||
#elif V8_TARGET_ARCH_MIPS
|
||||
// ===========================================================================
|
||||
@ -85,34 +71,24 @@ namespace {
|
||||
// ===========================================================================
|
||||
#define STACK_SHADOW_WORDS 4
|
||||
#define PARAM_REGISTERS a0, a1, a2, a3
|
||||
#define CALLEE_SAVE_REGISTERS \
|
||||
s0.bit() | s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() | s6.bit() | \
|
||||
s7.bit()
|
||||
#define CALLEE_SAVE_FP_REGISTERS \
|
||||
f20.bit() | f22.bit() | f24.bit() | f26.bit() | f28.bit() | f30.bit()
|
||||
#define CALLEE_SAVE_REGISTERS s0, s1, s2, s3, s4, s5, s6, s7
|
||||
#define CALLEE_SAVE_FP_REGISTERS f20, f22, f24, f26, f28, f30
|
||||
|
||||
#elif V8_TARGET_ARCH_MIPS64
|
||||
// ===========================================================================
|
||||
// == mips64 =================================================================
|
||||
// ===========================================================================
|
||||
#define PARAM_REGISTERS a0, a1, a2, a3, a4, a5, a6, a7
|
||||
#define CALLEE_SAVE_REGISTERS \
|
||||
s0.bit() | s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() | s6.bit() | \
|
||||
s7.bit()
|
||||
#define CALLEE_SAVE_FP_REGISTERS \
|
||||
f20.bit() | f22.bit() | f24.bit() | f26.bit() | f28.bit() | f30.bit()
|
||||
#define CALLEE_SAVE_REGISTERS s0, s1, s2, s3, s4, s5, s6, s7
|
||||
#define CALLEE_SAVE_FP_REGISTERS f20, f22, f24, f26, f28, f30
|
||||
|
||||
#elif V8_TARGET_ARCH_LOONG64
|
||||
// ===========================================================================
|
||||
// == loong64 ================================================================
|
||||
// ===========================================================================
|
||||
#define PARAM_REGISTERS a0, a1, a2, a3, a4, a5, a6, a7
|
||||
#define CALLEE_SAVE_REGISTERS \
|
||||
s0.bit() | s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() | s6.bit() | \
|
||||
s7.bit() | s8.bit() | fp.bit()
|
||||
#define CALLEE_SAVE_FP_REGISTERS \
|
||||
f24.bit() | f25.bit() | f26.bit() | f27.bit() | f28.bit() | f29.bit() | \
|
||||
f30.bit() | f31.bit()
|
||||
#define CALLEE_SAVE_REGISTERS s0, s1, s2, s3, s4, s5, s6, s7, s8, fp
|
||||
#define CALLEE_SAVE_FP_REGISTERS f24, f25, f26, f27, f28, f29, f30, f31
|
||||
|
||||
#elif V8_TARGET_ARCH_PPC64
|
||||
// ===========================================================================
|
||||
@ -124,14 +100,13 @@ namespace {
|
||||
#define STACK_SHADOW_WORDS 14
|
||||
#endif
|
||||
#define PARAM_REGISTERS r3, r4, r5, r6, r7, r8, r9, r10
|
||||
#define CALLEE_SAVE_REGISTERS \
|
||||
r14.bit() | r15.bit() | r16.bit() | r17.bit() | r18.bit() | r19.bit() | \
|
||||
r20.bit() | r21.bit() | r22.bit() | r23.bit() | r24.bit() | r25.bit() | \
|
||||
r26.bit() | r27.bit() | r28.bit() | r29.bit() | r30.bit()
|
||||
#define CALLEE_SAVE_FP_REGISTERS \
|
||||
d14.bit() | d15.bit() | d16.bit() | d17.bit() | d18.bit() | d19.bit() | \
|
||||
d20.bit() | d21.bit() | d22.bit() | d23.bit() | d24.bit() | d25.bit() | \
|
||||
d26.bit() | d27.bit() | d28.bit() | d29.bit() | d30.bit() | d31.bit()
|
||||
#define CALLEE_SAVE_REGISTERS \
|
||||
r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, \
|
||||
r29, r30
|
||||
|
||||
#define CALLEE_SAVE_FP_REGISTERS \
|
||||
d14, d15, d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, \
|
||||
d29, d30, d31
|
||||
|
||||
#elif V8_TARGET_ARCH_S390X
|
||||
// ===========================================================================
|
||||
@ -139,11 +114,8 @@ namespace {
|
||||
// ===========================================================================
|
||||
#define STACK_SHADOW_WORDS 20
|
||||
#define PARAM_REGISTERS r2, r3, r4, r5, r6
|
||||
#define CALLEE_SAVE_REGISTERS \
|
||||
r6.bit() | r7.bit() | r8.bit() | r9.bit() | r10.bit() | ip.bit() | r13.bit()
|
||||
#define CALLEE_SAVE_FP_REGISTERS \
|
||||
d8.bit() | d9.bit() | d10.bit() | d11.bit() | d12.bit() | d13.bit() | \
|
||||
d14.bit() | d15.bit()
|
||||
#define CALLEE_SAVE_REGISTERS r6, r7, r8, r9, r10, ip, r13
|
||||
#define CALLEE_SAVE_FP_REGISTERS d8, d9, d10, d11, d12, d13, d14, d15
|
||||
|
||||
#elif V8_TARGET_ARCH_RISCV64
|
||||
// ===========================================================================
|
||||
@ -152,12 +124,9 @@ namespace {
|
||||
#define PARAM_REGISTERS a0, a1, a2, a3, a4, a5, a6, a7
|
||||
// fp is not part of CALLEE_SAVE_REGISTERS (similar to how MIPS64 or PPC defines
|
||||
// it)
|
||||
#define CALLEE_SAVE_REGISTERS \
|
||||
s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() | s6.bit() | s7.bit() | \
|
||||
s8.bit() | s9.bit() | s10.bit() | s11.bit()
|
||||
#define CALLEE_SAVE_FP_REGISTERS \
|
||||
fs0.bit() | fs1.bit() | fs2.bit() | fs3.bit() | fs4.bit() | fs5.bit() | \
|
||||
fs6.bit() | fs7.bit() | fs8.bit() | fs9.bit() | fs10.bit() | fs11.bit()
|
||||
#define CALLEE_SAVE_REGISTERS s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11
|
||||
#define CALLEE_SAVE_FP_REGISTERS \
|
||||
fs0, fs1, fs2, fs3, fs4, fs5, fs6, fs7, fs8, fs9, fs10, fs11
|
||||
#else
|
||||
// ===========================================================================
|
||||
// == unknown ================================================================
|
||||
@ -318,17 +287,8 @@ CallDescriptor* Linkage::GetSimplifiedCDescriptor(Zone* zone,
|
||||
BuildParameterLocations(msig, kFPParamRegisterCount, kParamRegisterCount,
|
||||
kFPParamRegisters, kParamRegisters, &locations);
|
||||
|
||||
#ifdef CALLEE_SAVE_REGISTERS
|
||||
const RegList kCalleeSaveRegisters = CALLEE_SAVE_REGISTERS;
|
||||
#else
|
||||
const RegList kCalleeSaveRegisters = 0;
|
||||
#endif
|
||||
|
||||
#ifdef CALLEE_SAVE_FP_REGISTERS
|
||||
const RegList kCalleeSaveFPRegisters = CALLEE_SAVE_FP_REGISTERS;
|
||||
#else
|
||||
const RegList kCalleeSaveFPRegisters = 0;
|
||||
#endif
|
||||
const RegList kCalleeSaveRegisters = {CALLEE_SAVE_REGISTERS};
|
||||
const DoubleRegList kCalleeSaveFPRegisters = {CALLEE_SAVE_FP_REGISTERS};
|
||||
|
||||
// The target for C calls is always an address (i.e. machine pointer).
|
||||
MachineType target_type = MachineType::Pointer();
|
||||
|
@ -372,7 +372,7 @@ CallDescriptor* Linkage::GetCEntryStubCallDescriptor(
|
||||
js_parameter_count, // stack_parameter_count
|
||||
properties, // properties
|
||||
kNoCalleeSaved, // callee-saved
|
||||
kNoCalleeSaved, // callee-saved fp
|
||||
kNoCalleeSavedFp, // callee-saved fp
|
||||
flags, // flags
|
||||
debug_name, // debug name
|
||||
stack_order); // stack order
|
||||
@ -426,7 +426,7 @@ CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr,
|
||||
js_parameter_count, // stack_parameter_count
|
||||
Operator::kNoProperties, // properties
|
||||
kNoCalleeSaved, // callee-saved
|
||||
kNoCalleeSaved, // callee-saved fp
|
||||
kNoCalleeSavedFp, // callee-saved fp
|
||||
flags, // flags
|
||||
"js-call"); // debug name
|
||||
}
|
||||
@ -522,7 +522,7 @@ CallDescriptor* Linkage::GetStubCallDescriptor(
|
||||
RegList callee_saved_registers = kNoCalleeSaved;
|
||||
if (descriptor.CalleeSaveRegisters()) {
|
||||
callee_saved_registers = allocatable_registers;
|
||||
DCHECK(callee_saved_registers);
|
||||
DCHECK(!callee_saved_registers.is_empty());
|
||||
}
|
||||
LinkageLocation target_loc = LinkageLocation::ForAnyRegister(target_type);
|
||||
return zone->New<CallDescriptor>( // --
|
||||
@ -533,7 +533,7 @@ CallDescriptor* Linkage::GetStubCallDescriptor(
|
||||
stack_parameter_count, // stack_parameter_count
|
||||
properties, // properties
|
||||
callee_saved_registers, // callee-saved registers
|
||||
kNoCalleeSaved, // callee-saved fp
|
||||
kNoCalleeSavedFp, // callee-saved fp
|
||||
CallDescriptor::kCanUseRoots | flags, // flags
|
||||
descriptor.DebugName(), // debug name
|
||||
descriptor.GetStackArgumentOrder(), // stack order
|
||||
@ -583,7 +583,7 @@ CallDescriptor* Linkage::GetBytecodeDispatchCallDescriptor(
|
||||
stack_parameter_count, // stack_parameter_count
|
||||
Operator::kNoProperties, // properties
|
||||
kNoCalleeSaved, // callee-saved registers
|
||||
kNoCalleeSaved, // callee-saved fp
|
||||
kNoCalleeSavedFp, // callee-saved fp
|
||||
kFlags, // flags
|
||||
descriptor.DebugName());
|
||||
}
|
||||
|
@ -36,7 +36,8 @@ class OptimizedCompilationInfo;
|
||||
|
||||
namespace compiler {
|
||||
|
||||
const RegList kNoCalleeSaved = 0;
|
||||
constexpr RegList kNoCalleeSaved;
|
||||
constexpr DoubleRegList kNoCalleeSavedFp;
|
||||
|
||||
class OsrHelper;
|
||||
|
||||
@ -253,13 +254,13 @@ class V8_EXPORT_PRIVATE CallDescriptor final
|
||||
LocationSignature* location_sig, size_t param_slot_count,
|
||||
Operator::Properties properties,
|
||||
RegList callee_saved_registers,
|
||||
RegList callee_saved_fp_registers, Flags flags,
|
||||
DoubleRegList callee_saved_fp_registers, Flags flags,
|
||||
const char* debug_name = "",
|
||||
StackArgumentOrder stack_order = StackArgumentOrder::kDefault,
|
||||
#if V8_ENABLE_WEBASSEMBLY
|
||||
const wasm::FunctionSig* wasm_sig = nullptr,
|
||||
#endif
|
||||
const RegList allocatable_registers = 0,
|
||||
const RegList allocatable_registers = {},
|
||||
size_t return_slot_count = 0)
|
||||
: kind_(kind),
|
||||
target_type_(target_type),
|
||||
@ -414,7 +415,9 @@ class V8_EXPORT_PRIVATE CallDescriptor final
|
||||
RegList CalleeSavedRegisters() const { return callee_saved_registers_; }
|
||||
|
||||
// Get the callee-saved FP registers, if any, across this call.
|
||||
RegList CalleeSavedFPRegisters() const { return callee_saved_fp_registers_; }
|
||||
DoubleRegList CalleeSavedFPRegisters() const {
|
||||
return callee_saved_fp_registers_;
|
||||
}
|
||||
|
||||
const char* debug_name() const { return debug_name_; }
|
||||
|
||||
@ -443,7 +446,7 @@ class V8_EXPORT_PRIVATE CallDescriptor final
|
||||
RegList AllocatableRegisters() const { return allocatable_registers_; }
|
||||
|
||||
bool HasRestrictedAllocatableRegisters() const {
|
||||
return allocatable_registers_ != 0;
|
||||
return !allocatable_registers_.is_empty();
|
||||
}
|
||||
|
||||
EncodedCSignature ToEncodedCSignature() const;
|
||||
@ -461,7 +464,7 @@ class V8_EXPORT_PRIVATE CallDescriptor final
|
||||
const size_t return_slot_count_;
|
||||
const Operator::Properties properties_;
|
||||
const RegList callee_saved_registers_;
|
||||
const RegList callee_saved_fp_registers_;
|
||||
const DoubleRegList callee_saved_fp_registers_;
|
||||
// Non-zero value means restricting the set of allocatable registers for
|
||||
// register allocator to use.
|
||||
const RegList allocatable_registers_;
|
||||
|
@ -503,7 +503,7 @@ class PipelineData {
|
||||
if (call_descriptor && call_descriptor->RequiresFrameAsIncoming()) {
|
||||
sequence_->instruction_blocks()[0]->mark_needs_frame();
|
||||
} else {
|
||||
DCHECK_EQ(0u, call_descriptor->CalleeSavedFPRegisters());
|
||||
DCHECK(call_descriptor->CalleeSavedFPRegisters().is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
@ -3474,7 +3474,7 @@ bool PipelineImpl::SelectInstructions(Linkage* linkage) {
|
||||
|
||||
if (call_descriptor->HasRestrictedAllocatableRegisters()) {
|
||||
RegList registers = call_descriptor->AllocatableRegisters();
|
||||
DCHECK_LT(0, NumRegs(registers));
|
||||
DCHECK_LT(0, registers.Count());
|
||||
restricted_config.reset(
|
||||
RegisterConfiguration::RestrictGeneralRegisters(registers));
|
||||
config = restricted_config.get();
|
||||
|
@ -8606,8 +8606,8 @@ CallDescriptor* GetWasmCallDescriptor(Zone* zone, const wasm::FunctionSig* fsig,
|
||||
|
||||
int return_slots = rets.NumStackSlots();
|
||||
|
||||
const RegList kCalleeSaveRegisters = 0;
|
||||
const RegList kCalleeSaveFPRegisters = 0;
|
||||
const RegList kCalleeSaveRegisters;
|
||||
const DoubleRegList kCalleeSaveFPRegisters;
|
||||
|
||||
// The target for wasm calls is always a code object.
|
||||
MachineType target_type = MachineType::Pointer();
|
||||
@ -8639,7 +8639,7 @@ CallDescriptor* GetWasmCallDescriptor(Zone* zone, const wasm::FunctionSig* fsig,
|
||||
"wasm-call", // debug name
|
||||
StackArgumentOrder::kDefault, // order of the arguments in the stack
|
||||
fsig, // signature
|
||||
0, // allocatable registers
|
||||
RegList{}, // allocatable registers
|
||||
return_slots); // return slot count
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include "src/base/bits.h"
|
||||
#include "src/base/macros.h"
|
||||
#include "src/codegen/arm/register-arm.h"
|
||||
#include "src/codegen/register.h"
|
||||
#include "src/execution/frame-constants.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -77,17 +77,15 @@ class WasmCompileLazyFrameConstants : public TypedFrameConstants {
|
||||
class WasmDebugBreakFrameConstants : public TypedFrameConstants {
|
||||
public:
|
||||
// r10: root, r11: fp, r12: ip, r13: sp, r14: lr, r15: pc.
|
||||
static constexpr RegList kPushedGpRegs =
|
||||
Register::ListOf(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9);
|
||||
static constexpr RegList kPushedGpRegs = {r0, r1, r2, r3, r4,
|
||||
r5, r6, r7, r8, r9};
|
||||
|
||||
// d13: zero, d14-d15: scratch
|
||||
static constexpr RegList kPushedFpRegs = LowDwVfpRegister::ListOf(
|
||||
d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12);
|
||||
static constexpr DoubleRegList kPushedFpRegs = {d0, d1, d2, d3, d4, d5, d6,
|
||||
d7, d8, d9, d10, d11, d12};
|
||||
|
||||
static constexpr int kNumPushedGpRegisters =
|
||||
base::bits::CountPopulation(kPushedGpRegs);
|
||||
static constexpr int kNumPushedFpRegisters =
|
||||
base::bits::CountPopulation(kPushedFpRegs);
|
||||
static constexpr int kNumPushedGpRegisters = kPushedGpRegs.Count();
|
||||
static constexpr int kNumPushedFpRegisters = kPushedFpRegs.Count();
|
||||
|
||||
static constexpr int kLastPushedGpRegisterOffset =
|
||||
-TypedFrameConstants::kFixedFrameSizeFromFp -
|
||||
@ -97,15 +95,17 @@ class WasmDebugBreakFrameConstants : public TypedFrameConstants {
|
||||
|
||||
// Offsets are fp-relative.
|
||||
static int GetPushedGpRegisterOffset(int reg_code) {
|
||||
DCHECK_NE(0, kPushedGpRegs & (1 << reg_code));
|
||||
uint32_t lower_regs = kPushedGpRegs & ((uint32_t{1} << reg_code) - 1);
|
||||
DCHECK_NE(0, kPushedGpRegs.bits() & (1 << reg_code));
|
||||
uint32_t lower_regs =
|
||||
kPushedGpRegs.bits() & ((uint32_t{1} << reg_code) - 1);
|
||||
return kLastPushedGpRegisterOffset +
|
||||
base::bits::CountPopulation(lower_regs) * kSystemPointerSize;
|
||||
}
|
||||
|
||||
static int GetPushedFpRegisterOffset(int reg_code) {
|
||||
DCHECK_NE(0, kPushedFpRegs & (1 << reg_code));
|
||||
uint32_t lower_regs = kPushedFpRegs & ((uint32_t{1} << reg_code) - 1);
|
||||
DCHECK_NE(0, kPushedFpRegs.bits() & (1 << reg_code));
|
||||
uint32_t lower_regs =
|
||||
kPushedFpRegs.bits() & ((uint32_t{1} << reg_code) - 1);
|
||||
return kLastPushedFpRegisterOffset +
|
||||
base::bits::CountPopulation(lower_regs) * kDoubleSize;
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#include "src/base/bits.h"
|
||||
#include "src/base/macros.h"
|
||||
#include "src/codegen/arm64/register-arm64.h"
|
||||
#include "src/codegen/register.h"
|
||||
#include "src/codegen/reglist.h"
|
||||
#include "src/common/globals.h"
|
||||
@ -98,23 +97,21 @@ class WasmDebugBreakFrameConstants : public TypedFrameConstants {
|
||||
public:
|
||||
// x16: ip0, x17: ip1, x18: platform register, x26: root, x28: base, x29: fp,
|
||||
// x30: lr, x31: xzr.
|
||||
static constexpr RegList kPushedGpRegs = CPURegister::ListOf(
|
||||
x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x19,
|
||||
x20, x21, x22, x23, x24, x25, x27);
|
||||
static constexpr RegList kPushedGpRegs = {
|
||||
x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11,
|
||||
x12, x13, x14, x15, x19, x20, x21, x22, x23, x24, x25, x27};
|
||||
|
||||
// We push FpRegs as 128-bit SIMD registers, so 16-byte frame alignment
|
||||
// is guaranteed regardless of register count.
|
||||
static constexpr RegList kPushedFpRegs = CPURegister::ListOf(
|
||||
d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d16, d17,
|
||||
d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29);
|
||||
static constexpr DoubleRegList kPushedFpRegs = {
|
||||
d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14,
|
||||
d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29};
|
||||
|
||||
static constexpr int kNumPushedGpRegisters =
|
||||
base::bits::CountPopulation(kPushedGpRegs);
|
||||
static constexpr int kNumPushedGpRegisters = kPushedGpRegs.Count();
|
||||
static_assert(kNumPushedGpRegisters % 2 == 0,
|
||||
"stack frames need to be 16-byte aligned");
|
||||
|
||||
static constexpr int kNumPushedFpRegisters =
|
||||
base::bits::CountPopulation(kPushedFpRegs);
|
||||
static constexpr int kNumPushedFpRegisters = kPushedFpRegs.Count();
|
||||
|
||||
static constexpr int kLastPushedGpRegisterOffset =
|
||||
// Header is padded to 16 byte (see {MacroAssembler::EnterFrame}).
|
||||
@ -125,15 +122,17 @@ class WasmDebugBreakFrameConstants : public TypedFrameConstants {
|
||||
|
||||
// Offsets are fp-relative.
|
||||
static int GetPushedGpRegisterOffset(int reg_code) {
|
||||
DCHECK_NE(0, kPushedGpRegs & (1 << reg_code));
|
||||
uint32_t lower_regs = kPushedGpRegs & ((uint32_t{1} << reg_code) - 1);
|
||||
DCHECK_NE(0, kPushedGpRegs.bits() & (1 << reg_code));
|
||||
uint32_t lower_regs =
|
||||
kPushedGpRegs.bits() & ((uint32_t{1} << reg_code) - 1);
|
||||
return kLastPushedGpRegisterOffset +
|
||||
base::bits::CountPopulation(lower_regs) * kSystemPointerSize;
|
||||
}
|
||||
|
||||
static int GetPushedFpRegisterOffset(int reg_code) {
|
||||
DCHECK_NE(0, kPushedFpRegs & (1 << reg_code));
|
||||
uint32_t lower_regs = kPushedFpRegs & ((uint32_t{1} << reg_code) - 1);
|
||||
DCHECK_NE(0, kPushedFpRegs.bits() & (1 << reg_code));
|
||||
uint32_t lower_regs =
|
||||
kPushedFpRegs.bits() & ((uint32_t{1} << reg_code) - 1);
|
||||
return kLastPushedFpRegisterOffset +
|
||||
base::bits::CountPopulation(lower_regs) * kSimd128Size;
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ int PopLowestIndexAsCode(CPURegList* list) {
|
||||
if (list->IsEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
RegList reg_list = list->list();
|
||||
uint64_t reg_list = list->bits();
|
||||
int index = base::bits::CountTrailingZeros(reg_list);
|
||||
DCHECK((1LL << index) & reg_list);
|
||||
list->Remove(index);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user