#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() | fp.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()
#else
// ===========================================================================
int stack_slots = frame()->GetSpillSlotCount();
if (descriptor->kind() == CallDescriptor::kCallAddress) {
__ function_descriptor();
- int register_save_area_size = 0;
- RegList frame_saves = fp.bit();
+ RegList frame_saves = 0;
__ mflr(r0);
if (FLAG_enable_embedded_constant_pool) {
__ Push(r0, fp, kConstantPoolRegister);
// Adjust FP to point to saved FP.
__ subi(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset));
- register_save_area_size += kPointerSize;
frame_saves |= kConstantPoolRegister.bit();
} else {
__ Push(r0, fp);
__ mr(fp, sp);
}
+
// Save callee-saved registers.
const RegList saves = descriptor->CalleeSavedRegisters() & ~frame_saves;
- 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);
+ // register save area does not include the fp.
+ DCHECK(kNumCalleeSaved - 1 ==
+ base::bits::CountPopulation32(saves | frame_saves));
+ int register_save_area_size = (kNumCalleeSaved - 1) * kPointerSize;
+
+ // Save callee-saved Double registers.
+ const RegList double_saves = descriptor->CalleeSavedFPRegisters();
+ __ MultiPushDoubles(double_saves);
+ DCHECK(kNumCalleeSavedDoubles ==
+ base::bits::CountPopulation32(double_saves));
+ register_save_area_size += kNumCalleeSavedDoubles * kDoubleSize;
+
+ frame()->SetRegisterSaveAreaSize(register_save_area_size);
} else if (descriptor->IsJSFunctionCall()) {
CompilationInfo* info = this->info();
__ Prologue(info->IsCodePreAgingActive());
if (stack_slots > 0) {
__ Add(sp, sp, stack_slots * kPointerSize, r0);
}
+ // Restore double registers.
+ const RegList double_saves = descriptor->CalleeSavedFPRegisters();
+ __ MultiPopDoubles(double_saves);
+
// Restore registers.
- RegList frame_saves = fp.bit();
+ RegList frame_saves = 0;
if (FLAG_enable_embedded_constant_pool) {
frame_saves |= kConstantPoolRegister.bit();
}
const RegList saves = descriptor->CalleeSavedRegisters() & ~frame_saves;
- if (saves != 0) {
- __ MultiPop(saves);
- }
+ __ MultiPop(saves);
}
__ LeaveFrame(StackFrame::MANUAL);
__ Ret();
__ mflr(r0);
__ MultiPush(kJSCallerSaved | r0.bit());
if (save_doubles()) {
- __ SaveFPRegs(sp, 0, DoubleRegister::kNumVolatileRegisters);
+ __ MultiPushDoubles(kCallerSavedDoubles);
}
const int argument_count = 1;
const int fp_argument_count = 0;
__ CallCFunction(ExternalReference::store_buffer_overflow_function(isolate()),
argument_count);
if (save_doubles()) {
- __ RestoreFPRegs(sp, 0, DoubleRegister::kNumVolatileRegisters);
+ __ MultiPopDoubles(kCallerSavedDoubles);
}
__ MultiPop(kJSCallerSaved | r0.bit());
__ mtlr(r0);
// Save callee saved registers on the stack.
__ MultiPush(kCalleeSaved);
- // Floating point regs FPR0 - FRP13 are volatile
- // FPR14-FPR31 are non-volatile, but sub-calls will save them for us
-
- // int offset_to_argv = kPointerSize * 22; // matches (22*4) above
- // __ lwz(r7, MemOperand(sp, offset_to_argv));
+ // Save callee-saved double registers.
+ __ MultiPushDoubles(kCalleeSavedDoubles);
+ // Set up the reserved register for 0.0.
+ __ LoadDoubleLiteral(kDoubleRegZero, 0.0, r0);
// Push a frame with special values setup to mark it as an entry frame.
// r3: code entry
// Reset the stack to the callee saved registers.
__ addi(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
-// Restore callee-saved registers and return.
-#ifdef DEBUG
- if (FLAG_debug_code) {
- Label here;
- __ b(&here, SetLK);
- __ bind(&here);
- }
-#endif
+ // Restore callee-saved double registers.
+ __ MultiPopDoubles(kCalleeSavedDoubles);
+ // Restore callee-saved registers.
__ MultiPop(kCalleeSaved);
+ // Return
__ LoadP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize));
- __ mtctr(r0);
- __ bctr();
+ __ mtlr(r0);
+ __ blr();
}
masm->MultiPush(kJSCallerSaved & ~scratch1_.bit());
if (mode == kSaveFPRegs) {
// Save all volatile FP registers except d0.
- masm->SaveFPRegs(sp, 1, DoubleRegister::kNumVolatileRegisters - 1);
+ masm->MultiPushDoubles(kCallerSavedDoubles & ~d0.bit());
}
}
SaveFPRegsMode mode) {
if (mode == kSaveFPRegs) {
// Restore all volatile FP registers except d0.
- masm->RestoreFPRegs(sp, 1, DoubleRegister::kNumVolatileRegisters - 1);
+ masm->MultiPopDoubles(kCallerSavedDoubles & ~d0.bit());
}
masm->MultiPop(kJSCallerSaved & ~scratch1_.bit());
masm->pop(r0);
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 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;
+
+
// Number of registers for which space is reserved in safepoints. Must be a
// multiple of 8.
const int kNumSafepointRegisters = 32;
}
-void MacroAssembler::MultiPush(RegList regs) {
+void MacroAssembler::MultiPush(RegList regs, Register location) {
int16_t num_to_push = NumberOfBitsSet(regs);
int16_t stack_offset = num_to_push * kPointerSize;
- subi(sp, sp, Operand(stack_offset));
- for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
+ subi(location, location, Operand(stack_offset));
+ for (int16_t i = Register::kNumRegisters - 1; i >= 0; i--) {
if ((regs & (1 << i)) != 0) {
stack_offset -= kPointerSize;
- StoreP(ToRegister(i), MemOperand(sp, stack_offset));
+ StoreP(ToRegister(i), MemOperand(location, stack_offset));
}
}
}
-void MacroAssembler::MultiPop(RegList regs) {
+void MacroAssembler::MultiPop(RegList regs, Register location) {
int16_t stack_offset = 0;
- for (int16_t i = 0; i < kNumRegisters; i++) {
+ for (int16_t i = 0; i < Register::kNumRegisters; i++) {
if ((regs & (1 << i)) != 0) {
- LoadP(ToRegister(i), MemOperand(sp, stack_offset));
+ LoadP(ToRegister(i), MemOperand(location, stack_offset));
stack_offset += kPointerSize;
}
}
- addi(sp, sp, Operand(stack_offset));
+ addi(location, location, Operand(stack_offset));
+}
+
+
+void MacroAssembler::MultiPushDoubles(RegList dregs, Register location) {
+ int16_t num_to_push = NumberOfBitsSet(dregs);
+ int16_t stack_offset = num_to_push * kDoubleSize;
+
+ subi(location, location, Operand(stack_offset));
+ for (int16_t i = DoubleRegister::kNumRegisters - 1; i >= 0; i--) {
+ if ((dregs & (1 << i)) != 0) {
+ DoubleRegister dreg = DoubleRegister::from_code(i);
+ stack_offset -= kDoubleSize;
+ stfd(dreg, MemOperand(location, stack_offset));
+ }
+ }
+}
+
+
+void MacroAssembler::MultiPopDoubles(RegList dregs, Register location) {
+ int16_t stack_offset = 0;
+
+ for (int16_t i = 0; i < DoubleRegister::kNumRegisters; i++) {
+ if ((dregs & (1 << i)) != 0) {
+ DoubleRegister dreg = DoubleRegister::from_code(i);
+ lfd(dreg, MemOperand(location, stack_offset));
+ stack_offset += kDoubleSize;
+ }
+ }
+ addi(location, location, Operand(stack_offset));
}
// Optionally save all volatile double registers.
if (save_doubles) {
- SaveFPRegs(sp, 0, DoubleRegister::kNumVolatileRegisters);
+ MultiPushDoubles(kCallerSavedDoubles);
// Note that d0 will be accessible at
// fp - ExitFrameConstants::kFrameSize -
// kNumVolatileRegisters * kDoubleSize,
const int offset =
(ExitFrameConstants::kFrameSize + kNumRegs * kDoubleSize);
addi(r6, fp, Operand(-offset));
- RestoreFPRegs(r6, 0, kNumRegs);
+ MultiPopDoubles(kCallerSavedDoubles, r6);
}
// Clear top frame.
}
-void MacroAssembler::SaveFPRegs(Register location, int first, int count) {
- DCHECK(count > 0);
- int cur = first;
- subi(location, location, Operand(count * kDoubleSize));
- for (int i = 0; i < count; i++) {
- DoubleRegister reg = DoubleRegister::from_code(cur++);
- stfd(reg, MemOperand(location, i * kDoubleSize));
- }
-}
-
-
-void MacroAssembler::RestoreFPRegs(Register location, int first, int count) {
- DCHECK(count > 0);
- int cur = first + count - 1;
- for (int i = count - 1; i >= 0; i--) {
- DoubleRegister reg = DoubleRegister::from_code(cur--);
- lfd(reg, MemOperand(location, i * kDoubleSize));
- }
- addi(location, location, Operand(count * kDoubleSize));
-}
-
-
void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte(
Register first, Register second, Register scratch1, Register scratch2,
Label* failure) {
void Move(Register dst, Register src, Condition cond = al);
void Move(DoubleRegister dst, DoubleRegister src);
- void MultiPush(RegList regs);
- void MultiPop(RegList regs);
+ void MultiPush(RegList regs, Register location = sp);
+ void MultiPop(RegList regs, Register location = sp);
+
+ void MultiPushDoubles(RegList dregs, Register location = sp);
+ void MultiPopDoubles(RegList dregs, Register location = sp);
// Load an object from the root table.
void LoadRoot(Register destination, Heap::RootListIndex index,
bind(&label);
}
- // Pushes <count> double values to <location>, starting from d<first>.
- void SaveFPRegs(Register location, int first, int count);
-
- // Pops <count> double values from <location>, starting from d<first>.
- void RestoreFPRegs(Register location, int first, int count);
-
// ---------------------------------------------------------------------------
// Runtime calls
// Pop Code* offset from backtrack stack, add Code* and jump to location.
Pop(r3);
__ add(r3, r3, code_pointer());
- __ mtctr(r3);
- __ bctr();
+ __ Jump(r3);
}
// Restore registers r25..r31 and return (restoring lr to pc).
__ MultiPop(registers_to_retain);
__ pop(r0);
- __ mtctr(r0);
- __ bctr();
+ __ mtlr(r0);
+ __ blr();
// Backtrack code (branch target for conditional backtracks).
if (backtrack_label_.is_linked()) {