Commit 96a333d9 authored by mbrandy's avatar mbrandy Committed by Commit bot

PPC: Cleanup ABI-specifc code.

Where possible:
- eliminate special-case code generation for simulator.
- eliminate #ifdefs.

R=joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=

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

Cr-Commit-Position: refs/heads/master@{#33407}
parent 4efbeac1
......@@ -1504,14 +1504,14 @@ void Assembler::divdu(Register dst, Register src1, Register src2, OEBit o,
// Code address skips the function descriptor "header".
// TOC and static chain are ignored and set to 0.
void Assembler::function_descriptor() {
#if ABI_USES_FUNCTION_DESCRIPTORS
Label instructions;
DCHECK(pc_offset() == 0);
emit_label_addr(&instructions);
dp(0);
dp(0);
bind(&instructions);
#endif
if (ABI_USES_FUNCTION_DESCRIPTORS) {
Label instructions;
DCHECK(pc_offset() == 0);
emit_label_addr(&instructions);
dp(0);
dp(0);
bind(&instructions);
}
}
......
......@@ -46,12 +46,18 @@
#include "src/assembler.h"
#include "src/ppc/constants-ppc.h"
#define ABI_USES_FUNCTION_DESCRIPTORS \
(V8_HOST_ARCH_PPC && (V8_OS_AIX || \
(V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN)))
#if V8_HOST_ARCH_PPC && \
(V8_OS_AIX || (V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN))
#define ABI_USES_FUNCTION_DESCRIPTORS 1
#else
#define ABI_USES_FUNCTION_DESCRIPTORS 0
#endif
#define ABI_PASSES_HANDLES_IN_REGS \
(!V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64)
#if !V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64
#define ABI_PASSES_HANDLES_IN_REGS 1
#else
#define ABI_PASSES_HANDLES_IN_REGS 0
#endif
#if !V8_HOST_ARCH_PPC || !V8_TARGET_ARCH_PPC64 || V8_TARGET_LITTLE_ENDIAN
#define ABI_RETURNS_OBJECT_PAIRS_IN_REGS 1
......@@ -66,9 +72,9 @@
#endif
#if !V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64
#define ABI_TOC_REGISTER Register::kCode_r2
#define ABI_TOC_REGISTER 2
#else
#define ABI_TOC_REGISTER Register::kCode_r13
#define ABI_TOC_REGISTER 13
#endif
#define INSTR_AND_DATA_CACHE_COHERENCY LWSYNC
......
......@@ -1089,15 +1089,15 @@ void CEntryStub::Generate(MacroAssembler* masm) {
__ mov(isolate_reg, Operand(ExternalReference::isolate_address(isolate())));
Register target = r15;
#if ABI_USES_FUNCTION_DESCRIPTORS && !defined(USE_SIMULATOR)
// Native AIX/PPC64 Linux use a function descriptor.
__ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(r15, kPointerSize));
__ LoadP(ip, MemOperand(r15, 0)); // Instruction address
target = ip;
#elif ABI_CALL_VIA_IP
__ Move(ip, r15);
target = ip;
#endif
if (ABI_USES_FUNCTION_DESCRIPTORS) {
// AIX/PPC64BE Linux use a function descriptor.
__ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(r15, kPointerSize));
__ LoadP(ip, MemOperand(r15, 0)); // Instruction address
target = ip;
} else if (ABI_CALL_VIA_IP) {
__ Move(ip, r15);
target = ip;
}
// To let the GC traverse the return address of the exit frames, we need to
// know where the return address is. The CEntryStub is unmovable, so
......@@ -2251,16 +2251,6 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
// Locate the code entry and call it.
__ addi(code, code, Operand(Code::kHeaderSize - kHeapObjectTag));
#if ABI_USES_FUNCTION_DESCRIPTORS && defined(USE_SIMULATOR)
// Even Simulated AIX/PPC64 Linux uses a function descriptor for the
// RegExp routine. Extract the instruction address here since
// DirectCEntryStub::GenerateCall will not do it for calls out to
// what it thinks is C code compiled for the simulator/host
// platform.
__ LoadP(code, MemOperand(code, 0)); // Instruction address
#endif
DirectCEntryStub stub(isolate());
stub.GenerateCall(masm, code);
......@@ -3816,15 +3806,15 @@ void DirectCEntryStub::Generate(MacroAssembler* masm) {
void DirectCEntryStub::GenerateCall(MacroAssembler* masm, Register target) {
#if ABI_USES_FUNCTION_DESCRIPTORS && !defined(USE_SIMULATOR)
// Native AIX/PPC64 Linux use a function descriptor.
__ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(target, kPointerSize));
__ LoadP(ip, MemOperand(target, 0)); // Instruction address
#else
// ip needs to be set for DirectCEentryStub::Generate, and also
// for ABI_CALL_VIA_IP.
__ Move(ip, target);
#endif
if (ABI_USES_FUNCTION_DESCRIPTORS) {
// AIX/PPC64BE Linux use a function descriptor.
__ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(target, kPointerSize));
__ LoadP(ip, MemOperand(target, 0)); // Instruction address
} else {
// ip needs to be set for DirectCEentryStub::Generate, and also
// for ABI_CALL_VIA_IP.
__ Move(ip, target);
}
intptr_t code = reinterpret_cast<intptr_t>(GetCode().location());
__ mov(r0, Operand(code, RelocInfo::CODE_TARGET));
......@@ -4787,34 +4777,32 @@ void ProfileEntryHookStub::Generate(MacroAssembler* masm) {
#if !defined(USE_SIMULATOR)
uintptr_t entry_hook =
reinterpret_cast<uintptr_t>(isolate()->function_entry_hook());
__ mov(ip, Operand(entry_hook));
#else
// Under the simulator we need to indirect the entry hook through a
// trampoline function at a known address.
ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline));
ExternalReference entry_hook = ExternalReference(
&dispatcher, ExternalReference::BUILTIN_CALL, isolate());
#if ABI_USES_FUNCTION_DESCRIPTORS
// Function descriptor
__ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(ip, kPointerSize));
__ LoadP(ip, MemOperand(ip, 0));
#elif ABI_CALL_VIA_IP
// ip set above, so nothing to do.
// It additionally takes an isolate as a third parameter
__ mov(r5, Operand(ExternalReference::isolate_address(isolate())));
#endif
__ mov(ip, Operand(entry_hook));
if (ABI_USES_FUNCTION_DESCRIPTORS) {
__ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(ip, kPointerSize));
__ LoadP(ip, MemOperand(ip, 0));
}
// ip set above, so nothing more to do for ABI_CALL_VIA_IP.
// PPC LINUX ABI:
__ li(r0, Operand::Zero());
__ StorePU(r0, MemOperand(sp, -kNumRequiredStackFrameSlots * kPointerSize));
#else
// Under the simulator we need to indirect the entry hook through a
// trampoline function at a known address.
// It additionally takes an isolate as a third parameter
__ mov(r5, Operand(ExternalReference::isolate_address(isolate())));
ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline));
__ mov(ip, Operand(ExternalReference(
&dispatcher, ExternalReference::BUILTIN_CALL, isolate())));
#endif
__ Call(ip);
#if !defined(USE_SIMULATOR)
__ addi(sp, sp, Operand(kNumRequiredStackFrameSlots * kPointerSize));
#endif
// Restore the stack pointer if needed.
if (frame_alignment > kPointerSize) {
......@@ -5604,6 +5592,9 @@ void CallApiGetterStub::Generate(MacroAssembler* masm) {
// -----------------------------------
Register api_function_address = ApiGetterDescriptor::function_address();
int arg0Slot = 0;
int accessorInfoSlot = 0;
int apiStackSpace = 0;
DCHECK(api_function_address.is(r5));
__ mr(r3, sp); // r0 = Handle<Name>
......@@ -5621,29 +5612,29 @@ void CallApiGetterStub::Generate(MacroAssembler* masm) {
// [0] space for DirectCEntryStub's LR save
// [1] copy of Handle (first arg)
// [2] AccessorInfo&
#if ABI_PASSES_HANDLES_IN_REGS
const int kAccessorInfoSlot = kStackFrameExtraParamSlot + 1;
const int kApiStackSpace = 2;
#else
const int kArg0Slot = kStackFrameExtraParamSlot + 1;
const int kAccessorInfoSlot = kArg0Slot + 1;
const int kApiStackSpace = 3;
#endif
if (ABI_PASSES_HANDLES_IN_REGS) {
accessorInfoSlot = kStackFrameExtraParamSlot + 1;
apiStackSpace = 2;
} else {
arg0Slot = kStackFrameExtraParamSlot + 1;
accessorInfoSlot = arg0Slot + 1;
apiStackSpace = 3;
}
FrameScope frame_scope(masm, StackFrame::MANUAL);
__ EnterExitFrame(false, kApiStackSpace);
__ EnterExitFrame(false, apiStackSpace);
#if !ABI_PASSES_HANDLES_IN_REGS
// pass 1st arg by reference
__ StoreP(r3, MemOperand(sp, kArg0Slot * kPointerSize));
__ addi(r3, sp, Operand(kArg0Slot * kPointerSize));
#endif
if (!ABI_PASSES_HANDLES_IN_REGS) {
// pass 1st arg by reference
__ StoreP(r3, MemOperand(sp, arg0Slot * kPointerSize));
__ addi(r3, sp, Operand(arg0Slot * kPointerSize));
}
// Create PropertyAccessorInfo instance on the stack above the exit frame with
// r4 (internal::Object** args_) as the data.
__ StoreP(r4, MemOperand(sp, kAccessorInfoSlot * kPointerSize));
__ StoreP(r4, MemOperand(sp, accessorInfoSlot * kPointerSize));
// r4 = AccessorInfo&
__ addi(r4, sp, Operand(kAccessorInfoSlot * kPointerSize));
__ addi(r4, sp, Operand(accessorInfoSlot * kPointerSize));
const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
......
......@@ -58,9 +58,7 @@ UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) {
CodeDesc desc;
masm.GetCode(&desc);
#if !ABI_USES_FUNCTION_DESCRIPTORS
DCHECK(!RelocInfo::RequiresRelocation(desc));
#endif
DCHECK(ABI_USES_FUNCTION_DESCRIPTORS || !RelocInfo::RequiresRelocation(desc));
Assembler::FlushICache(isolate, buffer, actual_size);
base::OS::ProtectCode(buffer, actual_size);
......@@ -96,9 +94,7 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
CodeDesc desc;
masm.GetCode(&desc);
#if !ABI_USES_FUNCTION_DESCRIPTORS
DCHECK(!RelocInfo::RequiresRelocation(desc));
#endif
DCHECK(ABI_USES_FUNCTION_DESCRIPTORS || !RelocInfo::RequiresRelocation(desc));
Assembler::FlushICache(isolate, buffer, actual_size);
base::OS::ProtectCode(buffer, actual_size);
......
......@@ -1073,14 +1073,12 @@ int Decoder::InstructionDecode(byte* instr_ptr) {
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%08x ",
instr->InstructionBits());
#if ABI_USES_FUNCTION_DESCRIPTORS
// The first field will be identified as a jump table entry. We emit the rest
// of the structure as zero, so just skip past them.
if (instr->InstructionBits() == 0) {
if (ABI_USES_FUNCTION_DESCRIPTORS && instr->InstructionBits() == 0) {
// The first field will be identified as a jump table entry. We
// emit the rest of the structure as zero, so just skip past them.
Format(instr, "constant");
return Instruction::kInstrSize;
}
#endif
switch (instr->OpcodeValue() << 26) {
case TWI: {
......
......@@ -3087,20 +3087,21 @@ void MacroAssembler::CallCFunctionHelper(Register function,
int num_reg_arguments,
int num_double_arguments) {
DCHECK(has_frame());
// Just call directly. The function called cannot cause a GC, or
// allow preemption, so the return address in the link register
// stays correct.
// Just call directly. The function called cannot cause a GC, or
// allow preemption, so the return address in the link register
// stays correct.
Register dest = function;
#if ABI_USES_FUNCTION_DESCRIPTORS && !defined(USE_SIMULATOR)
// AIX uses a function descriptor. When calling C code be aware
// of this descriptor and pick up values from it
LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(function, kPointerSize));
LoadP(ip, MemOperand(function, 0));
dest = ip;
#elif ABI_CALL_VIA_IP
Move(ip, function);
dest = ip;
#endif
if (ABI_USES_FUNCTION_DESCRIPTORS) {
// AIX/PPC64BE Linux uses a function descriptor. When calling C code be
// aware of this descriptor and pick up values from it
LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(function, kPointerSize));
LoadP(ip, MemOperand(function, 0));
dest = ip;
} else if (ABI_CALL_VIA_IP) {
Move(ip, function);
dest = ip;
}
Call(dest);
......
......@@ -856,10 +856,19 @@ class Redirection {
isolate->simulator_i_cache(),
reinterpret_cast<void*>(&swi_instruction_), Instruction::kInstrSize);
isolate->set_simulator_redirection(this);
if (ABI_USES_FUNCTION_DESCRIPTORS) {
function_descriptor_[0] = reinterpret_cast<intptr_t>(&swi_instruction_);
function_descriptor_[1] = 0;
function_descriptor_[2] = 0;
}
}
void* address_of_swi_instruction() {
return reinterpret_cast<void*>(&swi_instruction_);
void* address() {
if (ABI_USES_FUNCTION_DESCRIPTORS) {
return reinterpret_cast<void*>(function_descriptor_);
} else {
return reinterpret_cast<void*>(&swi_instruction_);
}
}
void* external_function() { return external_function_; }
......@@ -884,9 +893,16 @@ class Redirection {
return reinterpret_cast<Redirection*>(addr_of_redirection);
}
static Redirection* FromAddress(void* address) {
int delta = ABI_USES_FUNCTION_DESCRIPTORS
? offsetof(Redirection, function_descriptor_)
: offsetof(Redirection, swi_instruction_);
char* addr_of_redirection = reinterpret_cast<char*>(address) - delta;
return reinterpret_cast<Redirection*>(addr_of_redirection);
}
static void* ReverseRedirection(intptr_t reg) {
Redirection* redirection = FromSwiInstruction(
reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg)));
Redirection* redirection = FromAddress(reinterpret_cast<void*>(reg));
return redirection->external_function();
}
......@@ -903,6 +919,7 @@ class Redirection {
uint32_t swi_instruction_;
ExternalReference::Type type_;
Redirection* next_;
intptr_t function_descriptor_[3];
};
......@@ -923,7 +940,7 @@ void* Simulator::RedirectExternalReference(Isolate* isolate,
void* external_function,
ExternalReference::Type type) {
Redirection* redirection = Redirection::Get(isolate, external_function, type);
return redirection->address_of_swi_instruction();
return redirection->address();
}
......@@ -1386,9 +1403,9 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
CHECK(stack_aligned);
SimulatorRuntimeDirectGetterCall target =
reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
#if !ABI_PASSES_HANDLES_IN_REGS
arg[0] = *(reinterpret_cast<intptr_t*>(arg[0]));
#endif
if (!ABI_PASSES_HANDLES_IN_REGS) {
arg[0] = *(reinterpret_cast<intptr_t*>(arg[0]));
}
target(arg[0], arg[1]);
} else if (redirection->type() ==
ExternalReference::PROFILING_GETTER_CALL) {
......@@ -1405,9 +1422,9 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
CHECK(stack_aligned);
SimulatorRuntimeProfilingGetterCall target =
reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
#if !ABI_PASSES_HANDLES_IN_REGS
arg[0] = *(reinterpret_cast<intptr_t*>(arg[0]));
#endif
if (!ABI_PASSES_HANDLES_IN_REGS) {
arg[0] = *(reinterpret_cast<intptr_t*>(arg[0]));
}
target(arg[0], arg[1], Redirection::ReverseRedirection(arg[2]));
} else {
// builtin call.
......@@ -3866,17 +3883,19 @@ void Simulator::CallInternal(byte* entry) {
// Adjust JS-based stack limit to C-based stack limit.
isolate_->stack_guard()->AdjustStackLimitForSimulator();
// Prepare to execute the code at entry
#if ABI_USES_FUNCTION_DESCRIPTORS
// entry is the function descriptor
set_pc(*(reinterpret_cast<intptr_t*>(entry)));
#else
// entry is the instruction address
set_pc(reinterpret_cast<intptr_t>(entry));
#endif
// Prepare to execute the code at entry
if (ABI_USES_FUNCTION_DESCRIPTORS) {
// entry is the function descriptor
set_pc(*(reinterpret_cast<intptr_t*>(entry)));
} else {
// entry is the instruction address
set_pc(reinterpret_cast<intptr_t>(entry));
}
// Put target address in ip (for JS prologue).
set_register(r12, get_pc());
if (ABI_CALL_VIA_IP) {
// Put target address in ip (for JS prologue).
set_register(r12, get_pc());
}
// Put down marker for end of simulation. The simulator will stop simulation
// when the PC reaches this value. By saving the "end simulation" value into
......@@ -3933,8 +3952,12 @@ void Simulator::CallInternal(byte* entry) {
Execute();
// Check that the non-volatile registers have been preserved.
CHECK_EQ(callee_saved_value, get_register(r2));
CHECK_EQ(callee_saved_value, get_register(r13));
if (ABI_TOC_REGISTER != 2) {
CHECK_EQ(callee_saved_value, get_register(r2));
}
if (ABI_TOC_REGISTER != 13) {
CHECK_EQ(callee_saved_value, get_register(r13));
}
CHECK_EQ(callee_saved_value, get_register(r14));
CHECK_EQ(callee_saved_value, get_register(r15));
CHECK_EQ(callee_saved_value, get_register(r16));
......
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