1
// Copyright 2012 the V8 project authors. All rights reserved.
3
// Copyright IBM Corp. 2012, 2013. All rights reserved.
5
// Redistribution and use in source and binary forms, with or without
6
// modification, are permitted provided that the following conditions are
9
// * Redistributions of source code must retain the above copyright
10
// notice, this list of conditions and the following disclaimer.
11
// * Redistributions in binary form must reproduce the above
12
// copyright notice, this list of conditions and the following
13
// disclaimer in the documentation and/or other materials provided
14
// with the distribution.
15
// * Neither the name of Google Inc. nor the names of its
16
// contributors may be used to endorse or promote products derived
17
// from this software without specific prior written permission.
19
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
#if defined(V8_TARGET_ARCH_PPC)
41
#ifdef ENABLE_DEBUGGER_SUPPORT
42
bool BreakLocationIterator::IsDebugBreakAtReturn() {
43
return Debug::IsDebugBreakAtReturn(rinfo());
47
void BreakLocationIterator::SetDebugBreakAtReturn() {
48
// Patch the code changing the return from JS function sequence from
54
// addi sp, sp, <delta>
57
// to a call to the debug break return code.
58
// this uses a FIXED_SEQUENCE to load a 32bit constant
60
// lis r0, <address hi>
61
// ori r0, r0, <address lo>
66
// The 64bit sequence is a bit longer
67
// lis r0, <address bits 63-48>
68
// ori r0, r0, <address bits 47-32>
70
// oris r0, r0, <address bits 31-16>
71
// ori r0, r0, <address bits 15-0>
76
CodePatcher patcher(rinfo()->pc(), Assembler::kJSReturnSequenceInstructions);
77
// printf("SetDebugBreakAtReturn: pc=%08x\n", (unsigned int)rinfo()->pc());
78
patcher.masm()->mov(v8::internal::r0,
79
Operand(reinterpret_cast<intptr_t>(
80
Isolate::Current()->debug()->debug_break_return()->entry())));
81
patcher.masm()->mtlr(v8::internal::r0);
82
patcher.masm()->bclr(BA, SetLK);
83
patcher.masm()->bkpt(0);
87
// Restore the JS frame exit code.
88
void BreakLocationIterator::ClearDebugBreakAtReturn() {
89
rinfo()->PatchCode(original_rinfo()->pc(),
90
Assembler::kJSReturnSequenceInstructions);
94
// A debug break in the frame exit code is identified by the JS frame exit code
95
// having been patched with a call instruction.
96
bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
97
ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()));
98
return rinfo->IsPatchedReturnSequence();
102
bool BreakLocationIterator::IsDebugBreakAtSlot() {
103
ASSERT(IsDebugBreakSlot());
104
// Check whether the debug break slot instructions have been patched.
105
return rinfo()->IsPatchedDebugBreakSlotSequence();
109
void BreakLocationIterator::SetDebugBreakAtSlot() {
110
ASSERT(IsDebugBreakSlot());
111
// Patch the code changing the debug break slot code from
119
// to a call to the debug break code, using a FIXED_SEQUENCE.
121
// lis r0, <address hi>
122
// ori r0, r0, <address lo>
126
// The 64bit sequence is +3 instructions longer for the load
128
CodePatcher patcher(rinfo()->pc(), Assembler::kDebugBreakSlotInstructions);
129
// printf("SetDebugBreakAtSlot: pc=%08x\n", (unsigned int)rinfo()->pc());
130
patcher.masm()->mov(v8::internal::r0,
131
Operand(reinterpret_cast<intptr_t>(
132
Isolate::Current()->debug()->debug_break_slot()->entry())));
133
patcher.masm()->mtlr(v8::internal::r0);
134
patcher.masm()->bclr(BA, SetLK);
138
void BreakLocationIterator::ClearDebugBreakAtSlot() {
139
ASSERT(IsDebugBreakSlot());
140
rinfo()->PatchCode(original_rinfo()->pc(),
141
Assembler::kDebugBreakSlotInstructions);
144
const bool Debug::FramePaddingLayout::kIsSupported = false;
147
#define __ ACCESS_MASM(masm)
150
static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
152
RegList non_object_regs) {
154
FrameScope scope(masm, StackFrame::INTERNAL);
156
// printf("Generate_DebugBreakCallHelper\n");
157
// Store the registers containing live values on the expression stack to
158
// make sure that these are correctly updated during GC. Non object values
159
// are stored as a smi causing it to be untouched by GC.
160
ASSERT((object_regs & ~kJSCallerSaved) == 0);
161
ASSERT((non_object_regs & ~kJSCallerSaved) == 0);
162
ASSERT((object_regs & non_object_regs) == 0);
163
if ((object_regs | non_object_regs) != 0) {
164
for (int i = 0; i < kNumJSCallerSaved; i++) {
165
int r = JSCallerSavedCode(i);
166
Register reg = { r };
167
if ((non_object_regs & (1 << r)) != 0) {
168
if (FLAG_debug_code) {
169
__ andis(r0, reg, Operand(0xc000));
170
__ Assert(eq, "Unable to encode value as smi", cr0);
175
__ MultiPush(object_regs | non_object_regs);
179
__ RecordComment("// Calling from debug break to runtime - come in - over");
181
__ mov(r3, Operand(0, RelocInfo::NONE)); // no arguments
182
__ mov(r4, Operand(ExternalReference::debug_break(masm->isolate())));
187
// Restore the register values from the expression stack.
188
if ((object_regs | non_object_regs) != 0) {
189
__ MultiPop(object_regs | non_object_regs);
190
for (int i = 0; i < kNumJSCallerSaved; i++) {
191
int r = JSCallerSavedCode(i);
192
Register reg = { r };
193
if ((non_object_regs & (1 << r)) != 0) {
196
if (FLAG_debug_code &&
197
(((object_regs |non_object_regs) & (1 << r)) == 0)) {
198
__ mov(reg, Operand(kDebugZapValue));
203
// Leave the internal frame.
206
// Now that the break point has been handled, resume normal execution by
207
// jumping to the target address intended by the caller and that was
208
// overwritten by the address of DebugBreakXXX.
209
ExternalReference after_break_target =
210
ExternalReference(Debug_Address::AfterBreakTarget(), masm->isolate());
211
__ mov(ip, Operand(after_break_target));
212
__ LoadP(ip, MemOperand(ip));
217
void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
218
// Calling convention for IC load (from ic-ppc.cc).
219
// ----------- S t a t e -------------
221
// -- lr : return address
223
// -- [sp] : receiver
224
// -----------------------------------
225
// Registers r3 and r5 contain objects that need to be pushed on the
226
// expression stack of the fake JS frame.
227
Generate_DebugBreakCallHelper(masm, r3.bit() | r5.bit(), 0);
231
void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
232
// Calling convention for IC store (from ic-ppc.cc).
233
// ----------- S t a t e -------------
237
// -- lr : return address
238
// -----------------------------------
239
// Registers r3, r4, and r5 contain objects that need to be pushed on the
240
// expression stack of the fake JS frame.
241
Generate_DebugBreakCallHelper(masm, r3.bit() | r4.bit() | r5.bit(), 0);
245
void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
246
// ---------- S t a t e --------------
247
// -- lr : return address
250
Generate_DebugBreakCallHelper(masm, r3.bit() | r4.bit(), 0);
254
void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
255
// ---------- S t a t e --------------
259
// -- lr : return address
260
Generate_DebugBreakCallHelper(masm, r3.bit() | r4.bit() | r5.bit(), 0);
264
void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
265
// Calling convention for IC call (from ic-ppc.cc)
266
// ----------- S t a t e -------------
268
// -----------------------------------
269
Generate_DebugBreakCallHelper(masm, r5.bit(), 0);
273
void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) {
274
// In places other than IC call sites it is expected that r3 is TOS which
275
// is an object - this is not generally the case so this should be used with
277
Generate_DebugBreakCallHelper(masm, r3.bit(), 0);
281
void Debug::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) {
282
// Register state for CallFunctionStub (from code-stubs-ppc.cc).
283
// ----------- S t a t e -------------
285
// -----------------------------------
286
Generate_DebugBreakCallHelper(masm, r4.bit(), 0);
290
void Debug::GenerateCallFunctionStubRecordDebugBreak(MacroAssembler* masm) {
291
// Register state for CallFunctionStub (from code-stubs-ppc.cc).
292
// ----------- S t a t e -------------
294
// -- r5 : cache cell for call target
295
// -----------------------------------
296
Generate_DebugBreakCallHelper(masm, r4.bit() | r5.bit(), 0);
300
void Debug::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) {
301
// Calling convention for CallConstructStub (from code-stubs-ppc.cc)
302
// ----------- S t a t e -------------
303
// -- r3 : number of arguments (not smi)
304
// -- r4 : constructor function
305
// -----------------------------------
306
Generate_DebugBreakCallHelper(masm, r4.bit(), r3.bit());
310
void Debug::GenerateCallConstructStubRecordDebugBreak(MacroAssembler* masm) {
311
// Calling convention for CallConstructStub (from code-stubs-ppc.cc)
312
// ----------- S t a t e -------------
313
// -- r3 : number of arguments (not smi)
314
// -- r4 : constructor function
315
// -- r5 : cache cell for call target
316
// -----------------------------------
317
Generate_DebugBreakCallHelper(masm, r4.bit() | r5.bit(), r3.bit());
321
void Debug::GenerateSlot(MacroAssembler* masm) {
322
// Generate enough nop's to make space for a call instruction. Avoid emitting
323
// the trampoline pool in the debug break slot code.
324
Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm);
325
Label check_codesize;
326
__ bind(&check_codesize);
327
__ RecordDebugBreakSlot();
328
for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
329
__ nop(MacroAssembler::DEBUG_BREAK_NOP);
331
ASSERT_EQ(Assembler::kDebugBreakSlotInstructions,
332
masm->InstructionsGeneratedSince(&check_codesize));
336
void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) {
337
// In the places where a debug break slot is inserted no registers can contain
339
Generate_DebugBreakCallHelper(masm, 0, 0);
343
void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
344
masm->Abort("LiveEdit frame dropping is not supported on ppc");
348
void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
349
masm->Abort("LiveEdit frame dropping is not supported on ppc");
352
const bool Debug::kFrameDropperSupported = false;
358
#endif // ENABLE_DEBUGGER_SUPPORT
360
} } // namespace v8::internal
362
#endif // V8_TARGET_ARCH_PPC