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