| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if V8_TARGET_ARCH_PPC | 5 #if V8_TARGET_ARCH_PPC |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1048 __ add(r4, r4, sp); | 1048 __ add(r4, r4, sp); |
| 1049 __ subi(r4, r4, Operand(kPointerSize)); | 1049 __ subi(r4, r4, Operand(kPointerSize)); |
| 1050 } | 1050 } |
| 1051 | 1051 |
| 1052 // Enter the exit frame that transitions from JavaScript to C++. | 1052 // Enter the exit frame that transitions from JavaScript to C++. |
| 1053 FrameScope scope(masm, StackFrame::MANUAL); | 1053 FrameScope scope(masm, StackFrame::MANUAL); |
| 1054 | 1054 |
| 1055 // Need at least one extra slot for return address location. | 1055 // Need at least one extra slot for return address location. |
| 1056 int arg_stack_space = 1; | 1056 int arg_stack_space = 1; |
| 1057 | 1057 |
| 1058 // PPC LINUX ABI: | |
| 1059 #if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS | |
| 1060 // Pass buffer for return value on stack if necessary | 1058 // Pass buffer for return value on stack if necessary |
| 1061 if (result_size() > 1) { | 1059 bool needs_return_buffer = |
| 1062 DCHECK_EQ(2, result_size()); | 1060 result_size() > 2 || |
| 1063 arg_stack_space += 2; | 1061 (result_size() == 2 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS); |
| 1062 if (needs_return_buffer) { |
| 1063 arg_stack_space += result_size(); |
| 1064 } | 1064 } |
| 1065 #endif | |
| 1066 | 1065 |
| 1067 __ EnterExitFrame(save_doubles(), arg_stack_space); | 1066 __ EnterExitFrame(save_doubles(), arg_stack_space); |
| 1068 | 1067 |
| 1069 // Store a copy of argc in callee-saved registers for later. | 1068 // Store a copy of argc in callee-saved registers for later. |
| 1070 __ mr(r14, r3); | 1069 __ mr(r14, r3); |
| 1071 | 1070 |
| 1072 // r3, r14: number of arguments including receiver (C callee-saved) | 1071 // r3, r14: number of arguments including receiver (C callee-saved) |
| 1073 // r4: pointer to the first argument | 1072 // r4: pointer to the first argument |
| 1074 // r15: pointer to builtin function (C callee-saved) | 1073 // r15: pointer to builtin function (C callee-saved) |
| 1075 | 1074 |
| 1076 // Result returned in registers or stack, depending on result size and ABI. | 1075 // Result returned in registers or stack, depending on result size and ABI. |
| 1077 | 1076 |
| 1078 Register isolate_reg = r5; | 1077 Register isolate_reg = r5; |
| 1079 #if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS | 1078 if (needs_return_buffer) { |
| 1080 if (result_size() > 1) { | 1079 // The return value is a non-scalar value. |
| 1081 // The return value is 16-byte non-scalar value. | |
| 1082 // Use frame storage reserved by calling function to pass return | 1080 // Use frame storage reserved by calling function to pass return |
| 1083 // buffer as implicit first argument. | 1081 // buffer as implicit first argument. |
| 1084 __ mr(r5, r4); | 1082 __ mr(r5, r4); |
| 1085 __ mr(r4, r3); | 1083 __ mr(r4, r3); |
| 1086 __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize)); | 1084 __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize)); |
| 1087 isolate_reg = r6; | 1085 isolate_reg = r6; |
| 1088 } | 1086 } |
| 1089 #endif | |
| 1090 | 1087 |
| 1091 // Call C built-in. | 1088 // Call C built-in. |
| 1092 __ mov(isolate_reg, Operand(ExternalReference::isolate_address(isolate()))); | 1089 __ mov(isolate_reg, Operand(ExternalReference::isolate_address(isolate()))); |
| 1093 | 1090 |
| 1094 Register target = r15; | 1091 Register target = r15; |
| 1095 #if ABI_USES_FUNCTION_DESCRIPTORS && !defined(USE_SIMULATOR) | 1092 #if ABI_USES_FUNCTION_DESCRIPTORS && !defined(USE_SIMULATOR) |
| 1096 // Native AIX/PPC64 Linux use a function descriptor. | 1093 // Native AIX/PPC64 Linux use a function descriptor. |
| 1097 __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(r15, kPointerSize)); | 1094 __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(r15, kPointerSize)); |
| 1098 __ LoadP(ip, MemOperand(r15, 0)); // Instruction address | 1095 __ LoadP(ip, MemOperand(r15, 0)); // Instruction address |
| 1099 target = ip; | 1096 target = ip; |
| 1100 #elif ABI_CALL_VIA_IP | 1097 #elif ABI_CALL_VIA_IP |
| 1101 __ Move(ip, r15); | 1098 __ Move(ip, r15); |
| 1102 target = ip; | 1099 target = ip; |
| 1103 #endif | 1100 #endif |
| 1104 | 1101 |
| 1105 // To let the GC traverse the return address of the exit frames, we need to | 1102 // To let the GC traverse the return address of the exit frames, we need to |
| 1106 // know where the return address is. The CEntryStub is unmovable, so | 1103 // know where the return address is. The CEntryStub is unmovable, so |
| 1107 // we can store the address on the stack to be able to find it again and | 1104 // we can store the address on the stack to be able to find it again and |
| 1108 // we never have to restore it, because it will not change. | 1105 // we never have to restore it, because it will not change. |
| 1109 Label after_call; | 1106 Label after_call; |
| 1110 __ mov_label_addr(r0, &after_call); | 1107 __ mov_label_addr(r0, &after_call); |
| 1111 __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); | 1108 __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); |
| 1112 __ Call(target); | 1109 __ Call(target); |
| 1113 __ bind(&after_call); | 1110 __ bind(&after_call); |
| 1114 | 1111 |
| 1115 #if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS | |
| 1116 // If return value is on the stack, pop it to registers. | 1112 // If return value is on the stack, pop it to registers. |
| 1117 if (result_size() > 1) { | 1113 if (needs_return_buffer) { |
| 1114 if (result_size() > 2) __ LoadP(r5, MemOperand(r3, 2 * kPointerSize)); |
| 1118 __ LoadP(r4, MemOperand(r3, kPointerSize)); | 1115 __ LoadP(r4, MemOperand(r3, kPointerSize)); |
| 1119 __ LoadP(r3, MemOperand(r3)); | 1116 __ LoadP(r3, MemOperand(r3)); |
| 1120 } | 1117 } |
| 1121 #endif | |
| 1122 | 1118 |
| 1123 // Check result for exception sentinel. | 1119 // Check result for exception sentinel. |
| 1124 Label exception_returned; | 1120 Label exception_returned; |
| 1125 __ CompareRoot(r3, Heap::kExceptionRootIndex); | 1121 __ CompareRoot(r3, Heap::kExceptionRootIndex); |
| 1126 __ beq(&exception_returned); | 1122 __ beq(&exception_returned); |
| 1127 | 1123 |
| 1128 // Check that there is no pending exception, otherwise we | 1124 // Check that there is no pending exception, otherwise we |
| 1129 // should have returned the exception sentinel. | 1125 // should have returned the exception sentinel. |
| 1130 if (FLAG_debug_code) { | 1126 if (FLAG_debug_code) { |
| 1131 Label okay; | 1127 Label okay; |
| 1132 ExternalReference pending_exception_address( | 1128 ExternalReference pending_exception_address( |
| 1133 Isolate::kPendingExceptionAddress, isolate()); | 1129 Isolate::kPendingExceptionAddress, isolate()); |
| 1134 | 1130 |
| 1135 __ mov(r5, Operand(pending_exception_address)); | 1131 __ mov(r6, Operand(pending_exception_address)); |
| 1136 __ LoadP(r5, MemOperand(r5)); | 1132 __ LoadP(r6, MemOperand(r6)); |
| 1137 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); | 1133 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); |
| 1138 // Cannot use check here as it attempts to generate call into runtime. | 1134 // Cannot use check here as it attempts to generate call into runtime. |
| 1139 __ beq(&okay); | 1135 __ beq(&okay); |
| 1140 __ stop("Unexpected pending exception"); | 1136 __ stop("Unexpected pending exception"); |
| 1141 __ bind(&okay); | 1137 __ bind(&okay); |
| 1142 } | 1138 } |
| 1143 | 1139 |
| 1144 // Exit C frame and return. | 1140 // Exit C frame and return. |
| 1145 // r3:r4: result | 1141 // r3:r4: result |
| 1146 // sp: stack pointer | 1142 // sp: stack pointer |
| 1147 // fp: frame pointer | 1143 // fp: frame pointer |
| (...skipping 4509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5657 kStackUnwindSpace, NULL, | 5653 kStackUnwindSpace, NULL, |
| 5658 MemOperand(fp, 6 * kPointerSize), NULL); | 5654 MemOperand(fp, 6 * kPointerSize), NULL); |
| 5659 } | 5655 } |
| 5660 | 5656 |
| 5661 | 5657 |
| 5662 #undef __ | 5658 #undef __ |
| 5663 } // namespace internal | 5659 } // namespace internal |
| 5664 } // namespace v8 | 5660 } // namespace v8 |
| 5665 | 5661 |
| 5666 #endif // V8_TARGET_ARCH_PPC | 5662 #endif // V8_TARGET_ARCH_PPC |
| OLD | NEW |