Home | History | Annotate | Download | only in mips
      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 
     16 namespace v8 {
     17 namespace 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 
     96 RegExpMacroAssemblerMIPS::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 
    122 RegExpMacroAssemblerMIPS::~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 
    136 int RegExpMacroAssemblerMIPS::stack_limit_slack()  {
    137   return RegExpStack::kStackLimitSlack;
    138 }
    139 
    140 
    141 void 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 
    149 void 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 
    160 void 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 
    169 void RegExpMacroAssemblerMIPS::Bind(Label* label) {
    170   __ bind(label);
    171 }
    172 
    173 
    174 void RegExpMacroAssemblerMIPS::CheckCharacter(uint32_t c, Label* on_equal) {
    175   BranchOrBacktrack(on_equal, eq, current_character(), Operand(c));
    176 }
    177 
    178 
    179 void RegExpMacroAssemblerMIPS::CheckCharacterGT(uc16 limit, Label* on_greater) {
    180   BranchOrBacktrack(on_greater, gt, current_character(), Operand(limit));
    181 }
    182 
    183 
    184 void 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 
    191 void 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 
    200 void RegExpMacroAssemblerMIPS::CheckCharacterLT(uc16 limit, Label* on_less) {
    201   BranchOrBacktrack(on_less, lt, current_character(), Operand(limit));
    202 }
    203 
    204 
    205 void 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 
    217 void 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 
    362 void 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 
    431 void RegExpMacroAssemblerMIPS::CheckNotCharacter(uint32_t c,
    432                                                  Label* on_not_equal) {
    433   BranchOrBacktrack(on_not_equal, ne, current_character(), Operand(c));
    434 }
    435 
    436 
    437 void 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 
    446 void 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 
    455 void 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 
    467 void 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 
    477 void 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 
    487 void 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 
    503 bool 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 
    608 void RegExpMacroAssemblerMIPS::Fail() {
    609   __ li(v0, Operand(FAILURE));
    610   __ jmp(&exit_label_);
    611 }
    612 
    613 
    614 Handle<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 
    914 void RegExpMacroAssemblerMIPS::GoTo(Label* to) {
    915   if (to == NULL) {
    916     Backtrack();
    917     return;
    918   }
    919   __ jmp(to);
    920   return;
    921 }
    922 
    923 
    924 void 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 
    932 void 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 
    940 void 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 
    947 RegExpMacroAssembler::IrregexpImplementation
    948     RegExpMacroAssemblerMIPS::Implementation() {
    949   return kMIPSImplementation;
    950 }
    951 
    952 
    953 void 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 
    969 void RegExpMacroAssemblerMIPS::PopCurrentPosition() {
    970   Pop(current_input_offset());
    971 }
    972 
    973 
    974 void RegExpMacroAssemblerMIPS::PopRegister(int register_index) {
    975   Pop(a0);
    976   __ sw(a0, register_location(register_index));
    977 }
    978 
    979 
    980 void 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 
   1005 void RegExpMacroAssemblerMIPS::PushCurrentPosition() {
   1006   Push(current_input_offset());
   1007 }
   1008 
   1009 
   1010 void 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 
   1018 void RegExpMacroAssemblerMIPS::ReadCurrentPositionFromRegister(int reg) {
   1019   __ lw(current_input_offset(), register_location(reg));
   1020 }
   1021 
   1022 
   1023 void 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 
   1030 void 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 
   1045 void 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 
   1052 bool RegExpMacroAssemblerMIPS::Succeed() {
   1053   __ jmp(&success_label_);
   1054   return global();
   1055 }
   1056 
   1057 
   1058 void 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 
   1069 void 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 
   1078 void 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 
   1085 bool RegExpMacroAssemblerMIPS::CanReadUnaligned() {
   1086   return false;
   1087 }
   1088 
   1089 
   1090 // Private methods:
   1091 
   1092 void 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.
   1147 template <typename T>
   1148 static T& frame_entry(Address re_frame, int frame_offset) {
   1149   return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset));
   1150 }
   1151 
   1152 
   1153 template <typename T>
   1154 static T* frame_entry_address(Address re_frame, int frame_offset) {
   1155   return reinterpret_cast<T*>(re_frame + frame_offset);
   1156 }
   1157 
   1158 
   1159 int 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 
   1172 MemOperand 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 
   1182 void 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 
   1195 void 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 
   1215 void RegExpMacroAssemblerMIPS::SafeCall(Label* to,
   1216                                         Condition cond,
   1217                                         Register rs,
   1218                                         const Operand& rt) {
   1219   __ BranchAndLink(to, cond, rs, rt);
   1220 }
   1221 
   1222 
   1223 void RegExpMacroAssemblerMIPS::SafeReturn() {
   1224   __ pop(ra);
   1225   __ Addu(t5, ra, Operand(masm_->CodeObject()));
   1226   __ Jump(t5);
   1227 }
   1228 
   1229 
   1230 void RegExpMacroAssemblerMIPS::SafeCallTarget(Label* name) {
   1231   __ bind(name);
   1232   __ Subu(ra, ra, Operand(masm_->CodeObject()));
   1233   __ push(ra);
   1234 }
   1235 
   1236 
   1237 void 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 
   1246 void 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 
   1253 void 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 
   1263 void 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 
   1273 void 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