__ mov(fp, sp);
saved_pp = false;
}
+ int register_save_area_size = saved_pp ? kPointerSize : 0;
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0 || saved_pp) {
// Save callee-saved registers.
- int register_save_area_size = saved_pp ? kPointerSize : 0;
- for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
- if (!((1 << i) & saves)) continue;
- register_save_area_size += kPointerSize;
- }
- frame()->SetRegisterSaveAreaSize(register_save_area_size);
__ stm(db_w, sp, saves);
+ register_save_area_size +=
+ kPointerSize * base::bits::CountPopulation32(saves);
+ }
+ const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
+ if (saves_fp != 0) {
+ // Save callee-saved FP registers.
+ STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 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::CountPopulation32(saves_fp));
+
+ __ vstm(db_w, sp, DwVfpRegister::from_code(first),
+ DwVfpRegister::from_code(last));
+ register_save_area_size += 2 * kPointerSize * (last - first + 1);
+ }
+ if (register_save_area_size > 0) {
+ frame()->SetRegisterSaveAreaSize(register_save_area_size);
}
} else if (descriptor->IsJSFunctionCall()) {
CompilationInfo* info = this->info();
if (stack_slots > 0) {
__ add(sp, sp, Operand(stack_slots * kPointerSize));
}
+ // Restore FP registers.
+ const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
+ if (saves_fp != 0) {
+ STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 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));
+ }
// Restore registers.
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) {
return r4.bit() | r5.bit() | r6.bit() | r7.bit() | r8.bit() | r9.bit() |
r10.bit();
}
+ static RegList CCalleeSaveFPRegisters() {
+ return (1 << d8.code()) | (1 << d9.code()) | (1 << d10.code()) |
+ (1 << d11.code()) | (1 << d12.code()) | (1 << d13.code()) |
+ (1 << d14.code()) | (1 << d15.code());
+ }
static Register CRegisterParameter(int i) {
static Register register_parameters[] = {r0, r1, r2, r3};
return register_parameters[i];
__ SetStackPointer(csp);
__ Push(lr, fp);
__ Mov(fp, csp);
- // TODO(dcarney): correct callee saved registers.
- __ PushCalleeSavedRegisters();
- frame()->SetRegisterSaveAreaSize(20 * kPointerSize);
+
+ // Save FP registers.
+ CPURegList saves_fp = CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
+ descriptor->CalleeSavedFPRegisters());
+ DCHECK(saves_fp.list() == CPURegList::GetCalleeSavedFP().list());
+ int saved_count = saves_fp.Count();
+ __ PushCPURegList(saves_fp);
+ // Save registers.
+ CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
+ descriptor->CalleeSavedRegisters());
+ // TODO(palfia): TF save list is not in sync with
+ // CPURegList::GetCalleeSaved(): x30 is missing.
+ // DCHECK(saves.list() == CPURegList::GetCalleeSaved().list());
+ saved_count += saves.Count();
+ __ PushCPURegList(saves);
+
+ frame()->SetRegisterSaveAreaSize(saved_count * kPointerSize);
} else if (descriptor->IsJSFunctionCall()) {
CompilationInfo* info = this->info();
__ SetStackPointer(jssp);
if (stack_slots > 0) {
__ Add(csp, csp, AlignedStackSlots(stack_slots) * kPointerSize);
}
+
// Restore registers.
- // TODO(dcarney): correct callee saved registers.
- __ PopCalleeSavedRegisters();
+ CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
+ descriptor->CalleeSavedRegisters());
+ __ PopCPURegList(saves);
+
+ CPURegList saves_fp =
+ CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
+ descriptor->CalleeSavedFPRegisters());
+ __ PopCPURegList(saves_fp);
}
+
__ Mov(csp, fp);
__ Pop(fp, lr);
__ Ret();
static Register RuntimeCallFunctionReg() { return x1; }
static Register RuntimeCallArgCountReg() { return x0; }
static RegList CCalleeSaveRegisters() {
- // TODO(dcarney): correct callee saved registers.
- return 0;
+ return (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()) | (1 << x29.code()) | (1 << x30.code());
+ }
+ static RegList CCalleeSaveFPRegisters() {
+ return (1 << d8.code()) | (1 << d9.code()) | (1 << d10.code()) |
+ (1 << d11.code()) | (1 << d12.code()) | (1 << d13.code()) |
+ (1 << d14.code()) | (1 << d15.code());
}
static Register CRegisterParameter(int i) {
static Register register_parameters[] = {x0, x1, x2, x3, x4, x5, x6, x7};
static RegList CCalleeSaveRegisters() {
return esi.bit() | edi.bit() | ebx.bit();
}
+ static RegList CCalleeSaveFPRegisters() { return 0; }
static Register CRegisterParameter(int i) { return no_reg; }
static int CRegisterParametersLength() { return 0; }
static int CStackBackingStoreLength() { return 0; }
js_parameter_count, // js_parameter_count
Operator::kNoProperties, // properties
kNoCalleeSaved, // callee-saved
+ kNoCalleeSaved, // callee-saved fp
flags, // flags
"js-call");
}
js_parameter_count, // js_parameter_count
properties, // properties
kNoCalleeSaved, // callee-saved
+ kNoCalleeSaved, // callee-saved fp
flags, // flags
function->name); // debug name
}
js_parameter_count, // js_parameter_count
properties, // properties
kNoCalleeSaved, // callee-saved registers
+ kNoCalleeSaved, // callee-saved fp
flags, // flags
descriptor.DebugName(isolate));
}
// The target for C calls is always an address (i.e. machine pointer).
MachineType target_type = kMachPtr;
LinkageLocation target_loc = LinkageLocation::AnyRegister();
- return new (zone) CallDescriptor( // --
- CallDescriptor::kCallAddress, // kind
- target_type, // target MachineType
- target_loc, // target location
- msig, // machine_sig
- locations.Build(), // location_sig
- 0, // js_parameter_count
- Operator::kNoProperties, // properties
- LinkageTraits::CCalleeSaveRegisters(), // callee-saved registers
- CallDescriptor::kNoFlags, // flags
+ return new (zone) CallDescriptor( // --
+ CallDescriptor::kCallAddress, // kind
+ target_type, // target MachineType
+ target_loc, // target location
+ msig, // machine_sig
+ locations.Build(), // location_sig
+ 0, // js_parameter_count
+ Operator::kNoProperties, // properties
+ LinkageTraits::CCalleeSaveRegisters(), // callee-saved registers
+ LinkageTraits::CCalleeSaveFPRegisters(), // callee-saved fp regs
+ CallDescriptor::kNoFlags, // flags
"c-call");
}
const MachineSignature* machine_sig,
LocationSignature* location_sig, size_t js_param_count,
Operator::Properties properties,
- RegList callee_saved_registers, Flags flags,
+ RegList callee_saved_registers,
+ RegList callee_saved_fp_registers, Flags flags,
const char* debug_name = "")
: kind_(kind),
target_type_(target_type),
js_param_count_(js_param_count),
properties_(properties),
callee_saved_registers_(callee_saved_registers),
+ callee_saved_fp_registers_(callee_saved_fp_registers),
flags_(flags),
debug_name_(debug_name) {
DCHECK(machine_sig->return_count() == location_sig->return_count());
// Get the callee-saved registers, if any, across this call.
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_; }
+
const char* debug_name() const { return debug_name_; }
bool UsesOnlyRegisters() const;
const size_t js_param_count_;
const Operator::Properties properties_;
const RegList callee_saved_registers_;
+ const RegList callee_saved_fp_registers_;
const Flags flags_;
const char* const debug_name_;
if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ Push(ra, fp);
__ mov(fp, sp);
+
const RegList saves = descriptor->CalleeSavedRegisters();
- if (saves != 0) { // Save callee-saved registers.
- // TODO(plind): make callee save size const, possibly DCHECK it.
- int register_save_area_size = 0;
- for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
- if (!((1 << i) & saves)) continue;
- register_save_area_size += kPointerSize;
- }
- frame()->SetRegisterSaveAreaSize(register_save_area_size);
- __ MultiPush(saves);
- }
+ // Save callee-saved registers.
+ __ MultiPush(saves);
+ DCHECK(kNumCalleeSaved == base::bits::CountPopulation32(saves));
+ int register_save_area_size = kNumCalleeSaved * kPointerSize;
+
+ const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
+ // Save callee-saved FPU registers.
+ __ MultiPushFPU(saves_fpu);
+ DCHECK(kNumCalleeSavedFPU == base::bits::CountPopulation32(saves_fpu));
+ register_save_area_size += kNumCalleeSavedFPU * kDoubleSize * kPointerSize;
+
+ frame()->SetRegisterSaveAreaSize(register_save_area_size);
} else if (descriptor->IsJSFunctionCall()) {
CompilationInfo* info = this->info();
__ Prologue(info->IsCodePreAgingActive());
if (stack_slots > 0) {
__ Addu(sp, sp, Operand(stack_slots * kPointerSize));
}
- // Restore registers.
+ // Restore FPU registers.
+ const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
+ __ MultiPopFPU(saves_fpu);
+
+ // Restore GP registers.
const RegList saves = descriptor->CalleeSavedRegisters();
- if (saves != 0) {
- __ MultiPop(saves);
- }
+ __ MultiPop(saves);
}
__ mov(sp, fp);
__ Pop(ra, fp);
return s0.bit() | s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() |
s6.bit() | s7.bit();
}
+ static RegList CCalleeSaveFPRegisters() {
+ return f20.bit() | f22.bit() | f24.bit() | f26.bit() | f28.bit() |
+ f30.bit();
+ }
static Register CRegisterParameter(int i) {
static Register register_parameters[] = {a0, a1, a2, a3};
return register_parameters[i];
if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ Push(ra, fp);
__ mov(fp, sp);
+
const RegList saves = descriptor->CalleeSavedRegisters();
- if (saves != 0) { // Save callee-saved registers.
- // TODO(plind): make callee save size const, possibly DCHECK it.
- int register_save_area_size = 0;
- for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
- if (!((1 << i) & saves)) continue;
- register_save_area_size += kPointerSize;
- }
- frame()->SetRegisterSaveAreaSize(register_save_area_size);
- __ MultiPush(saves);
- }
+ // Save callee-saved registers.
+ __ MultiPush(saves);
+ DCHECK(kNumCalleeSaved == base::bits::CountPopulation32(saves));
+ int register_save_area_size = kNumCalleeSaved * kPointerSize;
+
+ const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
+ // Save callee-saved FPU registers.
+ __ MultiPushFPU(saves_fpu);
+ DCHECK(kNumCalleeSavedFPU == base::bits::CountPopulation32(saves_fpu));
+ register_save_area_size += kNumCalleeSavedFPU * kDoubleSize * kPointerSize;
+
+ frame()->SetRegisterSaveAreaSize(register_save_area_size);
} else if (descriptor->IsJSFunctionCall()) {
CompilationInfo* info = this->info();
__ Prologue(info->IsCodePreAgingActive());
if (stack_slots > 0) {
__ Daddu(sp, sp, Operand(stack_slots * kPointerSize));
}
- // Restore registers.
+ // Restore FPU registers.
+ const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
+ __ MultiPopFPU(saves_fpu);
+
+ // Restore GP registers.
const RegList saves = descriptor->CalleeSavedRegisters();
- if (saves != 0) {
- __ MultiPop(saves);
- }
+ __ MultiPop(saves);
}
__ mov(sp, fp);
__ Pop(ra, fp);
return s0.bit() | s1.bit() | s2.bit() | s3.bit() | s4.bit() | s5.bit() |
s6.bit() | s7.bit();
}
+ static RegList CCalleeSaveFPRegisters() {
+ return f20.bit() | f22.bit() | f24.bit() | f26.bit() | f28.bit() |
+ f30.bit();
+ }
static Register CRegisterParameter(int i) {
static Register register_parameters[] = {a0, a1, a2, a3, a4, a5, a6, a7};
return register_parameters[i];
r24.bit() | r25.bit() | r26.bit() | r27.bit() | r28.bit() |
r29.bit() | r30.bit() | fp.bit();
}
+ static RegList CCalleeSaveFPRegisters() { return 0; }
static Register CRegisterParameter(int i) {
static Register register_parameters[] = {r3, r4, r5, r6, r7, r8, r9, r10};
return register_parameters[i];
if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ pushq(rbp);
__ movq(rbp, rsp);
+ int register_save_area_size = 0;
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) { // Save callee-saved registers.
- int register_save_area_size = 0;
for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
if (!((1 << i) & saves)) continue;
__ pushq(Register::from_code(i));
register_save_area_size += kPointerSize;
}
+ }
+ const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
+ if (saves_fp != 0) { // Save callee-saved XMM registers.
+ const uint32_t saves_fp_count = base::bits::CountPopulation32(saves_fp);
+ const int stack_size = saves_fp_count * 16;
+ // Adjust the stack pointer.
+ __ subp(rsp, Immediate(stack_size));
+ // Store the registers on the stack.
+ int slot_idx = 0;
+ for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
+ if (!((1 << i) & saves_fp)) continue;
+ __ movdqu(Operand(rsp, 16 * slot_idx), XMMRegister::from_code(i));
+ slot_idx++;
+ }
+ register_save_area_size += stack_size;
+ }
+ if (register_save_area_size > 0) {
frame()->SetRegisterSaveAreaSize(register_save_area_size);
}
} else if (descriptor->IsJSFunctionCall()) {
if (stack_slots > 0) {
__ addq(rsp, Immediate(stack_slots * kPointerSize));
}
- const RegList saves = descriptor->CalleeSavedRegisters();
// Restore registers.
+ const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
+ if (saves_fp != 0) {
+ const uint32_t saves_fp_count = base::bits::CountPopulation32(saves_fp);
+ const int stack_size = saves_fp_count * 16;
+ // Load the registers from the stack.
+ int slot_idx = 0;
+ for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
+ if (!((1 << i) & saves_fp)) continue;
+ __ movdqu(XMMRegister::from_code(i), Operand(rsp, 16 * slot_idx));
+ slot_idx++;
+ }
+ // Adjust the stack pointer.
+ __ addp(rsp, Immediate(stack_size));
+ }
+ const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) {
for (int i = 0; i < Register::kNumRegisters; i++) {
if (!((1 << i) & saves)) continue;
return rbx.bit() | r12.bit() | r13.bit() | r14.bit() | r15.bit();
}
}
+ static RegList CCalleeSaveFPRegisters() {
+ if (kWin64) {
+ return (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());
+ } else {
+ return 0;
+ }
+ }
static Register CRegisterParameter(int i) {
if (kWin64) {
static Register register_parameters[] = {rcx, rdx, r8, r9};
'test-api/ExternalArrays': [PASS, NO_VARIANTS],
# TODO(mips-team): Currently fails on mips board.
- 'test-simplified-lowering/RunNumberMultiply_TruncatingToUint32': [SKIP],
- 'test-simplified-lowering/RunNumberDivide_2_TruncatingToUint32': [SKIP],
'test-parsing/TooManyArguments': [SKIP],
'test-api/Threading3': [SKIP],
}], # 'arch == mips'
CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
- Operator::kNoProperties, 0, CallDescriptor::kNoFlags);
+ Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
- Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls);
+ Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
- Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls);
+ Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
- Operator::kNoProperties, 0, CallDescriptor::kNoFlags);
+ Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
- Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls);
+ Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0),
new (zone()) MachineSignature(1, 1, kMachineSignature),
new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
- Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls);
+ Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls);
Node* p0 = Parameter(0);
Node* p1 = Parameter(1);
Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,