• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #if V8_TARGET_ARCH_PPC
6 
7 #include "src/regexp/ppc/regexp-macro-assembler-ppc.h"
8 
9 #include "src/base/bits.h"
10 #include "src/code-stubs.h"
11 #include "src/log.h"
12 #include "src/macro-assembler.h"
13 #include "src/regexp/regexp-macro-assembler.h"
14 #include "src/regexp/regexp-stack.h"
15 #include "src/unicode.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 #ifndef V8_INTERPRETED_REGEXP
21 /*
22  * This assembler uses the following register assignment convention
23  * - r25: Temporarily stores the index of capture start after a matching pass
24  *        for a global regexp.
25  * - r26: Pointer to current code object (Code*) including heap object tag.
26  * - r27: Current position in input, as negative offset from end of string.
27  *        Please notice that this is the byte offset, not the character offset!
28  * - r28: Currently loaded character. Must be loaded using
29  *        LoadCurrentCharacter before using any of the dispatch methods.
30  * - r29: Points to tip of backtrack stack
31  * - r30: End of input (points to byte after last character in input).
32  * - r31: Frame pointer. Used to access arguments, local variables and
33  *         RegExp registers.
34  * - r12: IP register, used by assembler. Very volatile.
35  * - r1/sp : Points to tip of C stack.
36  *
37  * The remaining registers are free for computations.
38  * Each call to a public method should retain this convention.
39  *
40  * The stack will have the following structure:
41  *  - fp[44]  Isolate* isolate   (address of the current isolate)
42  *  - fp[40]  secondary link/return address used by native call.
43  *  - fp[36]  lr save area (currently unused)
44  *  - fp[32]  backchain    (currently unused)
45  *  --- sp when called ---
46  *  - fp[28]  return address     (lr).
47  *  - fp[24]  old frame pointer  (r31).
48  *  - fp[0..20]  backup of registers r25..r30
49  *  --- frame pointer ----
50  *  - fp[-4]  direct_call        (if 1, direct call from JavaScript code,
51  *                                if 0, call through the runtime system).
52  *  - fp[-8]  stack_area_base    (high end of the memory area to use as
53  *                                backtracking stack).
54  *  - fp[-12] capture array size (may fit multiple sets of matches)
55  *  - fp[-16] int* capture_array (int[num_saved_registers_], for output).
56  *  - fp[-20] end of input       (address of end of string).
57  *  - fp[-24] start of input     (address of first character in string).
58  *  - fp[-28] start index        (character index of start).
59  *  - fp[-32] void* input_string (location of a handle containing the string).
60  *  - fp[-36] success counter    (only for global regexps to count matches).
61  *  - fp[-40] Offset of location before start of input (effectively character
62  *            string start - 1). Used to initialize capture registers to a
63  *            non-position.
64  *  - fp[-44] At start (if 1, we are starting at the start of the
65  *    string, otherwise 0)
66  *  - fp[-48] register 0         (Only positions must be stored in the first
67  *  -         register 1          num_saved_registers_ registers)
68  *  -         ...
69  *  -         register num_registers-1
70  *  --- sp ---
71  *
72  * The first num_saved_registers_ registers are initialized to point to
73  * "character -1" in the string (i.e., char_size() bytes before the first
74  * character of the string). The remaining registers start out as garbage.
75  *
76  * The data up to the return address must be placed there by the calling
77  * code and the remaining arguments are passed in registers, e.g. by calling the
78  * code entry as cast to a function with the signature:
79  * int (*match)(String* input_string,
80  *              int start_index,
81  *              Address start,
82  *              Address end,
83  *              int* capture_output_array,
84  *              byte* stack_area_base,
85  *              Address secondary_return_address,  // Only used by native call.
86  *              bool direct_call = false)
87  * The call is performed by NativeRegExpMacroAssembler::Execute()
88  * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro
89  * in ppc/simulator-ppc.h.
90  * When calling as a non-direct call (i.e., from C++ code), the return address
91  * area is overwritten with the LR register by the RegExp code. When doing a
92  * direct call from generated code, the return address is placed there by
93  * the calling code, as in a normal exit frame.
94  */
95 
96 #define __ ACCESS_MASM(masm_)
97 
RegExpMacroAssemblerPPC(Isolate * isolate,Zone * zone,Mode mode,int registers_to_save)98 RegExpMacroAssemblerPPC::RegExpMacroAssemblerPPC(Isolate* isolate, Zone* zone,
99                                                  Mode mode,
100                                                  int registers_to_save)
101     : NativeRegExpMacroAssembler(isolate, zone),
102       masm_(new MacroAssembler(isolate, NULL, kRegExpCodeSize,
103                                CodeObjectRequired::kYes)),
104       mode_(mode),
105       num_registers_(registers_to_save),
106       num_saved_registers_(registers_to_save),
107       entry_label_(),
108       start_label_(),
109       success_label_(),
110       backtrack_label_(),
111       exit_label_(),
112       internal_failure_label_() {
113   DCHECK_EQ(0, registers_to_save % 2);
114 
115 // Called from C
116   __ function_descriptor();
117 
118   __ b(&entry_label_);  // We'll write the entry code later.
119   // If the code gets too big or corrupted, an internal exception will be
120   // raised, and we will exit right away.
121   __ bind(&internal_failure_label_);
122   __ li(r3, Operand(FAILURE));
123   __ Ret();
124   __ bind(&start_label_);  // And then continue from here.
125 }
126 
127 
~RegExpMacroAssemblerPPC()128 RegExpMacroAssemblerPPC::~RegExpMacroAssemblerPPC() {
129   delete masm_;
130   // Unuse labels in case we throw away the assembler without calling GetCode.
131   entry_label_.Unuse();
132   start_label_.Unuse();
133   success_label_.Unuse();
134   backtrack_label_.Unuse();
135   exit_label_.Unuse();
136   check_preempt_label_.Unuse();
137   stack_overflow_label_.Unuse();
138   internal_failure_label_.Unuse();
139 }
140 
141 
stack_limit_slack()142 int RegExpMacroAssemblerPPC::stack_limit_slack() {
143   return RegExpStack::kStackLimitSlack;
144 }
145 
146 
AdvanceCurrentPosition(int by)147 void RegExpMacroAssemblerPPC::AdvanceCurrentPosition(int by) {
148   if (by != 0) {
149     __ addi(current_input_offset(), current_input_offset(),
150             Operand(by * char_size()));
151   }
152 }
153 
154 
AdvanceRegister(int reg,int by)155 void RegExpMacroAssemblerPPC::AdvanceRegister(int reg, int by) {
156   DCHECK(reg >= 0);
157   DCHECK(reg < num_registers_);
158   if (by != 0) {
159     __ LoadP(r3, register_location(reg), r0);
160     __ mov(r0, Operand(by));
161     __ add(r3, r3, r0);
162     __ StoreP(r3, register_location(reg), r0);
163   }
164 }
165 
166 
Backtrack()167 void RegExpMacroAssemblerPPC::Backtrack() {
168   CheckPreemption();
169   // Pop Code* offset from backtrack stack, add Code* and jump to location.
170   Pop(r3);
171   __ add(r3, r3, code_pointer());
172   __ Jump(r3);
173 }
174 
175 
Bind(Label * label)176 void RegExpMacroAssemblerPPC::Bind(Label* label) { __ bind(label); }
177 
178 
CheckCharacter(uint32_t c,Label * on_equal)179 void RegExpMacroAssemblerPPC::CheckCharacter(uint32_t c, Label* on_equal) {
180   __ Cmpli(current_character(), Operand(c), r0);
181   BranchOrBacktrack(eq, on_equal);
182 }
183 
184 
CheckCharacterGT(uc16 limit,Label * on_greater)185 void RegExpMacroAssemblerPPC::CheckCharacterGT(uc16 limit, Label* on_greater) {
186   __ Cmpli(current_character(), Operand(limit), r0);
187   BranchOrBacktrack(gt, on_greater);
188 }
189 
190 
CheckAtStart(Label * on_at_start)191 void RegExpMacroAssemblerPPC::CheckAtStart(Label* on_at_start) {
192   __ LoadP(r4, MemOperand(frame_pointer(), kStringStartMinusOne));
193   __ addi(r3, current_input_offset(), Operand(-char_size()));
194   __ cmp(r3, r4);
195   BranchOrBacktrack(eq, on_at_start);
196 }
197 
198 
CheckNotAtStart(int cp_offset,Label * on_not_at_start)199 void RegExpMacroAssemblerPPC::CheckNotAtStart(int cp_offset,
200                                               Label* on_not_at_start) {
201   __ LoadP(r4, MemOperand(frame_pointer(), kStringStartMinusOne));
202   __ addi(r3, current_input_offset(),
203           Operand(-char_size() + cp_offset * char_size()));
204   __ cmp(r3, r4);
205   BranchOrBacktrack(ne, on_not_at_start);
206 }
207 
208 
CheckCharacterLT(uc16 limit,Label * on_less)209 void RegExpMacroAssemblerPPC::CheckCharacterLT(uc16 limit, Label* on_less) {
210   __ Cmpli(current_character(), Operand(limit), r0);
211   BranchOrBacktrack(lt, on_less);
212 }
213 
214 
CheckGreedyLoop(Label * on_equal)215 void RegExpMacroAssemblerPPC::CheckGreedyLoop(Label* on_equal) {
216   Label backtrack_non_equal;
217   __ LoadP(r3, MemOperand(backtrack_stackpointer(), 0));
218   __ cmp(current_input_offset(), r3);
219   __ bne(&backtrack_non_equal);
220   __ addi(backtrack_stackpointer(), backtrack_stackpointer(),
221           Operand(kPointerSize));
222 
223   __ bind(&backtrack_non_equal);
224   BranchOrBacktrack(eq, on_equal);
225 }
226 
CheckNotBackReferenceIgnoreCase(int start_reg,bool read_backward,bool unicode,Label * on_no_match)227 void RegExpMacroAssemblerPPC::CheckNotBackReferenceIgnoreCase(
228     int start_reg, bool read_backward, bool unicode, Label* on_no_match) {
229   Label fallthrough;
230   __ LoadP(r3, register_location(start_reg), r0);  // Index of start of capture
231   __ LoadP(r4, register_location(start_reg + 1), r0);  // Index of end
232   __ sub(r4, r4, r3, LeaveOE, SetRC);                  // Length of capture.
233 
234   // At this point, the capture registers are either both set or both cleared.
235   // If the capture length is zero, then the capture is either empty or cleared.
236   // Fall through in both cases.
237   __ beq(&fallthrough, cr0);
238 
239   // Check that there are enough characters left in the input.
240   if (read_backward) {
241     __ LoadP(r6, MemOperand(frame_pointer(), kStringStartMinusOne));
242     __ add(r6, r6, r4);
243     __ cmp(current_input_offset(), r6);
244     BranchOrBacktrack(le, on_no_match);
245   } else {
246     __ add(r0, r4, current_input_offset(), LeaveOE, SetRC);
247     BranchOrBacktrack(gt, on_no_match, cr0);
248   }
249 
250   if (mode_ == LATIN1) {
251     Label success;
252     Label fail;
253     Label loop_check;
254 
255     // r3 - offset of start of capture
256     // r4 - length of capture
257     __ add(r3, r3, end_of_input_address());
258     __ add(r5, end_of_input_address(), current_input_offset());
259     if (read_backward) {
260       __ sub(r5, r5, r4);  // Offset by length when matching backwards.
261     }
262     __ add(r4, r3, r4);
263 
264     // r3 - Address of start of capture.
265     // r4 - Address of end of capture
266     // r5 - Address of current input position.
267 
268     Label loop;
269     __ bind(&loop);
270     __ lbz(r6, MemOperand(r3));
271     __ addi(r3, r3, Operand(char_size()));
272     __ lbz(r25, MemOperand(r5));
273     __ addi(r5, r5, Operand(char_size()));
274     __ cmp(r25, r6);
275     __ beq(&loop_check);
276 
277     // Mismatch, try case-insensitive match (converting letters to lower-case).
278     __ ori(r6, r6, Operand(0x20));  // Convert capture character to lower-case.
279     __ ori(r25, r25, Operand(0x20));  // Also convert input character.
280     __ cmp(r25, r6);
281     __ bne(&fail);
282     __ subi(r6, r6, Operand('a'));
283     __ cmpli(r6, Operand('z' - 'a'));  // Is r6 a lowercase letter?
284     __ ble(&loop_check);               // In range 'a'-'z'.
285     // Latin-1: Check for values in range [224,254] but not 247.
286     __ subi(r6, r6, Operand(224 - 'a'));
287     __ cmpli(r6, Operand(254 - 224));
288     __ bgt(&fail);                    // Weren't Latin-1 letters.
289     __ cmpi(r6, Operand(247 - 224));  // Check for 247.
290     __ beq(&fail);
291 
292     __ bind(&loop_check);
293     __ cmp(r3, r4);
294     __ blt(&loop);
295     __ b(&success);
296 
297     __ bind(&fail);
298     BranchOrBacktrack(al, on_no_match);
299 
300     __ bind(&success);
301     // Compute new value of character position after the matched part.
302     __ sub(current_input_offset(), r5, end_of_input_address());
303     if (read_backward) {
304       __ LoadP(r3, register_location(start_reg));  // Index of start of capture
305       __ LoadP(r4,
306                register_location(start_reg + 1));  // Index of end of capture
307       __ add(current_input_offset(), current_input_offset(), r3);
308       __ sub(current_input_offset(), current_input_offset(), r4);
309     }
310   } else {
311     DCHECK(mode_ == UC16);
312     int argument_count = 4;
313     __ PrepareCallCFunction(argument_count, r5);
314 
315     // r3 - offset of start of capture
316     // r4 - length of capture
317 
318     // Put arguments into arguments registers.
319     // Parameters are
320     //   r3: Address byte_offset1 - Address captured substring's start.
321     //   r4: Address byte_offset2 - Address of current character position.
322     //   r5: size_t byte_length - length of capture in bytes(!)
323     //   r6: Isolate* isolate or 0 if unicode flag.
324 
325     // Address of start of capture.
326     __ add(r3, r3, end_of_input_address());
327     // Length of capture.
328     __ mr(r5, r4);
329     // Save length in callee-save register for use on return.
330     __ mr(r25, r4);
331     // Address of current input position.
332     __ add(r4, current_input_offset(), end_of_input_address());
333     if (read_backward) {
334       __ sub(r4, r4, r25);
335     }
336     // Isolate.
337 #ifdef V8_I18N_SUPPORT
338     if (unicode) {
339       __ li(r6, Operand::Zero());
340     } else  // NOLINT
341 #endif      // V8_I18N_SUPPORT
342     {
343       __ mov(r6, Operand(ExternalReference::isolate_address(isolate())));
344     }
345 
346     {
347       AllowExternalCallThatCantCauseGC scope(masm_);
348       ExternalReference function =
349           ExternalReference::re_case_insensitive_compare_uc16(isolate());
350       __ CallCFunction(function, argument_count);
351     }
352 
353     // Check if function returned non-zero for success or zero for failure.
354     __ cmpi(r3, Operand::Zero());
355     BranchOrBacktrack(eq, on_no_match);
356 
357     // On success, advance position by length of capture.
358     if (read_backward) {
359       __ sub(current_input_offset(), current_input_offset(), r25);
360     } else {
361       __ add(current_input_offset(), current_input_offset(), r25);
362     }
363   }
364 
365   __ bind(&fallthrough);
366 }
367 
368 
CheckNotBackReference(int start_reg,bool read_backward,Label * on_no_match)369 void RegExpMacroAssemblerPPC::CheckNotBackReference(int start_reg,
370                                                     bool read_backward,
371                                                     Label* on_no_match) {
372   Label fallthrough;
373   Label success;
374 
375   // Find length of back-referenced capture.
376   __ LoadP(r3, register_location(start_reg), r0);
377   __ LoadP(r4, register_location(start_reg + 1), r0);
378   __ sub(r4, r4, r3, LeaveOE, SetRC);  // Length to check.
379 
380   // At this point, the capture registers are either both set or both cleared.
381   // If the capture length is zero, then the capture is either empty or cleared.
382   // Fall through in both cases.
383   __ beq(&fallthrough, cr0);
384 
385   // Check that there are enough characters left in the input.
386   if (read_backward) {
387     __ LoadP(r6, MemOperand(frame_pointer(), kStringStartMinusOne));
388     __ add(r6, r6, r4);
389     __ cmp(current_input_offset(), r6);
390     BranchOrBacktrack(lt, on_no_match);
391   } else {
392     __ add(r0, r4, current_input_offset(), LeaveOE, SetRC);
393     BranchOrBacktrack(gt, on_no_match, cr0);
394   }
395 
396   // r3 - offset of start of capture
397   // r4 - length of capture
398   __ add(r3, r3, end_of_input_address());
399   __ add(r5, end_of_input_address(), current_input_offset());
400   if (read_backward) {
401     __ sub(r5, r5, r4);  // Offset by length when matching backwards.
402   }
403   __ add(r4, r4, r3);
404 
405   Label loop;
406   __ bind(&loop);
407   if (mode_ == LATIN1) {
408     __ lbz(r6, MemOperand(r3));
409     __ addi(r3, r3, Operand(char_size()));
410     __ lbz(r25, MemOperand(r5));
411     __ addi(r5, r5, Operand(char_size()));
412   } else {
413     DCHECK(mode_ == UC16);
414     __ lhz(r6, MemOperand(r3));
415     __ addi(r3, r3, Operand(char_size()));
416     __ lhz(r25, MemOperand(r5));
417     __ addi(r5, r5, Operand(char_size()));
418   }
419   __ cmp(r6, r25);
420   BranchOrBacktrack(ne, on_no_match);
421   __ cmp(r3, r4);
422   __ blt(&loop);
423 
424   // Move current character position to position after match.
425   __ sub(current_input_offset(), r5, end_of_input_address());
426   if (read_backward) {
427     __ LoadP(r3, register_location(start_reg));  // Index of start of capture
428     __ LoadP(r4, register_location(start_reg + 1));  // Index of end of capture
429     __ add(current_input_offset(), current_input_offset(), r3);
430     __ sub(current_input_offset(), current_input_offset(), r4);
431   }
432 
433   __ bind(&fallthrough);
434 }
435 
436 
CheckNotCharacter(unsigned c,Label * on_not_equal)437 void RegExpMacroAssemblerPPC::CheckNotCharacter(unsigned c,
438                                                 Label* on_not_equal) {
439   __ Cmpli(current_character(), Operand(c), r0);
440   BranchOrBacktrack(ne, on_not_equal);
441 }
442 
443 
CheckCharacterAfterAnd(uint32_t c,uint32_t mask,Label * on_equal)444 void RegExpMacroAssemblerPPC::CheckCharacterAfterAnd(uint32_t c, uint32_t mask,
445                                                      Label* on_equal) {
446   __ mov(r0, Operand(mask));
447   if (c == 0) {
448     __ and_(r3, current_character(), r0, SetRC);
449   } else {
450     __ and_(r3, current_character(), r0);
451     __ Cmpli(r3, Operand(c), r0, cr0);
452   }
453   BranchOrBacktrack(eq, on_equal, cr0);
454 }
455 
456 
CheckNotCharacterAfterAnd(unsigned c,unsigned mask,Label * on_not_equal)457 void RegExpMacroAssemblerPPC::CheckNotCharacterAfterAnd(unsigned c,
458                                                         unsigned mask,
459                                                         Label* on_not_equal) {
460   __ mov(r0, Operand(mask));
461   if (c == 0) {
462     __ and_(r3, current_character(), r0, SetRC);
463   } else {
464     __ and_(r3, current_character(), r0);
465     __ Cmpli(r3, Operand(c), r0, cr0);
466   }
467   BranchOrBacktrack(ne, on_not_equal, cr0);
468 }
469 
470 
CheckNotCharacterAfterMinusAnd(uc16 c,uc16 minus,uc16 mask,Label * on_not_equal)471 void RegExpMacroAssemblerPPC::CheckNotCharacterAfterMinusAnd(
472     uc16 c, uc16 minus, uc16 mask, Label* on_not_equal) {
473   DCHECK(minus < String::kMaxUtf16CodeUnit);
474   __ subi(r3, current_character(), Operand(minus));
475   __ mov(r0, Operand(mask));
476   __ and_(r3, r3, r0);
477   __ Cmpli(r3, Operand(c), r0);
478   BranchOrBacktrack(ne, on_not_equal);
479 }
480 
481 
CheckCharacterInRange(uc16 from,uc16 to,Label * on_in_range)482 void RegExpMacroAssemblerPPC::CheckCharacterInRange(uc16 from, uc16 to,
483                                                     Label* on_in_range) {
484   __ mov(r0, Operand(from));
485   __ sub(r3, current_character(), r0);
486   __ Cmpli(r3, Operand(to - from), r0);
487   BranchOrBacktrack(le, on_in_range);  // Unsigned lower-or-same condition.
488 }
489 
490 
CheckCharacterNotInRange(uc16 from,uc16 to,Label * on_not_in_range)491 void RegExpMacroAssemblerPPC::CheckCharacterNotInRange(uc16 from, uc16 to,
492                                                        Label* on_not_in_range) {
493   __ mov(r0, Operand(from));
494   __ sub(r3, current_character(), r0);
495   __ Cmpli(r3, Operand(to - from), r0);
496   BranchOrBacktrack(gt, on_not_in_range);  // Unsigned higher condition.
497 }
498 
499 
CheckBitInTable(Handle<ByteArray> table,Label * on_bit_set)500 void RegExpMacroAssemblerPPC::CheckBitInTable(Handle<ByteArray> table,
501                                               Label* on_bit_set) {
502   __ mov(r3, Operand(table));
503   if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) {
504     __ andi(r4, current_character(), Operand(kTableSize - 1));
505     __ addi(r4, r4, Operand(ByteArray::kHeaderSize - kHeapObjectTag));
506   } else {
507     __ addi(r4, current_character(),
508             Operand(ByteArray::kHeaderSize - kHeapObjectTag));
509   }
510   __ lbzx(r3, MemOperand(r3, r4));
511   __ cmpi(r3, Operand::Zero());
512   BranchOrBacktrack(ne, on_bit_set);
513 }
514 
515 
CheckSpecialCharacterClass(uc16 type,Label * on_no_match)516 bool RegExpMacroAssemblerPPC::CheckSpecialCharacterClass(uc16 type,
517                                                          Label* on_no_match) {
518   // Range checks (c in min..max) are generally implemented by an unsigned
519   // (c - min) <= (max - min) check
520   switch (type) {
521     case 's':
522       // Match space-characters
523       if (mode_ == LATIN1) {
524         // One byte space characters are '\t'..'\r', ' ' and \u00a0.
525         Label success;
526         __ cmpi(current_character(), Operand(' '));
527         __ beq(&success);
528         // Check range 0x09..0x0d
529         __ subi(r3, current_character(), Operand('\t'));
530         __ cmpli(r3, Operand('\r' - '\t'));
531         __ ble(&success);
532         // \u00a0 (NBSP).
533         __ cmpi(r3, Operand(0x00a0 - '\t'));
534         BranchOrBacktrack(ne, on_no_match);
535         __ bind(&success);
536         return true;
537       }
538       return false;
539     case 'S':
540       // The emitted code for generic character classes is good enough.
541       return false;
542     case 'd':
543       // Match ASCII digits ('0'..'9')
544       __ subi(r3, current_character(), Operand('0'));
545       __ cmpli(r3, Operand('9' - '0'));
546       BranchOrBacktrack(gt, on_no_match);
547       return true;
548     case 'D':
549       // Match non ASCII-digits
550       __ subi(r3, current_character(), Operand('0'));
551       __ cmpli(r3, Operand('9' - '0'));
552       BranchOrBacktrack(le, on_no_match);
553       return true;
554     case '.': {
555       // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
556       __ xori(r3, current_character(), Operand(0x01));
557       // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
558       __ subi(r3, r3, Operand(0x0b));
559       __ cmpli(r3, Operand(0x0c - 0x0b));
560       BranchOrBacktrack(le, on_no_match);
561       if (mode_ == UC16) {
562         // Compare original value to 0x2028 and 0x2029, using the already
563         // computed (current_char ^ 0x01 - 0x0b). I.e., check for
564         // 0x201d (0x2028 - 0x0b) or 0x201e.
565         __ subi(r3, r3, Operand(0x2028 - 0x0b));
566         __ cmpli(r3, Operand(1));
567         BranchOrBacktrack(le, on_no_match);
568       }
569       return true;
570     }
571     case 'n': {
572       // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
573       __ xori(r3, current_character(), Operand(0x01));
574       // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
575       __ subi(r3, r3, Operand(0x0b));
576       __ cmpli(r3, Operand(0x0c - 0x0b));
577       if (mode_ == LATIN1) {
578         BranchOrBacktrack(gt, on_no_match);
579       } else {
580         Label done;
581         __ ble(&done);
582         // Compare original value to 0x2028 and 0x2029, using the already
583         // computed (current_char ^ 0x01 - 0x0b). I.e., check for
584         // 0x201d (0x2028 - 0x0b) or 0x201e.
585         __ subi(r3, r3, Operand(0x2028 - 0x0b));
586         __ cmpli(r3, Operand(1));
587         BranchOrBacktrack(gt, on_no_match);
588         __ bind(&done);
589       }
590       return true;
591     }
592     case 'w': {
593       if (mode_ != LATIN1) {
594         // Table is 256 entries, so all Latin1 characters can be tested.
595         __ cmpi(current_character(), Operand('z'));
596         BranchOrBacktrack(gt, on_no_match);
597       }
598       ExternalReference map = ExternalReference::re_word_character_map();
599       __ mov(r3, Operand(map));
600       __ lbzx(r3, MemOperand(r3, current_character()));
601       __ cmpli(r3, Operand::Zero());
602       BranchOrBacktrack(eq, on_no_match);
603       return true;
604     }
605     case 'W': {
606       Label done;
607       if (mode_ != LATIN1) {
608         // Table is 256 entries, so all Latin1 characters can be tested.
609         __ cmpli(current_character(), Operand('z'));
610         __ bgt(&done);
611       }
612       ExternalReference map = ExternalReference::re_word_character_map();
613       __ mov(r3, Operand(map));
614       __ lbzx(r3, MemOperand(r3, current_character()));
615       __ cmpli(r3, Operand::Zero());
616       BranchOrBacktrack(ne, on_no_match);
617       if (mode_ != LATIN1) {
618         __ bind(&done);
619       }
620       return true;
621     }
622     case '*':
623       // Match any character.
624       return true;
625     // No custom implementation (yet): s(UC16), S(UC16).
626     default:
627       return false;
628   }
629 }
630 
631 
Fail()632 void RegExpMacroAssemblerPPC::Fail() {
633   __ li(r3, Operand(FAILURE));
634   __ b(&exit_label_);
635 }
636 
637 
GetCode(Handle<String> source)638 Handle<HeapObject> RegExpMacroAssemblerPPC::GetCode(Handle<String> source) {
639   Label return_r3;
640 
641   if (masm_->has_exception()) {
642     // If the code gets corrupted due to long regular expressions and lack of
643     // space on trampolines, an internal exception flag is set. If this case
644     // is detected, we will jump into exit sequence right away.
645     __ bind_to(&entry_label_, internal_failure_label_.pos());
646   } else {
647     // Finalize code - write the entry point code now we know how many
648     // registers we need.
649 
650     // Entry code:
651     __ bind(&entry_label_);
652 
653     // Tell the system that we have a stack frame.  Because the type
654     // is MANUAL, no is generated.
655     FrameScope scope(masm_, StackFrame::MANUAL);
656 
657     // Ensure register assigments are consistent with callee save mask
658     DCHECK(r25.bit() & kRegExpCalleeSaved);
659     DCHECK(code_pointer().bit() & kRegExpCalleeSaved);
660     DCHECK(current_input_offset().bit() & kRegExpCalleeSaved);
661     DCHECK(current_character().bit() & kRegExpCalleeSaved);
662     DCHECK(backtrack_stackpointer().bit() & kRegExpCalleeSaved);
663     DCHECK(end_of_input_address().bit() & kRegExpCalleeSaved);
664     DCHECK(frame_pointer().bit() & kRegExpCalleeSaved);
665 
666     // Actually emit code to start a new stack frame.
667     // Push arguments
668     // Save callee-save registers.
669     // Start new stack frame.
670     // Store link register in existing stack-cell.
671     // Order here should correspond to order of offset constants in header file.
672     RegList registers_to_retain = kRegExpCalleeSaved;
673     RegList argument_registers = r3.bit() | r4.bit() | r5.bit() | r6.bit() |
674                                  r7.bit() | r8.bit() | r9.bit() | r10.bit();
675     __ mflr(r0);
676     __ push(r0);
677     __ MultiPush(argument_registers | registers_to_retain);
678     // Set frame pointer in space for it if this is not a direct call
679     // from generated code.
680     __ addi(frame_pointer(), sp, Operand(8 * kPointerSize));
681     __ li(r3, Operand::Zero());
682     __ push(r3);  // Make room for success counter and initialize it to 0.
683     __ push(r3);  // Make room for "string start - 1" constant.
684     // Check if we have space on the stack for registers.
685     Label stack_limit_hit;
686     Label stack_ok;
687 
688     ExternalReference stack_limit =
689         ExternalReference::address_of_stack_limit(isolate());
690     __ mov(r3, Operand(stack_limit));
691     __ LoadP(r3, MemOperand(r3));
692     __ sub(r3, sp, r3, LeaveOE, SetRC);
693     // Handle it if the stack pointer is already below the stack limit.
694     __ ble(&stack_limit_hit, cr0);
695     // Check if there is room for the variable number of registers above
696     // the stack limit.
697     __ Cmpli(r3, Operand(num_registers_ * kPointerSize), r0);
698     __ bge(&stack_ok);
699     // Exit with OutOfMemory exception. There is not enough space on the stack
700     // for our working registers.
701     __ li(r3, Operand(EXCEPTION));
702     __ b(&return_r3);
703 
704     __ bind(&stack_limit_hit);
705     CallCheckStackGuardState(r3);
706     __ cmpi(r3, Operand::Zero());
707     // If returned value is non-zero, we exit with the returned value as result.
708     __ bne(&return_r3);
709 
710     __ bind(&stack_ok);
711 
712     // Allocate space on stack for registers.
713     __ Add(sp, sp, -num_registers_ * kPointerSize, r0);
714     // Load string end.
715     __ LoadP(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
716     // Load input start.
717     __ LoadP(r3, MemOperand(frame_pointer(), kInputStart));
718     // Find negative length (offset of start relative to end).
719     __ sub(current_input_offset(), r3, end_of_input_address());
720     // Set r3 to address of char before start of the input string
721     // (effectively string position -1).
722     __ LoadP(r4, MemOperand(frame_pointer(), kStartIndex));
723     __ subi(r3, current_input_offset(), Operand(char_size()));
724     if (mode_ == UC16) {
725       __ ShiftLeftImm(r0, r4, Operand(1));
726       __ sub(r3, r3, r0);
727     } else {
728       __ sub(r3, r3, r4);
729     }
730     // Store this value in a local variable, for use when clearing
731     // position registers.
732     __ StoreP(r3, MemOperand(frame_pointer(), kStringStartMinusOne));
733 
734     // Initialize code pointer register
735     __ mov(code_pointer(), Operand(masm_->CodeObject()));
736 
737     Label load_char_start_regexp, start_regexp;
738     // Load newline if index is at start, previous character otherwise.
739     __ cmpi(r4, Operand::Zero());
740     __ bne(&load_char_start_regexp);
741     __ li(current_character(), Operand('\n'));
742     __ b(&start_regexp);
743 
744     // Global regexp restarts matching here.
745     __ bind(&load_char_start_regexp);
746     // Load previous char as initial value of current character register.
747     LoadCurrentCharacterUnchecked(-1, 1);
748     __ bind(&start_regexp);
749 
750     // Initialize on-stack registers.
751     if (num_saved_registers_ > 0) {  // Always is, if generated from a regexp.
752       // Fill saved registers with initial value = start offset - 1
753       if (num_saved_registers_ > 8) {
754         // One slot beyond address of register 0.
755         __ addi(r4, frame_pointer(), Operand(kRegisterZero + kPointerSize));
756         __ li(r5, Operand(num_saved_registers_));
757         __ mtctr(r5);
758         Label init_loop;
759         __ bind(&init_loop);
760         __ StorePU(r3, MemOperand(r4, -kPointerSize));
761         __ bdnz(&init_loop);
762       } else {
763         for (int i = 0; i < num_saved_registers_; i++) {
764           __ StoreP(r3, register_location(i), r0);
765         }
766       }
767     }
768 
769     // Initialize backtrack stack pointer.
770     __ LoadP(backtrack_stackpointer(),
771              MemOperand(frame_pointer(), kStackHighEnd));
772 
773     __ b(&start_label_);
774 
775     // Exit code:
776     if (success_label_.is_linked()) {
777       // Save captures when successful.
778       __ bind(&success_label_);
779       if (num_saved_registers_ > 0) {
780         // copy captures to output
781         __ LoadP(r4, MemOperand(frame_pointer(), kInputStart));
782         __ LoadP(r3, MemOperand(frame_pointer(), kRegisterOutput));
783         __ LoadP(r5, MemOperand(frame_pointer(), kStartIndex));
784         __ sub(r4, end_of_input_address(), r4);
785         // r4 is length of input in bytes.
786         if (mode_ == UC16) {
787           __ ShiftRightImm(r4, r4, Operand(1));
788         }
789         // r4 is length of input in characters.
790         __ add(r4, r4, r5);
791         // r4 is length of string in characters.
792 
793         DCHECK_EQ(0, num_saved_registers_ % 2);
794         // Always an even number of capture registers. This allows us to
795         // unroll the loop once to add an operation between a load of a register
796         // and the following use of that register.
797         for (int i = 0; i < num_saved_registers_; i += 2) {
798           __ LoadP(r5, register_location(i), r0);
799           __ LoadP(r6, register_location(i + 1), r0);
800           if (i == 0 && global_with_zero_length_check()) {
801             // Keep capture start in r25 for the zero-length check later.
802             __ mr(r25, r5);
803           }
804           if (mode_ == UC16) {
805             __ ShiftRightArithImm(r5, r5, 1);
806             __ add(r5, r4, r5);
807             __ ShiftRightArithImm(r6, r6, 1);
808             __ add(r6, r4, r6);
809           } else {
810             __ add(r5, r4, r5);
811             __ add(r6, r4, r6);
812           }
813           __ stw(r5, MemOperand(r3));
814           __ addi(r3, r3, Operand(kIntSize));
815           __ stw(r6, MemOperand(r3));
816           __ addi(r3, r3, Operand(kIntSize));
817         }
818       }
819 
820       if (global()) {
821         // Restart matching if the regular expression is flagged as global.
822         __ LoadP(r3, MemOperand(frame_pointer(), kSuccessfulCaptures));
823         __ LoadP(r4, MemOperand(frame_pointer(), kNumOutputRegisters));
824         __ LoadP(r5, MemOperand(frame_pointer(), kRegisterOutput));
825         // Increment success counter.
826         __ addi(r3, r3, Operand(1));
827         __ StoreP(r3, MemOperand(frame_pointer(), kSuccessfulCaptures));
828         // Capture results have been stored, so the number of remaining global
829         // output registers is reduced by the number of stored captures.
830         __ subi(r4, r4, Operand(num_saved_registers_));
831         // Check whether we have enough room for another set of capture results.
832         __ cmpi(r4, Operand(num_saved_registers_));
833         __ blt(&return_r3);
834 
835         __ StoreP(r4, MemOperand(frame_pointer(), kNumOutputRegisters));
836         // Advance the location for output.
837         __ addi(r5, r5, Operand(num_saved_registers_ * kIntSize));
838         __ StoreP(r5, MemOperand(frame_pointer(), kRegisterOutput));
839 
840         // Prepare r3 to initialize registers with its value in the next run.
841         __ LoadP(r3, MemOperand(frame_pointer(), kStringStartMinusOne));
842 
843         if (global_with_zero_length_check()) {
844           // Special case for zero-length matches.
845           // r25: capture start index
846           __ cmp(current_input_offset(), r25);
847           // Not a zero-length match, restart.
848           __ bne(&load_char_start_regexp);
849           // Offset from the end is zero if we already reached the end.
850           __ cmpi(current_input_offset(), Operand::Zero());
851           __ beq(&exit_label_);
852           // Advance current position after a zero-length match.
853           Label advance;
854           __ bind(&advance);
855           __ addi(current_input_offset(), current_input_offset(),
856                   Operand((mode_ == UC16) ? 2 : 1));
857           if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
858         }
859 
860         __ b(&load_char_start_regexp);
861       } else {
862         __ li(r3, Operand(SUCCESS));
863       }
864     }
865 
866     // Exit and return r3
867     __ bind(&exit_label_);
868     if (global()) {
869       __ LoadP(r3, MemOperand(frame_pointer(), kSuccessfulCaptures));
870     }
871 
872     __ bind(&return_r3);
873     // Skip sp past regexp registers and local variables..
874     __ mr(sp, frame_pointer());
875     // Restore registers r25..r31 and return (restoring lr to pc).
876     __ MultiPop(registers_to_retain);
877     __ pop(r0);
878     __ mtlr(r0);
879     __ blr();
880 
881     // Backtrack code (branch target for conditional backtracks).
882     if (backtrack_label_.is_linked()) {
883       __ bind(&backtrack_label_);
884       Backtrack();
885     }
886 
887     Label exit_with_exception;
888 
889     // Preempt-code
890     if (check_preempt_label_.is_linked()) {
891       SafeCallTarget(&check_preempt_label_);
892 
893       CallCheckStackGuardState(r3);
894       __ cmpi(r3, Operand::Zero());
895       // If returning non-zero, we should end execution with the given
896       // result as return value.
897       __ bne(&return_r3);
898 
899       // String might have moved: Reload end of string from frame.
900       __ LoadP(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
901       SafeReturn();
902     }
903 
904     // Backtrack stack overflow code.
905     if (stack_overflow_label_.is_linked()) {
906       SafeCallTarget(&stack_overflow_label_);
907       // Reached if the backtrack-stack limit has been hit.
908       Label grow_failed;
909 
910       // Call GrowStack(backtrack_stackpointer(), &stack_base)
911       static const int num_arguments = 3;
912       __ PrepareCallCFunction(num_arguments, r3);
913       __ mr(r3, backtrack_stackpointer());
914       __ addi(r4, frame_pointer(), Operand(kStackHighEnd));
915       __ mov(r5, Operand(ExternalReference::isolate_address(isolate())));
916       ExternalReference grow_stack =
917           ExternalReference::re_grow_stack(isolate());
918       __ CallCFunction(grow_stack, num_arguments);
919       // If return NULL, we have failed to grow the stack, and
920       // must exit with a stack-overflow exception.
921       __ cmpi(r3, Operand::Zero());
922       __ beq(&exit_with_exception);
923       // Otherwise use return value as new stack pointer.
924       __ mr(backtrack_stackpointer(), r3);
925       // Restore saved registers and continue.
926       SafeReturn();
927     }
928 
929     if (exit_with_exception.is_linked()) {
930       // If any of the code above needed to exit with an exception.
931       __ bind(&exit_with_exception);
932       // Exit with Result EXCEPTION(-1) to signal thrown exception.
933       __ li(r3, Operand(EXCEPTION));
934       __ b(&return_r3);
935     }
936   }
937 
938   CodeDesc code_desc;
939   masm_->GetCode(&code_desc);
940   Handle<Code> code = isolate()->factory()->NewCode(
941       code_desc, Code::ComputeFlags(Code::REGEXP), masm_->CodeObject());
942   PROFILE(masm_->isolate(),
943           RegExpCodeCreateEvent(AbstractCode::cast(*code), *source));
944   return Handle<HeapObject>::cast(code);
945 }
946 
947 
GoTo(Label * to)948 void RegExpMacroAssemblerPPC::GoTo(Label* to) { BranchOrBacktrack(al, to); }
949 
950 
IfRegisterGE(int reg,int comparand,Label * if_ge)951 void RegExpMacroAssemblerPPC::IfRegisterGE(int reg, int comparand,
952                                            Label* if_ge) {
953   __ LoadP(r3, register_location(reg), r0);
954   __ Cmpi(r3, Operand(comparand), r0);
955   BranchOrBacktrack(ge, if_ge);
956 }
957 
958 
IfRegisterLT(int reg,int comparand,Label * if_lt)959 void RegExpMacroAssemblerPPC::IfRegisterLT(int reg, int comparand,
960                                            Label* if_lt) {
961   __ LoadP(r3, register_location(reg), r0);
962   __ Cmpi(r3, Operand(comparand), r0);
963   BranchOrBacktrack(lt, if_lt);
964 }
965 
966 
IfRegisterEqPos(int reg,Label * if_eq)967 void RegExpMacroAssemblerPPC::IfRegisterEqPos(int reg, Label* if_eq) {
968   __ LoadP(r3, register_location(reg), r0);
969   __ cmp(r3, current_input_offset());
970   BranchOrBacktrack(eq, if_eq);
971 }
972 
973 
974 RegExpMacroAssembler::IrregexpImplementation
Implementation()975 RegExpMacroAssemblerPPC::Implementation() {
976   return kPPCImplementation;
977 }
978 
979 
LoadCurrentCharacter(int cp_offset,Label * on_end_of_input,bool check_bounds,int characters)980 void RegExpMacroAssemblerPPC::LoadCurrentCharacter(int cp_offset,
981                                                    Label* on_end_of_input,
982                                                    bool check_bounds,
983                                                    int characters) {
984   DCHECK(cp_offset < (1 << 30));  // Be sane! (And ensure negation works)
985   if (check_bounds) {
986     if (cp_offset >= 0) {
987       CheckPosition(cp_offset + characters - 1, on_end_of_input);
988     } else {
989       CheckPosition(cp_offset, on_end_of_input);
990     }
991   }
992   LoadCurrentCharacterUnchecked(cp_offset, characters);
993 }
994 
995 
PopCurrentPosition()996 void RegExpMacroAssemblerPPC::PopCurrentPosition() {
997   Pop(current_input_offset());
998 }
999 
1000 
PopRegister(int register_index)1001 void RegExpMacroAssemblerPPC::PopRegister(int register_index) {
1002   Pop(r3);
1003   __ StoreP(r3, register_location(register_index), r0);
1004 }
1005 
1006 
PushBacktrack(Label * label)1007 void RegExpMacroAssemblerPPC::PushBacktrack(Label* label) {
1008   __ mov_label_offset(r3, label);
1009   Push(r3);
1010   CheckStackLimit();
1011 }
1012 
1013 
PushCurrentPosition()1014 void RegExpMacroAssemblerPPC::PushCurrentPosition() {
1015   Push(current_input_offset());
1016 }
1017 
1018 
PushRegister(int register_index,StackCheckFlag check_stack_limit)1019 void RegExpMacroAssemblerPPC::PushRegister(int register_index,
1020                                            StackCheckFlag check_stack_limit) {
1021   __ LoadP(r3, register_location(register_index), r0);
1022   Push(r3);
1023   if (check_stack_limit) CheckStackLimit();
1024 }
1025 
1026 
ReadCurrentPositionFromRegister(int reg)1027 void RegExpMacroAssemblerPPC::ReadCurrentPositionFromRegister(int reg) {
1028   __ LoadP(current_input_offset(), register_location(reg), r0);
1029 }
1030 
1031 
ReadStackPointerFromRegister(int reg)1032 void RegExpMacroAssemblerPPC::ReadStackPointerFromRegister(int reg) {
1033   __ LoadP(backtrack_stackpointer(), register_location(reg), r0);
1034   __ LoadP(r3, MemOperand(frame_pointer(), kStackHighEnd));
1035   __ add(backtrack_stackpointer(), backtrack_stackpointer(), r3);
1036 }
1037 
1038 
SetCurrentPositionFromEnd(int by)1039 void RegExpMacroAssemblerPPC::SetCurrentPositionFromEnd(int by) {
1040   Label after_position;
1041   __ Cmpi(current_input_offset(), Operand(-by * char_size()), r0);
1042   __ bge(&after_position);
1043   __ mov(current_input_offset(), Operand(-by * char_size()));
1044   // On RegExp code entry (where this operation is used), the character before
1045   // the current position is expected to be already loaded.
1046   // We have advanced the position, so it's safe to read backwards.
1047   LoadCurrentCharacterUnchecked(-1, 1);
1048   __ bind(&after_position);
1049 }
1050 
1051 
SetRegister(int register_index,int to)1052 void RegExpMacroAssemblerPPC::SetRegister(int register_index, int to) {
1053   DCHECK(register_index >= num_saved_registers_);  // Reserved for positions!
1054   __ mov(r3, Operand(to));
1055   __ StoreP(r3, register_location(register_index), r0);
1056 }
1057 
1058 
Succeed()1059 bool RegExpMacroAssemblerPPC::Succeed() {
1060   __ b(&success_label_);
1061   return global();
1062 }
1063 
1064 
WriteCurrentPositionToRegister(int reg,int cp_offset)1065 void RegExpMacroAssemblerPPC::WriteCurrentPositionToRegister(int reg,
1066                                                              int cp_offset) {
1067   if (cp_offset == 0) {
1068     __ StoreP(current_input_offset(), register_location(reg), r0);
1069   } else {
1070     __ mov(r0, Operand(cp_offset * char_size()));
1071     __ add(r3, current_input_offset(), r0);
1072     __ StoreP(r3, register_location(reg), r0);
1073   }
1074 }
1075 
1076 
ClearRegisters(int reg_from,int reg_to)1077 void RegExpMacroAssemblerPPC::ClearRegisters(int reg_from, int reg_to) {
1078   DCHECK(reg_from <= reg_to);
1079   __ LoadP(r3, MemOperand(frame_pointer(), kStringStartMinusOne));
1080   for (int reg = reg_from; reg <= reg_to; reg++) {
1081     __ StoreP(r3, register_location(reg), r0);
1082   }
1083 }
1084 
1085 
WriteStackPointerToRegister(int reg)1086 void RegExpMacroAssemblerPPC::WriteStackPointerToRegister(int reg) {
1087   __ LoadP(r4, MemOperand(frame_pointer(), kStackHighEnd));
1088   __ sub(r3, backtrack_stackpointer(), r4);
1089   __ StoreP(r3, register_location(reg), r0);
1090 }
1091 
1092 
1093 // Private methods:
1094 
CallCheckStackGuardState(Register scratch)1095 void RegExpMacroAssemblerPPC::CallCheckStackGuardState(Register scratch) {
1096   int frame_alignment = masm_->ActivationFrameAlignment();
1097   int stack_space = kNumRequiredStackFrameSlots;
1098   int stack_passed_arguments = 1;  // space for return address pointer
1099 
1100   // The following stack manipulation logic is similar to
1101   // PrepareCallCFunction.  However, we need an extra slot on the
1102   // stack to house the return address parameter.
1103   if (frame_alignment > kPointerSize) {
1104     // Make stack end at alignment and make room for stack arguments
1105     // -- preserving original value of sp.
1106     __ mr(scratch, sp);
1107     __ addi(sp, sp, Operand(-(stack_passed_arguments + 1) * kPointerSize));
1108     DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
1109     __ ClearRightImm(sp, sp, Operand(WhichPowerOf2(frame_alignment)));
1110     __ StoreP(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
1111   } else {
1112     // Make room for stack arguments
1113     stack_space += stack_passed_arguments;
1114   }
1115 
1116   // Allocate frame with required slots to make ABI work.
1117   __ li(r0, Operand::Zero());
1118   __ StorePU(r0, MemOperand(sp, -stack_space * kPointerSize));
1119 
1120   // RegExp code frame pointer.
1121   __ mr(r5, frame_pointer());
1122   // Code* of self.
1123   __ mov(r4, Operand(masm_->CodeObject()));
1124   // r3 will point to the return address, placed by DirectCEntry.
1125   __ addi(r3, sp, Operand(kStackFrameExtraParamSlot * kPointerSize));
1126 
1127   ExternalReference stack_guard_check =
1128       ExternalReference::re_check_stack_guard_state(isolate());
1129   __ mov(ip, Operand(stack_guard_check));
1130   DirectCEntryStub stub(isolate());
1131   stub.GenerateCall(masm_, ip);
1132 
1133   // Restore the stack pointer
1134   stack_space = kNumRequiredStackFrameSlots + stack_passed_arguments;
1135   if (frame_alignment > kPointerSize) {
1136     __ LoadP(sp, MemOperand(sp, stack_space * kPointerSize));
1137   } else {
1138     __ addi(sp, sp, Operand(stack_space * kPointerSize));
1139   }
1140 
1141   __ mov(code_pointer(), Operand(masm_->CodeObject()));
1142 }
1143 
1144 
1145 // Helper function for reading a value out of a stack frame.
1146 template <typename T>
frame_entry(Address re_frame,int frame_offset)1147 static T& frame_entry(Address re_frame, int frame_offset) {
1148   return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset));
1149 }
1150 
1151 
1152 template <typename T>
frame_entry_address(Address re_frame,int frame_offset)1153 static T* frame_entry_address(Address re_frame, int frame_offset) {
1154   return reinterpret_cast<T*>(re_frame + frame_offset);
1155 }
1156 
1157 
CheckStackGuardState(Address * return_address,Code * re_code,Address re_frame)1158 int RegExpMacroAssemblerPPC::CheckStackGuardState(Address* return_address,
1159                                                   Code* re_code,
1160                                                   Address re_frame) {
1161   return NativeRegExpMacroAssembler::CheckStackGuardState(
1162       frame_entry<Isolate*>(re_frame, kIsolate),
1163       frame_entry<intptr_t>(re_frame, kStartIndex),
1164       frame_entry<intptr_t>(re_frame, kDirectCall) == 1, return_address,
1165       re_code, frame_entry_address<String*>(re_frame, kInputString),
1166       frame_entry_address<const byte*>(re_frame, kInputStart),
1167       frame_entry_address<const byte*>(re_frame, kInputEnd));
1168 }
1169 
1170 
register_location(int register_index)1171 MemOperand RegExpMacroAssemblerPPC::register_location(int register_index) {
1172   DCHECK(register_index < (1 << 30));
1173   if (num_registers_ <= register_index) {
1174     num_registers_ = register_index + 1;
1175   }
1176   return MemOperand(frame_pointer(),
1177                     kRegisterZero - register_index * kPointerSize);
1178 }
1179 
1180 
CheckPosition(int cp_offset,Label * on_outside_input)1181 void RegExpMacroAssemblerPPC::CheckPosition(int cp_offset,
1182                                             Label* on_outside_input) {
1183   if (cp_offset >= 0) {
1184     __ Cmpi(current_input_offset(), Operand(-cp_offset * char_size()), r0);
1185     BranchOrBacktrack(ge, on_outside_input);
1186   } else {
1187     __ LoadP(r4, MemOperand(frame_pointer(), kStringStartMinusOne));
1188     __ addi(r3, current_input_offset(), Operand(cp_offset * char_size()));
1189     __ cmp(r3, r4);
1190     BranchOrBacktrack(le, on_outside_input);
1191   }
1192 }
1193 
1194 
BranchOrBacktrack(Condition condition,Label * to,CRegister cr)1195 void RegExpMacroAssemblerPPC::BranchOrBacktrack(Condition condition, Label* to,
1196                                                 CRegister cr) {
1197   if (condition == al) {  // Unconditional.
1198     if (to == NULL) {
1199       Backtrack();
1200       return;
1201     }
1202     __ b(to);
1203     return;
1204   }
1205   if (to == NULL) {
1206     __ b(condition, &backtrack_label_, cr);
1207     return;
1208   }
1209   __ b(condition, to, cr);
1210 }
1211 
1212 
SafeCall(Label * to,Condition cond,CRegister cr)1213 void RegExpMacroAssemblerPPC::SafeCall(Label* to, Condition cond,
1214                                        CRegister cr) {
1215   __ b(cond, to, cr, SetLK);
1216 }
1217 
1218 
SafeReturn()1219 void RegExpMacroAssemblerPPC::SafeReturn() {
1220   __ pop(r0);
1221   __ mov(ip, Operand(masm_->CodeObject()));
1222   __ add(r0, r0, ip);
1223   __ mtlr(r0);
1224   __ blr();
1225 }
1226 
1227 
SafeCallTarget(Label * name)1228 void RegExpMacroAssemblerPPC::SafeCallTarget(Label* name) {
1229   __ bind(name);
1230   __ mflr(r0);
1231   __ mov(ip, Operand(masm_->CodeObject()));
1232   __ sub(r0, r0, ip);
1233   __ push(r0);
1234 }
1235 
1236 
Push(Register source)1237 void RegExpMacroAssemblerPPC::Push(Register source) {
1238   DCHECK(!source.is(backtrack_stackpointer()));
1239   __ StorePU(source, MemOperand(backtrack_stackpointer(), -kPointerSize));
1240 }
1241 
1242 
Pop(Register target)1243 void RegExpMacroAssemblerPPC::Pop(Register target) {
1244   DCHECK(!target.is(backtrack_stackpointer()));
1245   __ LoadP(target, MemOperand(backtrack_stackpointer()));
1246   __ addi(backtrack_stackpointer(), backtrack_stackpointer(),
1247           Operand(kPointerSize));
1248 }
1249 
1250 
CheckPreemption()1251 void RegExpMacroAssemblerPPC::CheckPreemption() {
1252   // Check for preemption.
1253   ExternalReference stack_limit =
1254       ExternalReference::address_of_stack_limit(isolate());
1255   __ mov(r3, Operand(stack_limit));
1256   __ LoadP(r3, MemOperand(r3));
1257   __ cmpl(sp, r3);
1258   SafeCall(&check_preempt_label_, le);
1259 }
1260 
1261 
CheckStackLimit()1262 void RegExpMacroAssemblerPPC::CheckStackLimit() {
1263   ExternalReference stack_limit =
1264       ExternalReference::address_of_regexp_stack_limit(isolate());
1265   __ mov(r3, Operand(stack_limit));
1266   __ LoadP(r3, MemOperand(r3));
1267   __ cmpl(backtrack_stackpointer(), r3);
1268   SafeCall(&stack_overflow_label_, le);
1269 }
1270 
1271 
LoadCurrentCharacterUnchecked(int cp_offset,int characters)1272 void RegExpMacroAssemblerPPC::LoadCurrentCharacterUnchecked(int cp_offset,
1273                                                             int characters) {
1274   Register offset = current_input_offset();
1275   if (cp_offset != 0) {
1276     // r25 is not being used to store the capture start index at this point.
1277     __ addi(r25, current_input_offset(), Operand(cp_offset * char_size()));
1278     offset = r25;
1279   }
1280   // The lwz, stw, lhz, sth instructions can do unaligned accesses, if the CPU
1281   // and the operating system running on the target allow it.
1282   // We assume we don't want to do unaligned loads on PPC, so this function
1283   // must only be used to load a single character at a time.
1284 
1285   __ add(current_character(), end_of_input_address(), offset);
1286 #if V8_TARGET_LITTLE_ENDIAN
1287   if (mode_ == LATIN1) {
1288     if (characters == 4) {
1289       __ lwz(current_character(), MemOperand(current_character()));
1290     } else if (characters == 2) {
1291       __ lhz(current_character(), MemOperand(current_character()));
1292     } else {
1293       DCHECK(characters == 1);
1294       __ lbz(current_character(), MemOperand(current_character()));
1295     }
1296   } else {
1297     DCHECK(mode_ == UC16);
1298     if (characters == 2) {
1299       __ lwz(current_character(), MemOperand(current_character()));
1300     } else {
1301       DCHECK(characters == 1);
1302       __ lhz(current_character(), MemOperand(current_character()));
1303     }
1304   }
1305 #else
1306   if (mode_ == LATIN1) {
1307     if (characters == 4) {
1308       __ lwbrx(current_character(), MemOperand(r0, current_character()));
1309     } else if (characters == 2) {
1310       __ lhbrx(current_character(), MemOperand(r0, current_character()));
1311     } else {
1312       DCHECK(characters == 1);
1313       __ lbz(current_character(), MemOperand(current_character()));
1314     }
1315   } else {
1316     DCHECK(mode_ == UC16);
1317     if (characters == 2) {
1318       __ lwz(current_character(), MemOperand(current_character()));
1319       __ rlwinm(current_character(), current_character(), 16, 0, 31);
1320     } else {
1321       DCHECK(characters == 1);
1322       __ lhz(current_character(), MemOperand(current_character()));
1323     }
1324   }
1325 #endif
1326 }
1327 
1328 
1329 #undef __
1330 
1331 #endif  // V8_INTERPRETED_REGEXP
1332 }  // namespace internal
1333 }  // namespace v8
1334 
1335 #endif  // V8_TARGET_ARCH_PPC
1336