Commit d586e9c5 authored by yangguo@chromium.org's avatar yangguo@chromium.org

MIPS: port ARM: Fix context save/restore for VFP registers.

This commit was missed/skipped earlier for some reason.

Ported r8357 (d78dae4)

BUG=
TEST=

Review URL: http://codereview.chromium.org/7809014

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9088 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c657d440
...@@ -3695,9 +3695,20 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { ...@@ -3695,9 +3695,20 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
// Save callee saved registers on the stack. // Save callee saved registers on the stack.
__ MultiPush(kCalleeSaved | ra.bit()); __ MultiPush(kCalleeSaved | ra.bit());
if (CpuFeatures::IsSupported(FPU)) {
CpuFeatures::Scope scope(FPU);
// Save callee-saved FPU registers.
__ MultiPushFPU(kCalleeSavedFPU);
}
// Load argv in s0 register. // Load argv in s0 register.
__ lw(s0, MemOperand(sp, (kNumCalleeSaved + 1) * kPointerSize + int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize;
StandardFrameConstants::kCArgsSlotsSize)); if (CpuFeatures::IsSupported(FPU)) {
offset_to_argv += kNumCalleeSavedFPU * kDoubleSize;
}
__ lw(s0, MemOperand(sp, offset_to_argv +
StandardFrameConstants::kCArgsSlotsSize));
// We build an EntryFrame. // We build an EntryFrame.
__ li(t3, Operand(-1)); // Push a bad frame pointer to fail if it is used. __ li(t3, Operand(-1)); // Push a bad frame pointer to fail if it is used.
...@@ -3829,6 +3840,12 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { ...@@ -3829,6 +3840,12 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
// Reset the stack to the callee saved registers. // Reset the stack to the callee saved registers.
__ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset); __ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset);
if (CpuFeatures::IsSupported(FPU)) {
CpuFeatures::Scope scope(FPU);
// Restore callee-saved fpu registers.
__ MultiPopFPU(kCalleeSavedFPU);
}
// Restore callee saved registers from the stack. // Restore callee saved registers from the stack.
__ MultiPop(kCalleeSaved | ra.bit()); __ MultiPop(kCalleeSaved | ra.bit());
// Return. // Return.
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#ifndef V8_MIPS_FRAMES_MIPS_H_ #ifndef V8_MIPS_FRAMES_MIPS_H_
#define V8_MIPS_FRAMES_MIPS_H_ #define V8_MIPS_FRAMES_MIPS_H_
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -40,13 +39,22 @@ namespace internal { ...@@ -40,13 +39,22 @@ namespace internal {
static const int kNumRegs = 32; static const int kNumRegs = 32;
static const RegList kJSCallerSaved = static const RegList kJSCallerSaved =
1 << 2 | // v0 1 << 2 | // v0
1 << 4 | // a0 1 << 3 | // v1
1 << 5 | // a1 1 << 4 | // a0
1 << 6 | // a2 1 << 5 | // a1
1 << 7; // a3 1 << 6 | // a2
1 << 7 | // a3
static const int kNumJSCallerSaved = 5; 1 << 8 | // t0
1 << 9 | // t1
1 << 10 | // t2
1 << 11 | // t3
1 << 12 | // t4
1 << 13 | // t5
1 << 14 | // t6
1 << 15; // t7
static const int kNumJSCallerSaved = 14;
// Return the code of the n-th caller-saved register available to JavaScript // Return the code of the n-th caller-saved register available to JavaScript
...@@ -56,19 +64,31 @@ int JSCallerSavedCode(int n); ...@@ -56,19 +64,31 @@ int JSCallerSavedCode(int n);
// Callee-saved registers preserved when switching from C to JavaScript. // Callee-saved registers preserved when switching from C to JavaScript.
static const RegList kCalleeSaved = static const RegList kCalleeSaved =
// Saved temporaries. 1 << 16 | // s0
1 << 16 | 1 << 17 | 1 << 18 | 1 << 19 | 1 << 17 | // s1
1 << 20 | 1 << 21 | 1 << 22 | 1 << 23 | 1 << 18 | // s2
// fp. 1 << 19 | // s3
1 << 30; 1 << 20 | // s4
1 << 21 | // s5
1 << 22 | // s6 (roots in Javascript code)
1 << 23 | // s7 (cp in Javascript code)
1 << 30; // fp/s8
static const int kNumCalleeSaved = 9; static const int kNumCalleeSaved = 9;
static const RegList kCalleeSavedFPU =
1 << 20 | // f20
1 << 22 | // f22
1 << 24 | // f24
1 << 26 | // f26
1 << 28 | // f28
1 << 30; // f30
static const int kNumCalleeSavedFPU = 6;
// Number of registers for which space is reserved in safepoints. Must be a // Number of registers for which space is reserved in safepoints. Must be a
// multiple of 8. // multiple of 8.
// TODO(mips): Only 8 registers may actually be sufficient. Revisit. // TODO(mips): Only 8 registers may actually be sufficient. Revisit.
static const int kNumSafepointRegisters = 16; static const int kNumSafepointRegisters = 24;
// Define the list of registers actually saved at safepoints. // Define the list of registers actually saved at safepoints.
// Note that the number of saved registers may be smaller than the reserved // Note that the number of saved registers may be smaller than the reserved
...@@ -82,37 +102,37 @@ typedef Object* JSCallerSavedBuffer[kNumJSCallerSaved]; ...@@ -82,37 +102,37 @@ typedef Object* JSCallerSavedBuffer[kNumJSCallerSaved];
static const int kUndefIndex = -1; static const int kUndefIndex = -1;
// Map with indexes on stack that corresponds to codes of saved registers. // Map with indexes on stack that corresponds to codes of saved registers.
static const int kSafepointRegisterStackIndexMap[kNumRegs] = { static const int kSafepointRegisterStackIndexMap[kNumRegs] = {
kUndefIndex, kUndefIndex, // zero_reg
kUndefIndex, kUndefIndex, // at
0, // v0 0, // v0
kUndefIndex, 1, // v1
1, // a0 2, // a0
2, // a1 3, // a1
3, // a2 4, // a2
4, // a3 5, // a3
kUndefIndex, 6, // t0
kUndefIndex, 7, // t1
kUndefIndex, 8, // t2
kUndefIndex, 9, // t3
kUndefIndex, 10, // t4
kUndefIndex, 11, // t5
kUndefIndex, 12, // t6
kUndefIndex, 13, // t7
5, // Saved temporaries. 14, // s0
6, 15, // s1
7, 16, // s2
8, 17, // s3
9, 18, // s4
10, 19, // s5
11, 20, // s6
12, 21, // s7
kUndefIndex, kUndefIndex, // t8
kUndefIndex, kUndefIndex, // t9
kUndefIndex, kUndefIndex, // k0
kUndefIndex, kUndefIndex, // k1
13, // gp kUndefIndex, // gp
14, // sp kUndefIndex, // sp
15, // fp 22, // fp
kUndefIndex kUndefIndex
}; };
......
...@@ -703,52 +703,114 @@ void MacroAssembler::li(Register rd, Operand j, bool gen2instr) { ...@@ -703,52 +703,114 @@ void MacroAssembler::li(Register rd, Operand j, bool gen2instr) {
void MacroAssembler::MultiPush(RegList regs) { void MacroAssembler::MultiPush(RegList regs) {
int16_t NumSaved = 0; int16_t num_to_push = NumberOfBitsSet(regs);
int16_t NumToPush = NumberOfBitsSet(regs); int16_t stack_offset = num_to_push * kPointerSize;
addiu(sp, sp, -4 * NumToPush); Subu(sp, sp, Operand(stack_offset));
for (int16_t i = kNumRegisters; i > 0; i--) { for (int16_t i = kNumRegisters; i > 0; i--) {
if ((regs & (1 << i)) != 0) { if ((regs & (1 << i)) != 0) {
sw(ToRegister(i), MemOperand(sp, 4 * (NumToPush - ++NumSaved))); stack_offset -= kPointerSize;
sw(ToRegister(i), MemOperand(sp, stack_offset));
} }
} }
} }
void MacroAssembler::MultiPushReversed(RegList regs) { void MacroAssembler::MultiPushReversed(RegList regs) {
int16_t NumSaved = 0; int16_t num_to_push = NumberOfBitsSet(regs);
int16_t NumToPush = NumberOfBitsSet(regs); int16_t stack_offset = num_to_push * kPointerSize;
addiu(sp, sp, -4 * NumToPush); Subu(sp, sp, Operand(stack_offset));
for (int16_t i = 0; i < kNumRegisters; i++) { for (int16_t i = 0; i < kNumRegisters; i++) {
if ((regs & (1 << i)) != 0) { if ((regs & (1 << i)) != 0) {
sw(ToRegister(i), MemOperand(sp, 4 * (NumToPush - ++NumSaved))); stack_offset -= kPointerSize;
sw(ToRegister(i), MemOperand(sp, stack_offset));
} }
} }
} }
void MacroAssembler::MultiPop(RegList regs) { void MacroAssembler::MultiPop(RegList regs) {
int16_t NumSaved = 0; int16_t stack_offset = 0;
for (int16_t i = 0; i < kNumRegisters; i++) { for (int16_t i = 0; i < kNumRegisters; i++) {
if ((regs & (1 << i)) != 0) { if ((regs & (1 << i)) != 0) {
lw(ToRegister(i), MemOperand(sp, 4 * (NumSaved++))); lw(ToRegister(i), MemOperand(sp, stack_offset));
stack_offset += kPointerSize;
} }
} }
addiu(sp, sp, 4 * NumSaved); addiu(sp, sp, stack_offset);
} }
void MacroAssembler::MultiPopReversed(RegList regs) { void MacroAssembler::MultiPopReversed(RegList regs) {
int16_t NumSaved = 0; int16_t stack_offset = 0;
for (int16_t i = kNumRegisters; i > 0; i--) { for (int16_t i = kNumRegisters; i > 0; i--) {
if ((regs & (1 << i)) != 0) { if ((regs & (1 << i)) != 0) {
lw(ToRegister(i), MemOperand(sp, 4 * (NumSaved++))); lw(ToRegister(i), MemOperand(sp, stack_offset));
stack_offset += kPointerSize;
} }
} }
addiu(sp, sp, 4 * NumSaved); addiu(sp, sp, stack_offset);
}
void MacroAssembler::MultiPushFPU(RegList regs) {
CpuFeatures::Scope scope(FPU);
int16_t num_to_push = NumberOfBitsSet(regs);
int16_t stack_offset = num_to_push * kDoubleSize;
Subu(sp, sp, Operand(stack_offset));
for (int16_t i = kNumRegisters; i > 0; i--) {
if ((regs & (1 << i)) != 0) {
stack_offset -= kDoubleSize;
sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
}
}
}
void MacroAssembler::MultiPushReversedFPU(RegList regs) {
CpuFeatures::Scope scope(FPU);
int16_t num_to_push = NumberOfBitsSet(regs);
int16_t stack_offset = num_to_push * kDoubleSize;
Subu(sp, sp, Operand(stack_offset));
for (int16_t i = 0; i < kNumRegisters; i++) {
if ((regs & (1 << i)) != 0) {
stack_offset -= kDoubleSize;
sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
}
}
}
void MacroAssembler::MultiPopFPU(RegList regs) {
CpuFeatures::Scope scope(FPU);
int16_t stack_offset = 0;
for (int16_t i = 0; i < kNumRegisters; i++) {
if ((regs & (1 << i)) != 0) {
ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
stack_offset += kDoubleSize;
}
}
addiu(sp, sp, stack_offset);
}
void MacroAssembler::MultiPopReversedFPU(RegList regs) {
CpuFeatures::Scope scope(FPU);
int16_t stack_offset = 0;
for (int16_t i = kNumRegisters; i > 0; i--) {
if ((regs & (1 << i)) != 0) {
ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset));
stack_offset += kDoubleSize;
}
}
addiu(sp, sp, stack_offset);
} }
......
...@@ -442,6 +442,9 @@ class MacroAssembler: public Assembler { ...@@ -442,6 +442,9 @@ class MacroAssembler: public Assembler {
void MultiPush(RegList regs); void MultiPush(RegList regs);
void MultiPushReversed(RegList regs); void MultiPushReversed(RegList regs);
void MultiPushFPU(RegList regs);
void MultiPushReversedFPU(RegList regs);
// Lower case push() for compatibility with arch-independent code. // Lower case push() for compatibility with arch-independent code.
void push(Register src) { void push(Register src) {
Addu(sp, sp, Operand(-kPointerSize)); Addu(sp, sp, Operand(-kPointerSize));
...@@ -487,6 +490,9 @@ class MacroAssembler: public Assembler { ...@@ -487,6 +490,9 @@ class MacroAssembler: public Assembler {
void MultiPop(RegList regs); void MultiPop(RegList regs);
void MultiPopReversed(RegList regs); void MultiPopReversed(RegList regs);
void MultiPopFPU(RegList regs);
void MultiPopReversedFPU(RegList regs);
// Lower case pop() for compatibility with arch-independent code. // Lower case pop() for compatibility with arch-independent code.
void pop(Register dst) { void pop(Register dst) {
lw(dst, MemOperand(sp, 0)); lw(dst, MemOperand(sp, 0));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment