PPC: Clean up register save/restore logic.

NOPRESUBMIT=true
R=titzer@chromium.org, michael_dawson@ca.ibm.com, jyan@ca.ibm.com, joransiu@ca.ibm.com
BUG=

Review URL: https://codereview.chromium.org/1271583002

Cr-Commit-Position: refs/heads/master@{#29978}
This commit is contained in:
mbrandy 2015-08-03 07:36:43 -07:00 committed by Commit bot
parent 80efc9d2fb
commit e16cfe562d
8 changed files with 124 additions and 76 deletions

View File

@ -138,7 +138,11 @@ LinkageLocation stackloc(int i) {
#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
// ===========================================================================

View File

@ -1296,27 +1296,34 @@ void CodeGenerator::AssemblePrologue() {
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());
@ -1359,15 +1366,17 @@ void CodeGenerator::AssembleReturn() {
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();

View File

@ -749,7 +749,7 @@ void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
__ 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;
@ -761,7 +761,7 @@ void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
__ 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);
@ -1234,11 +1234,10 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// 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
@ -1360,20 +1359,16 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// 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();
}

View File

@ -181,7 +181,7 @@ class RecordWriteStub : public PlatformCodeStub {
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());
}
}
@ -189,7 +189,7 @@ class RecordWriteStub : public PlatformCodeStub {
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);

View File

@ -55,6 +55,43 @@ const RegList kCalleeSaved = 1 << 14 | // r14
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;

View File

@ -224,30 +224,59 @@ void MacroAssembler::Move(DoubleRegister dst, DoubleRegister src) {
}
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));
}
@ -825,7 +854,7 @@ void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) {
// 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,
@ -891,7 +920,7 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count,
const int offset =
(ExitFrameConstants::kFrameSize + kNumRegs * kDoubleSize);
addi(r6, fp, Operand(-offset));
RestoreFPRegs(r6, 0, kNumRegs);
MultiPopDoubles(kCallerSavedDoubles, r6);
}
// Clear top frame.
@ -2955,28 +2984,6 @@ void MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
}
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) {

View File

@ -152,8 +152,11 @@ class MacroAssembler : public Assembler {
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,
@ -888,12 +891,6 @@ class MacroAssembler : public Assembler {
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

View File

@ -171,8 +171,7 @@ void RegExpMacroAssemblerPPC::Backtrack() {
// Pop Code* offset from backtrack stack, add Code* and jump to location.
Pop(r3);
__ add(r3, r3, code_pointer());
__ mtctr(r3);
__ bctr();
__ Jump(r3);
}
@ -834,8 +833,8 @@ Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) {
// 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()) {