From e16cfe562d5dc142eb604002afb3d0e4dfca663e Mon Sep 17 00:00:00 2001 From: mbrandy Date: Mon, 3 Aug 2015 07:36:43 -0700 Subject: [PATCH] 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} --- src/compiler/c-linkage.cc | 6 ++- src/compiler/ppc/code-generator-ppc.cc | 33 ++++++++++------ src/ppc/code-stubs-ppc.cc | 29 ++++++-------- src/ppc/code-stubs-ppc.h | 4 +- src/ppc/frames-ppc.h | 37 ++++++++++++++++++ src/ppc/macro-assembler-ppc.cc | 71 +++++++++++++++++++--------------- src/ppc/macro-assembler-ppc.h | 13 +++---- src/ppc/regexp-macro-assembler-ppc.cc | 7 ++-- 8 files changed, 124 insertions(+), 76 deletions(-) diff --git a/src/compiler/c-linkage.cc b/src/compiler/c-linkage.cc index d261d78..61b3ee3 100644 --- a/src/compiler/c-linkage.cc +++ b/src/compiler/c-linkage.cc @@ -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 // =========================================================================== diff --git a/src/compiler/ppc/code-generator-ppc.cc b/src/compiler/ppc/code-generator-ppc.cc index 3d91e68..4e9f99f 100644 --- a/src/compiler/ppc/code-generator-ppc.cc +++ b/src/compiler/ppc/code-generator-ppc.cc @@ -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(); diff --git a/src/ppc/code-stubs-ppc.cc b/src/ppc/code-stubs-ppc.cc index 35e9f29..13e0948 100644 --- a/src/ppc/code-stubs-ppc.cc +++ b/src/ppc/code-stubs-ppc.cc @@ -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(); } diff --git a/src/ppc/code-stubs-ppc.h b/src/ppc/code-stubs-ppc.h index 3c71a23..238c9f7 100644 --- a/src/ppc/code-stubs-ppc.h +++ b/src/ppc/code-stubs-ppc.h @@ -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); diff --git a/src/ppc/frames-ppc.h b/src/ppc/frames-ppc.h index 16e86db..d5b6d3c 100644 --- a/src/ppc/frames-ppc.h +++ b/src/ppc/frames-ppc.h @@ -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; diff --git a/src/ppc/macro-assembler-ppc.cc b/src/ppc/macro-assembler-ppc.cc index 1598f8f..4ee6323 100644 --- a/src/ppc/macro-assembler-ppc.cc +++ b/src/ppc/macro-assembler-ppc.cc @@ -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) { diff --git a/src/ppc/macro-assembler-ppc.h b/src/ppc/macro-assembler-ppc.h index 95e98e4..77621e7 100644 --- a/src/ppc/macro-assembler-ppc.h +++ b/src/ppc/macro-assembler-ppc.h @@ -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 double values to , starting from d. - void SaveFPRegs(Register location, int first, int count); - - // Pops double values from , starting from d. - void RestoreFPRegs(Register location, int first, int count); - // --------------------------------------------------------------------------- // Runtime calls diff --git a/src/ppc/regexp-macro-assembler-ppc.cc b/src/ppc/regexp-macro-assembler-ppc.cc index 05e84e4..9e4e9e5 100644 --- a/src/ppc/regexp-macro-assembler-ppc.cc +++ b/src/ppc/regexp-macro-assembler-ppc.cc @@ -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 RegExpMacroAssemblerPPC::GetCode(Handle 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()) { -- 2.7.4