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