13233d2f30cad1f77ff9f43fcbee12f182b18f6b6mstarzinger@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
47516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
67516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
793a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_MIPS
87516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/code-stubs.h"
104b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/log.h"
11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/macro-assembler.h"
12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/regexp-macro-assembler.h"
134b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/regexp-stack.h"
144b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/unicode.h"
154b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org
16196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/mips/regexp-macro-assembler-mips.h"
177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgnamespace v8 {
197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgnamespace internal {
207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org#ifndef V8_INTERPRETED_REGEXP
227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org/*
237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * This assembler uses the following register assignment convention
24777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org * - t7 : Temporarily stores the index of capture start after a matching pass
25777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org *        for a global regexp.
267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * - t1 : Pointer to current code object (Code*) including heap object tag.
277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * - t2 : Current position in input, as negative offset from end of string.
287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org *        Please notice that this is the byte offset, not the character offset!
297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * - t3 : Currently loaded character. Must be loaded using
307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org *        LoadCurrentCharacter before using any of the dispatch methods.
31777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org * - t4 : Points to tip of backtrack stack
327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * - t5 : Unused.
337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * - t6 : End of input (points to byte after last character in input).
347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * - fp : Frame pointer. Used to access arguments, local variables and
357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org *         RegExp registers.
36777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org * - sp : Points to tip of C stack.
377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org *
387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * The remaining registers are free for computations.
397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * Each call to a public method should retain this convention.
40c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *
417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * The stack will have the following structure:
42c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *
43777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org *  - fp[64]  Isolate* isolate   (address of the current isolate)
44777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org *  - fp[60]  direct_call  (if 1, direct call from JavaScript code,
45c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *                          if 0, call through the runtime system).
46777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org *  - fp[56]  stack_area_base (High end of the memory area to use as
47c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *                             backtracking stack).
48777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org *  - fp[52]  capture array size (may fit multiple sets of matches)
49c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *  - fp[48]  int* capture_array (int[num_saved_registers_], for output).
50c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *  - fp[44]  secondary link/return address used by native call.
51c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *  --- sp when called ---
52777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org *  - fp[40]  return address      (lr).
53777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org *  - fp[36]  old frame pointer   (r11).
54c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *  - fp[0..32]  backup of registers s0..s7.
55c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *  --- frame pointer ----
56777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org *  - fp[-4]  end of input       (address of end of string).
57777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org *  - fp[-8]  start of input     (address of first character in string).
58c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *  - fp[-12] start index        (character index of start).
59c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *  - fp[-16] void* input_string (location of a handle containing the string).
60777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org *  - fp[-20] success counter    (only for global regexps to count matches).
61777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org *  - fp[-24] Offset of location before start of input (effectively character
62c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *            position -1). Used to initialize capture registers to a
63c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *            non-position.
64777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org *  - fp[-28] At start (if 1, we are starting at the start of the
65c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *    string, otherwise 0)
66777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org *  - fp[-32] register 0         (Only positions must be stored in the first
67c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *  -         register 1          num_saved_registers_ registers)
68c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *  -         ...
69c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *  -         register num_registers-1
70c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *  --- sp ---
717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org *
727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * The first num_saved_registers_ registers are initialized to point to
737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * "character -1" in the string (i.e., char_size() bytes before the first
747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * character of the string). The remaining registers start out as garbage.
757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org *
767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * The data up to the return address must be placed there by the calling
77c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org * code and the remaining arguments are passed in registers, e.g. by calling the
78c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org * code entry as cast to a function with the signature:
797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * int (*match)(String* input_string,
807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org *              int start_index,
817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org *              Address start,
827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org *              Address end,
83c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *              Address secondary_return_address,  // Only used by native call.
847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org *              int* capture_output_array,
857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org *              byte* stack_area_base,
86c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org *              bool direct_call = false)
877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org * The call is performed by NativeRegExpMacroAssembler::Execute()
88c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro
89c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org * in mips/simulator-mips.h.
90c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org * When calling as a non-direct call (i.e., from C++ code), the return address
91c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org * area is overwritten with the ra register by the RegExp code. When doing a
92c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org * direct call from generated code, the return address is placed there by
93c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org * the calling code, as in a normal exit frame.
947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org */
957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org#define __ ACCESS_MASM(masm_)
977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgRegExpMacroAssemblerMIPS::RegExpMacroAssemblerMIPS(
997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    Mode mode,
1007028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    int registers_to_save,
1017028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    Zone* zone)
1027028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    : NativeRegExpMacroAssembler(zone),
1031fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      masm_(new MacroAssembler(zone->isolate(), NULL, kRegExpCodeSize)),
1047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      mode_(mode),
1057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      num_registers_(registers_to_save),
1067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      num_saved_registers_(registers_to_save),
1077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      entry_label_(),
1087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      start_label_(),
1097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      success_label_(),
1107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      backtrack_label_(),
111c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      exit_label_(),
112c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      internal_failure_label_() {
113e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, registers_to_save % 2);
1147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  __ jmp(&entry_label_);   // We'll write the entry code later.
115c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If the code gets too big or corrupted, an internal exception will be
116c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // raised, and we will exit right away.
117c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&internal_failure_label_);
118c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ li(v0, Operand(FAILURE));
119c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Ret();
1207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  __ bind(&start_label_);  // And then continue from here.
1217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
1227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgRegExpMacroAssemblerMIPS::~RegExpMacroAssemblerMIPS() {
1257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  delete masm_;
1267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  // Unuse labels in case we throw away the assembler without calling GetCode.
1277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  entry_label_.Unuse();
1287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  start_label_.Unuse();
1297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  success_label_.Unuse();
1307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  backtrack_label_.Unuse();
1317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  exit_label_.Unuse();
1327516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  check_preempt_label_.Unuse();
1337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  stack_overflow_label_.Unuse();
134c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  internal_failure_label_.Unuse();
1357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
1367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgint RegExpMacroAssemblerMIPS::stack_limit_slack()  {
1397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return RegExpStack::kStackLimitSlack;
1407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
1417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::AdvanceCurrentPosition(int by) {
144c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (by != 0) {
145c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Addu(current_input_offset(),
14628faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org            current_input_offset(), Operand(by * char_size()));
147c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
1497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1507516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1517516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::AdvanceRegister(int reg, int by) {
152e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(reg >= 0);
153e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(reg < num_registers_);
154c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (by != 0) {
155c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lw(a0, register_location(reg));
156c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Addu(a0, a0, Operand(by));
157c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ sw(a0, register_location(reg));
158c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
1607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::Backtrack() {
163c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  CheckPreemption();
164c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Pop Code* offset from backtrack stack, add Code* and jump to location.
165c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Pop(a0);
166c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(a0, a0, code_pointer());
1676db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org  __ Jump(a0);
1687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
1697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::Bind(Label* label) {
172c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(label);
1737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
1747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckCharacter(uint32_t c, Label* on_equal) {
177c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  BranchOrBacktrack(on_equal, eq, current_character(), Operand(c));
1787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
1797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckCharacterGT(uc16 limit, Label* on_greater) {
182c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  BranchOrBacktrack(on_greater, gt, current_character(), Operand(limit));
1837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
1847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckAtStart(Label* on_at_start) {
187c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label not_at_start;
188c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Did we start the match at the start of the string at all?
189777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org  __ lw(a0, MemOperand(frame_pointer(), kStartIndex));
190777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org  BranchOrBacktrack(&not_at_start, ne, a0, Operand(zero_reg));
191c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
192c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If we did, are we still at the start of the input?
193c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a1, MemOperand(frame_pointer(), kInputStart));
194c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(a0, end_of_input_address(), Operand(current_input_offset()));
195c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  BranchOrBacktrack(on_at_start, eq, a0, Operand(a1));
196c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&not_at_start);
1977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
1987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckNotAtStart(Label* on_not_at_start) {
201c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Did we start the match at the start of the string at all?
202777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org  __ lw(a0, MemOperand(frame_pointer(), kStartIndex));
203777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org  BranchOrBacktrack(on_not_at_start, ne, a0, Operand(zero_reg));
204c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If we did, are we still at the start of the input?
205c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a1, MemOperand(frame_pointer(), kInputStart));
206c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(a0, end_of_input_address(), Operand(current_input_offset()));
207c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  BranchOrBacktrack(on_not_at_start, ne, a0, Operand(a1));
2087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
2097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckCharacterLT(uc16 limit, Label* on_less) {
212c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  BranchOrBacktrack(on_less, lt, current_character(), Operand(limit));
2137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
2147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckGreedyLoop(Label* on_equal) {
217c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label backtrack_non_equal;
218c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a0, MemOperand(backtrack_stackpointer(), 0));
219c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(&backtrack_non_equal, ne, current_input_offset(), Operand(a0));
220c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(backtrack_stackpointer(),
221c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          backtrack_stackpointer(),
222c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          Operand(kPointerSize));
223c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&backtrack_non_equal);
224c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  BranchOrBacktrack(on_equal, eq, current_input_offset(), Operand(a0));
2257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
2267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
2287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckNotBackReferenceIgnoreCase(
2297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int start_reg,
2307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    Label* on_no_match) {
231c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label fallthrough;
232c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a0, register_location(start_reg));  // Index of start of capture.
233c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a1, register_location(start_reg + 1));  // Index of end of capture.
234c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Subu(a1, a1, a0);  // Length of capture.
235c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
236c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If length is zero, either the capture is empty or it is not participating.
237c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // In either case succeed immediately.
238c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(&fallthrough, eq, a1, Operand(zero_reg));
239c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
240c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(t5, a1, current_input_offset());
241c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that there are enough characters left in the input.
242c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  BranchOrBacktrack(on_no_match, gt, t5, Operand(zero_reg));
243c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
2442c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  if (mode_ == LATIN1) {
245c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Label success;
246c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Label fail;
247c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Label loop_check;
248c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
249c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // a0 - offset of start of capture.
250c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // a1 - length of capture.
251c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Addu(a0, a0, Operand(end_of_input_address()));
252c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Addu(a2, end_of_input_address(), Operand(current_input_offset()));
253c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Addu(a1, a0, Operand(a1));
254c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
255c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // a0 - Address of start of capture.
256c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // a1 - Address of end of capture.
257c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // a2 - Address of current input position.
258c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
259c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Label loop;
260c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ bind(&loop);
261c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lbu(a3, MemOperand(a0, 0));
262c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ addiu(a0, a0, char_size());
263c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lbu(t0, MemOperand(a2, 0));
264c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ addiu(a2, a2, char_size());
265c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
266c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Branch(&loop_check, eq, t0, Operand(a3));
267c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
268c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Mismatch, try case-insensitive match (converting letters to lower-case).
269c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Or(a3, a3, Operand(0x20));  // Convert capture character to lower-case.
270c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Or(t0, t0, Operand(0x20));  // Also convert input character.
271c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Branch(&fail, ne, t0, Operand(a3));
272c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Subu(a3, a3, Operand('a'));
27346a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org    __ Branch(&loop_check, ls, a3, Operand('z' - 'a'));
27446a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org    // Latin-1: Check for values in range [224,254] but not 247.
27546a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org    __ Subu(a3, a3, Operand(224 - 'a'));
27646a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org    // Weren't Latin-1 letters.
27746a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org    __ Branch(&fail, hi, a3, Operand(254 - 224));
27846a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org    // Check for 247.
27946a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org    __ Branch(&fail, eq, a3, Operand(247 - 224));
280c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
281c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ bind(&loop_check);
282c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Branch(&loop, lt, a0, Operand(a1));
283c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ jmp(&success);
284c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
285c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ bind(&fail);
286c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    GoTo(on_no_match);
287c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
288c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ bind(&success);
289c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Compute new value of character position after the matched part.
290c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Subu(current_input_offset(), a2, end_of_input_address());
291c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
292e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(mode_ == UC16);
293c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Put regexp engine registers on stack.
294c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    RegList regexp_registers_to_retain = current_input_offset().bit() |
295c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        current_character().bit() | backtrack_stackpointer().bit();
296c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ MultiPush(regexp_registers_to_retain);
297c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
298c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    int argument_count = 4;
299c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ PrepareCallCFunction(argument_count, a2);
300c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
301c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // a0 - offset of start of capture.
302c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // a1 - length of capture.
303c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
304c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Put arguments into arguments registers.
305c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Parameters are
306c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    //   a0: Address byte_offset1 - Address captured substring's start.
307c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    //   a1: Address byte_offset2 - Address of current character position.
308c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    //   a2: size_t byte_length - length of capture in bytes(!).
309c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    //   a3: Isolate* isolate.
310c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
311c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Address of start of capture.
312c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Addu(a0, a0, Operand(end_of_input_address()));
313c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Length of capture.
314c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ mov(a2, a1);
315c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Save length in callee-save register for use on return.
316c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ mov(s3, a1);
317c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Address of current input position.
318c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Addu(a1, current_input_offset(), Operand(end_of_input_address()));
319c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Isolate.
32032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org    __ li(a3, Operand(ExternalReference::isolate_address(masm_->isolate())));
321c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
322c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
323c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      AllowExternalCallThatCantCauseGC scope(masm_);
324c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ExternalReference function =
325c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate());
326c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ CallCFunction(function, argument_count);
327c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
328c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
329c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Restore regexp engine registers.
330c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ MultiPop(regexp_registers_to_retain);
33188aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org    __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
332c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
333c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
334c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Check if function returned non-zero for success or zero for failure.
335c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    BranchOrBacktrack(on_no_match, eq, v0, Operand(zero_reg));
336c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // On success, increment position by length of capture.
337c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Addu(current_input_offset(), current_input_offset(), Operand(s3));
338c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
339c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
340c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&fallthrough);
3417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
3427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3447516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckNotBackReference(
3457516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    int start_reg,
3467516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    Label* on_no_match) {
347c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label fallthrough;
348c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label success;
349c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
350c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Find length of back-referenced capture.
351c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a0, register_location(start_reg));
352c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a1, register_location(start_reg + 1));
353c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Subu(a1, a1, a0);  // Length to check.
354c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Succeed on empty capture (including no capture).
355c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(&fallthrough, eq, a1, Operand(zero_reg));
356c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
357c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(t5, a1, current_input_offset());
358c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check that there are enough characters left in the input.
359c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  BranchOrBacktrack(on_no_match, gt, t5, Operand(zero_reg));
360c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
361c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Compute pointers to match string and capture string.
362c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(a0, a0, Operand(end_of_input_address()));
363c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(a2, end_of_input_address(), Operand(current_input_offset()));
364c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(a1, a1, Operand(a0));
365c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
366c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label loop;
367c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&loop);
3682c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  if (mode_ == LATIN1) {
369c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lbu(a3, MemOperand(a0, 0));
370c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ addiu(a0, a0, char_size());
371c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lbu(t0, MemOperand(a2, 0));
372c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ addiu(a2, a2, char_size());
373c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
374e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(mode_ == UC16);
375c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lhu(a3, MemOperand(a0, 0));
376c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ addiu(a0, a0, char_size());
377c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lhu(t0, MemOperand(a2, 0));
378c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ addiu(a2, a2, char_size());
379c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
380c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  BranchOrBacktrack(on_no_match, ne, a3, Operand(t0));
381c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(&loop, lt, a0, Operand(a1));
382c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
383c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Move current character position to position after match.
384c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Subu(current_input_offset(), a2, end_of_input_address());
385c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&fallthrough);
3867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
3877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckNotCharacter(uint32_t c,
39028faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                                 Label* on_not_equal) {
391c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  BranchOrBacktrack(on_not_equal, ne, current_character(), Operand(c));
3927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
3937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
3957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckCharacterAfterAnd(uint32_t c,
39628faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                                      uint32_t mask,
39728faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                                      Label* on_equal) {
398c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ And(a0, current_character(), Operand(mask));
39928faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org  Operand rhs = (c == 0) ? Operand(zero_reg) : Operand(c);
40028faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org  BranchOrBacktrack(on_equal, eq, a0, rhs);
4017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
4027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckNotCharacterAfterAnd(uint32_t c,
40528faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                                         uint32_t mask,
40628faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                                         Label* on_not_equal) {
407c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ And(a0, current_character(), Operand(mask));
40828faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org  Operand rhs = (c == 0) ? Operand(zero_reg) : Operand(c);
40928faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org  BranchOrBacktrack(on_not_equal, ne, a0, rhs);
4107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
4117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4137516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckNotCharacterAfterMinusAnd(
4147516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    uc16 c,
4157516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    uc16 minus,
4167516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    uc16 mask,
4177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    Label* on_not_equal) {
418e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(minus < String::kMaxUtf16CodeUnit);
419ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  __ Subu(a0, current_character(), Operand(minus));
420ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  __ And(a0, a0, Operand(mask));
421ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  BranchOrBacktrack(on_not_equal, ne, a0, Operand(c));
4227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
4237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
4257d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckCharacterInRange(
4267d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    uc16 from,
4277d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    uc16 to,
4287d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    Label* on_in_range) {
4297d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  __ Subu(a0, current_character(), Operand(from));
4307d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  // Unsigned lower-or-same condition.
4317d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  BranchOrBacktrack(on_in_range, ls, a0, Operand(to - from));
4327d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org}
4337d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org
4347d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org
4357d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckCharacterNotInRange(
4367d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    uc16 from,
4377d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    uc16 to,
4387d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    Label* on_not_in_range) {
4397d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  __ Subu(a0, current_character(), Operand(from));
4407d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  // Unsigned higher condition.
4417d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  BranchOrBacktrack(on_not_in_range, hi, a0, Operand(to - from));
4427d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org}
4437d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org
4447d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org
4457d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckBitInTable(
4467d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    Handle<ByteArray> table,
4477d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    Label* on_bit_set) {
4487d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  __ li(a0, Operand(table));
4492c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) {
4507d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ And(a1, current_character(), Operand(kTableSize - 1));
4517d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ Addu(a0, a0, a1);
4527d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  } else {
4537d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ Addu(a0, a0, current_character());
4547d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  }
4557d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org
4567d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  __ lbu(a0, FieldMemOperand(a0, ByteArray::kHeaderSize));
4577d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  BranchOrBacktrack(on_bit_set, ne, a0, Operand(zero_reg));
4587d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org}
4597d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org
4607d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org
4617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgbool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(uc16 type,
46228faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                                          Label* on_no_match) {
463c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Range checks (c in min..max) are generally implemented by an unsigned
464c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // (c - min) <= (max - min) check.
465c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  switch (type) {
466c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  case 's':
467c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Match space-characters.
4682c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (mode_ == LATIN1) {
4696e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      // One byte space characters are '\t'..'\r', ' ' and \u00a0.
470c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      Label success;
471c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ Branch(&success, eq, current_character(), Operand(' '));
472c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Check range 0x09..0x0d.
473c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ Subu(a0, current_character(), Operand('\t'));
4746e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      __ Branch(&success, ls, a0, Operand('\r' - '\t'));
4756e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      // \u00a0 (NBSP).
4766e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      BranchOrBacktrack(on_no_match, ne, a0, Operand(0x00a0 - '\t'));
477c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ bind(&success);
478c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      return true;
479c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
480c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return false;
481c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  case 'S':
4826e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org    // The emitted code for generic character classes is good enough.
483c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return false;
484c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  case 'd':
4852c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    // Match Latin1 digits ('0'..'9').
486c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Subu(a0, current_character(), Operand('0'));
487c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    BranchOrBacktrack(on_no_match, hi, a0, Operand('9' - '0'));
488c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return true;
489c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  case 'D':
4902c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    // Match non Latin1-digits.
491c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Subu(a0, current_character(), Operand('0'));
492c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    BranchOrBacktrack(on_no_match, ls, a0, Operand('9' - '0'));
493c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return true;
494c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  case '.': {
495c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029).
496c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Xor(a0, current_character(), Operand(0x01));
497c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c.
498c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Subu(a0, a0, Operand(0x0b));
499c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    BranchOrBacktrack(on_no_match, ls, a0, Operand(0x0c - 0x0b));
500c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (mode_ == UC16) {
501c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Compare original value to 0x2028 and 0x2029, using the already
502c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // computed (current_char ^ 0x01 - 0x0b). I.e., check for
503c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // 0x201d (0x2028 - 0x0b) or 0x201e.
504c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ Subu(a0, a0, Operand(0x2028 - 0x0b));
505c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      BranchOrBacktrack(on_no_match, ls, a0, Operand(1));
506c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
507c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return true;
508c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
509c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  case 'n': {
510c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029).
511c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Xor(a0, current_character(), Operand(0x01));
512c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c.
513c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Subu(a0, a0, Operand(0x0b));
5142c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (mode_ == LATIN1) {
515c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      BranchOrBacktrack(on_no_match, hi, a0, Operand(0x0c - 0x0b));
516c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    } else {
517c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      Label done;
518c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      BranchOrBacktrack(&done, ls, a0, Operand(0x0c - 0x0b));
519c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Compare original value to 0x2028 and 0x2029, using the already
520c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // computed (current_char ^ 0x01 - 0x0b). I.e., check for
521c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // 0x201d (0x2028 - 0x0b) or 0x201e.
522c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ Subu(a0, a0, Operand(0x2028 - 0x0b));
523c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      BranchOrBacktrack(on_no_match, hi, a0, Operand(1));
524c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ bind(&done);
525c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
526c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return true;
527c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
528c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  case 'w': {
5292c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (mode_ != LATIN1) {
5302c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      // Table is 256 entries, so all Latin1 characters can be tested.
531c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      BranchOrBacktrack(on_no_match, hi, current_character(), Operand('z'));
532c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
533c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    ExternalReference map = ExternalReference::re_word_character_map();
534c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ li(a0, Operand(map));
535c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Addu(a0, a0, current_character());
536c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lbu(a0, MemOperand(a0, 0));
537c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    BranchOrBacktrack(on_no_match, eq, a0, Operand(zero_reg));
538c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return true;
539c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
540c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  case 'W': {
541c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Label done;
5422c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (mode_ != LATIN1) {
5432c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      // Table is 256 entries, so all Latin1 characters can be tested.
544c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ Branch(&done, hi, current_character(), Operand('z'));
545c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
546c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    ExternalReference map = ExternalReference::re_word_character_map();
547c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ li(a0, Operand(map));
548c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Addu(a0, a0, current_character());
549c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lbu(a0, MemOperand(a0, 0));
550c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    BranchOrBacktrack(on_no_match, ne, a0, Operand(zero_reg));
5512c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (mode_ != LATIN1) {
552c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ bind(&done);
553c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
554c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return true;
555c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
556c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  case '*':
557c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Match any character.
558c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return true;
559c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // No custom implementation (yet): s(UC16), S(UC16).
560c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  default:
561c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return false;
562c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
5637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
5647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::Fail() {
567c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ li(v0, Operand(FAILURE));
568c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ jmp(&exit_label_);
5697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
5707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
5717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
57283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgHandle<HeapObject> RegExpMacroAssemblerMIPS::GetCode(Handle<String> source) {
573777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org  Label return_v0;
574c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (masm_->has_exception()) {
575c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // If the code gets corrupted due to long regular expressions and lack of
576c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // space on trampolines, an internal exception flag is set. If this case
577c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // is detected, we will jump into exit sequence right away.
578c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ bind_to(&entry_label_, internal_failure_label_.pos());
579c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
580c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Finalize code - write the entry point code now we know how many
581c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // registers we need.
582c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
583c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Entry code:
584c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ bind(&entry_label_);
585c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
586c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Tell the system that we have a stack frame.  Because the type is MANUAL,
587c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // no is generated.
588c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FrameScope scope(masm_, StackFrame::MANUAL);
589c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
590c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Actually emit code to start a new stack frame.
591c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Push arguments
592c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Save callee-save registers.
593c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Start new stack frame.
594c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Store link register in existing stack-cell.
595c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Order here should correspond to order of offset constants in header file.
596c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    RegList registers_to_retain = s0.bit() | s1.bit() | s2.bit() |
597c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        s3.bit() | s4.bit() | s5.bit() | s6.bit() | s7.bit() | fp.bit();
598c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    RegList argument_registers = a0.bit() | a1.bit() | a2.bit() | a3.bit();
599c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ MultiPush(argument_registers | registers_to_retain | ra.bit());
600c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Set frame pointer in space for it if this is not a direct call
601c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // from generated code.
602c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Addu(frame_pointer(), sp, Operand(4 * kPointerSize));
603777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    __ mov(a0, zero_reg);
604777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    __ push(a0);  // Make room for success counter and initialize it to 0.
605c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ push(a0);  // Make room for "position - 1" constant (value irrelevant).
606c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
607c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Check if we have space on the stack for registers.
608c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Label stack_limit_hit;
609c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Label stack_ok;
610c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
611c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    ExternalReference stack_limit =
612c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        ExternalReference::address_of_stack_limit(masm_->isolate());
613c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ li(a0, Operand(stack_limit));
614c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lw(a0, MemOperand(a0));
615c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Subu(a0, sp, a0);
616c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Handle it if the stack pointer is already below the stack limit.
617c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Branch(&stack_limit_hit, le, a0, Operand(zero_reg));
618c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Check if there is room for the variable number of registers above
619c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // the stack limit.
620c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Branch(&stack_ok, hs, a0, Operand(num_registers_ * kPointerSize));
621c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Exit with OutOfMemory exception. There is not enough space on the stack
622c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // for our working registers.
623c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ li(v0, Operand(EXCEPTION));
624777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    __ jmp(&return_v0);
625c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
626c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ bind(&stack_limit_hit);
627c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    CallCheckStackGuardState(a0);
628c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // If returned value is non-zero, we exit with the returned value as result.
629777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    __ Branch(&return_v0, ne, v0, Operand(zero_reg));
630c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
631c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ bind(&stack_ok);
632c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Allocate space on stack for registers.
633c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Subu(sp, sp, Operand(num_registers_ * kPointerSize));
634c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Load string end.
635c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
636c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Load input start.
637c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lw(a0, MemOperand(frame_pointer(), kInputStart));
638c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Find negative length (offset of start relative to end).
639c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Subu(current_input_offset(), a0, end_of_input_address());
640c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Set a0 to address of char before start of the input string
641c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // (effectively string position -1).
642c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lw(a1, MemOperand(frame_pointer(), kStartIndex));
643c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Subu(a0, current_input_offset(), Operand(char_size()));
644c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ sll(t5, a1, (mode_ == UC16) ? 1 : 0);
645c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Subu(a0, a0, t5);
646c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Store this value in a local variable, for use when clearing
647c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // position registers.
648c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ sw(a0, MemOperand(frame_pointer(), kInputStartMinusOne));
649c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
650777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    // Initialize code pointer register
651777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
652777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org
653777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    Label load_char_start_regexp, start_regexp;
654777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    // Load newline if index is at start, previous character otherwise.
655777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    __ Branch(&load_char_start_regexp, ne, a1, Operand(zero_reg));
656777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    __ li(current_character(), Operand('\n'));
657777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    __ jmp(&start_regexp);
658777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org
659777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    // Global regexp restarts matching here.
660777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    __ bind(&load_char_start_regexp);
661777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    // Load previous char as initial value of current character register.
662777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    LoadCurrentCharacterUnchecked(-1, 1);
663777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    __ bind(&start_regexp);
664c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
665777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    // Initialize on-stack registers.
666c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (num_saved_registers_ > 0) {  // Always is, if generated from a regexp.
667c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Fill saved registers with initial value = start offset - 1.
668777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org      if (num_saved_registers_ > 8) {
669777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        // Address of register 0.
670777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ Addu(a1, frame_pointer(), Operand(kRegisterZero));
671777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ li(a2, Operand(num_saved_registers_));
672777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        Label init_loop;
673777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ bind(&init_loop);
674777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ sw(a0, MemOperand(a1));
675777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ Addu(a1, a1, Operand(-kPointerSize));
676777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ Subu(a2, a2, Operand(1));
677777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ Branch(&init_loop, ne, a2, Operand(zero_reg));
678777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org      } else {
679777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        for (int i = 0; i < num_saved_registers_; i++) {
680777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org          __ sw(a0, register_location(i));
681777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        }
682777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org      }
683c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
684c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
685c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Initialize backtrack stack pointer.
686c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lw(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd));
687777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org
688c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ jmp(&start_label_);
689c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
690c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
691c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Exit code:
692c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (success_label_.is_linked()) {
693c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Save captures when successful.
694c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ bind(&success_label_);
695c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      if (num_saved_registers_ > 0) {
696c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        // Copy captures to output.
697c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        __ lw(a1, MemOperand(frame_pointer(), kInputStart));
698c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        __ lw(a0, MemOperand(frame_pointer(), kRegisterOutput));
699c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        __ lw(a2, MemOperand(frame_pointer(), kStartIndex));
700c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        __ Subu(a1, end_of_input_address(), a1);
701c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        // a1 is length of input in bytes.
702c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        if (mode_ == UC16) {
703c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          __ srl(a1, a1, 1);
704c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        }
705c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        // a1 is length of input in characters.
706c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        __ Addu(a1, a1, Operand(a2));
707c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        // a1 is length of string in characters.
708c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
709e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK_EQ(0, num_saved_registers_ % 2);
710c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        // Always an even number of capture registers. This allows us to
711c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        // unroll the loop once to add an operation between a load of a register
712c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        // and the following use of that register.
713c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        for (int i = 0; i < num_saved_registers_; i += 2) {
714c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          __ lw(a2, register_location(i));
715c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          __ lw(a3, register_location(i + 1));
7167028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          if (i == 0 && global_with_zero_length_check()) {
717777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org            // Keep capture start in a4 for the zero-length check later.
718777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org            __ mov(t7, a2);
719777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org          }
720c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          if (mode_ == UC16) {
721c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org            __ sra(a2, a2, 1);
722c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org            __ Addu(a2, a2, a1);
723c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org            __ sra(a3, a3, 1);
724c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org            __ Addu(a3, a3, a1);
725c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          } else {
726c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org            __ Addu(a2, a1, Operand(a2));
727c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org            __ Addu(a3, a1, Operand(a3));
728c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          }
729c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          __ sw(a2, MemOperand(a0));
730c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          __ Addu(a0, a0, kPointerSize);
731c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          __ sw(a3, MemOperand(a0));
732c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          __ Addu(a0, a0, kPointerSize);
733c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org        }
734c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      }
735777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org
736777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org      if (global()) {
737777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        // Restart matching if the regular expression is flagged as global.
738777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ lw(a0, MemOperand(frame_pointer(), kSuccessfulCaptures));
739777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ lw(a1, MemOperand(frame_pointer(), kNumOutputRegisters));
740777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ lw(a2, MemOperand(frame_pointer(), kRegisterOutput));
741777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        // Increment success counter.
742777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ Addu(a0, a0, 1);
743777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ sw(a0, MemOperand(frame_pointer(), kSuccessfulCaptures));
744777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        // Capture results have been stored, so the number of remaining global
745777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        // output registers is reduced by the number of stored captures.
746777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ Subu(a1, a1, num_saved_registers_);
747777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        // Check whether we have enough room for another set of capture results.
748777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ mov(v0, a0);
749777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ Branch(&return_v0, lt, a1, Operand(num_saved_registers_));
750777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org
751777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ sw(a1, MemOperand(frame_pointer(), kNumOutputRegisters));
752777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        // Advance the location for output.
753777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ Addu(a2, a2, num_saved_registers_ * kPointerSize);
754777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ sw(a2, MemOperand(frame_pointer(), kRegisterOutput));
755777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org
756777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        // Prepare a0 to initialize registers with its value in the next run.
757777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ lw(a0, MemOperand(frame_pointer(), kInputStartMinusOne));
7587028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
7597028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        if (global_with_zero_length_check()) {
7607028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          // Special case for zero-length matches.
7617028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          // t7: capture start index
7627028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          // Not a zero-length match, restart.
7637028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          __ Branch(
7647028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org              &load_char_start_regexp, ne, current_input_offset(), Operand(t7));
7657028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          // Offset from the end is zero if we already reached the end.
7667028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          __ Branch(&exit_label_, eq, current_input_offset(),
7677028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org                    Operand(zero_reg));
7687028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          // Advance current position after a zero-length match.
7697028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          __ Addu(current_input_offset(),
7707028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org                  current_input_offset(),
7717028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org                  Operand((mode_ == UC16) ? 2 : 1));
7727028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        }
7737028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
774777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ Branch(&load_char_start_regexp);
775777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org      } else {
776777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org        __ li(v0, Operand(SUCCESS));
777777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org      }
778c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
779c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Exit and return v0.
780c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ bind(&exit_label_);
781777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    if (global()) {
782777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org      __ lw(v0, MemOperand(frame_pointer(), kSuccessfulCaptures));
783777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    }
784777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org
785777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    __ bind(&return_v0);
786c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Skip sp past regexp registers and local variables..
787c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ mov(sp, frame_pointer());
788c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Restore registers s0..s7 and return (restoring ra to pc).
789c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ MultiPop(registers_to_retain | ra.bit());
790c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Ret();
791c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
792c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Backtrack code (branch target for conditional backtracks).
793c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (backtrack_label_.is_linked()) {
794c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ bind(&backtrack_label_);
795c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      Backtrack();
796c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
797c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
798c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Label exit_with_exception;
799c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
800c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Preempt-code.
801c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (check_preempt_label_.is_linked()) {
802c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      SafeCallTarget(&check_preempt_label_);
803c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Put regexp engine registers on stack.
804c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      RegList regexp_registers_to_retain = current_input_offset().bit() |
805c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          current_character().bit() | backtrack_stackpointer().bit();
806c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ MultiPush(regexp_registers_to_retain);
807c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      CallCheckStackGuardState(a0);
808c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ MultiPop(regexp_registers_to_retain);
809c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // If returning non-zero, we should end execution with the given
810c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // result as return value.
811777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org      __ Branch(&return_v0, ne, v0, Operand(zero_reg));
812c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
813c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // String might have moved: Reload end of string from frame.
814c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
81588aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org      __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
816c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      SafeReturn();
817c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
818c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
819c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Backtrack stack overflow code.
820c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (stack_overflow_label_.is_linked()) {
821c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      SafeCallTarget(&stack_overflow_label_);
822c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Reached if the backtrack-stack limit has been hit.
823c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Put regexp engine registers on stack first.
824c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      RegList regexp_registers = current_input_offset().bit() |
825c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          current_character().bit();
826c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ MultiPush(regexp_registers);
827c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      Label grow_failed;
828c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Call GrowStack(backtrack_stackpointer(), &stack_base)
829c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      static const int num_arguments = 3;
830c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ PrepareCallCFunction(num_arguments, a0);
831c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ mov(a0, backtrack_stackpointer());
832c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ Addu(a1, frame_pointer(), Operand(kStackHighEnd));
83332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      __ li(a2, Operand(ExternalReference::isolate_address(masm_->isolate())));
834c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      ExternalReference grow_stack =
835c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          ExternalReference::re_grow_stack(masm_->isolate());
836c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ CallCFunction(grow_stack, num_arguments);
837c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Restore regexp registers.
838c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ MultiPop(regexp_registers);
839c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // If return NULL, we have failed to grow the stack, and
840c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // must exit with a stack-overflow exception.
841c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ Branch(&exit_with_exception, eq, v0, Operand(zero_reg));
842c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Otherwise use return value as new stack pointer.
843c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ mov(backtrack_stackpointer(), v0);
844c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Restore saved registers and continue.
84588aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org      __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
846c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
847c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      SafeReturn();
848c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
849c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
850c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (exit_with_exception.is_linked()) {
851c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // If any of the code above needed to exit with an exception.
852c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ bind(&exit_with_exception);
853c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      // Exit with Result EXCEPTION(-1) to signal thrown exception.
854c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ li(v0, Operand(EXCEPTION));
855777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org      __ jmp(&return_v0);
856c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
857c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
858c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
859c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  CodeDesc code_desc;
860c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  masm_->GetCode(&code_desc);
861d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  Handle<Code> code = isolate()->factory()->NewCode(
862d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org      code_desc, Code::ComputeFlags(Code::REGEXP), masm_->CodeObject());
863e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org  LOG(masm_->isolate(), RegExpCodeCreateEvent(*code, *source));
864c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  return Handle<HeapObject>::cast(code);
8657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
8667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::GoTo(Label* to) {
869c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (to == NULL) {
870c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Backtrack();
871c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return;
872c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
873c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ jmp(to);
874c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  return;
8757516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
8767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::IfRegisterGE(int reg,
87928faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                            int comparand,
88028faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                            Label* if_ge) {
8817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  __ lw(a0, register_location(reg));
8827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    BranchOrBacktrack(if_ge, ge, a0, Operand(comparand));
8837516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
8847516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::IfRegisterLT(int reg,
88728faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                            int comparand,
88828faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                            Label* if_lt) {
889c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a0, register_location(reg));
890c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  BranchOrBacktrack(if_lt, lt, a0, Operand(comparand));
8917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
8927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
8947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::IfRegisterEqPos(int reg,
89528faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                               Label* if_eq) {
896c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a0, register_location(reg));
897c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  BranchOrBacktrack(if_eq, eq, a0, Operand(current_input_offset()));
8987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
8997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgRegExpMacroAssembler::IrregexpImplementation
9027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org    RegExpMacroAssemblerMIPS::Implementation() {
9037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return kMIPSImplementation;
9047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
9057516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::LoadCurrentCharacter(int cp_offset,
90828faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                                    Label* on_end_of_input,
90928faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                                    bool check_bounds,
91028faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                                    int characters) {
911e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(cp_offset >= -1);      // ^ and \b can look behind one character.
912e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(cp_offset < (1<<30));  // Be sane! (And ensure negation works).
913c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (check_bounds) {
914c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    CheckPosition(cp_offset + characters - 1, on_end_of_input);
915c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
916c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  LoadCurrentCharacterUnchecked(cp_offset, characters);
9177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
9187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::PopCurrentPosition() {
921c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Pop(current_input_offset());
9227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
9237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::PopRegister(int register_index) {
926c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Pop(a0);
927c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ sw(a0, register_location(register_index));
9287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
9297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9307516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9317516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::PushBacktrack(Label* label) {
932c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (label->is_bound()) {
933c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    int target = label->pos();
934c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ li(a0, Operand(target + Code::kHeaderSize - kHeapObjectTag));
935c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
9367bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org    Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
937c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    Label after_constant;
938c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Branch(&after_constant);
939c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    int offset = masm_->pc_offset();
940c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    int cp_offset = offset + Code::kHeaderSize - kHeapObjectTag;
941c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ emit(0);
942c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    masm_->label_at_put(label, offset);
943c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ bind(&after_constant);
944c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (is_int16(cp_offset)) {
945c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ lw(a0, MemOperand(code_pointer(), cp_offset));
946c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    } else {
947c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ Addu(a0, code_pointer(), cp_offset);
948c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      __ lw(a0, MemOperand(a0, 0));
949c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
950c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
951c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Push(a0);
952c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  CheckStackLimit();
9537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
9547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::PushCurrentPosition() {
9577516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  Push(current_input_offset());
9587516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
9597516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::PushRegister(int register_index,
96228faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                            StackCheckFlag check_stack_limit) {
963c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a0, register_location(register_index));
964c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Push(a0);
965c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (check_stack_limit) CheckStackLimit();
9667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
9677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9687516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::ReadCurrentPositionFromRegister(int reg) {
970c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(current_input_offset(), register_location(reg));
9717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
9727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9737516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::ReadStackPointerFromRegister(int reg) {
975c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(backtrack_stackpointer(), register_location(reg));
976c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a0, MemOperand(frame_pointer(), kStackHighEnd));
977c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(backtrack_stackpointer(), backtrack_stackpointer(), Operand(a0));
9787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
9797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::SetCurrentPositionFromEnd(int by) {
982c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Label after_position;
983c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(&after_position,
984c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org            ge,
985c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org            current_input_offset(),
986c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org            Operand(-by * char_size()));
987c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ li(current_input_offset(), -by * char_size());
988c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // On RegExp code entry (where this operation is used), the character before
989c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // the current position is expected to be already loaded.
990c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // We have advanced the position, so it's safe to read backwards.
991c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  LoadCurrentCharacterUnchecked(-1, 1);
992c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(&after_position);
9937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
9947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
9967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::SetRegister(int register_index, int to) {
997e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(register_index >= num_saved_registers_);  // Reserved for positions!
998c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ li(a0, Operand(to));
999c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ sw(a0, register_location(register_index));
10007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
10017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
1003777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.orgbool RegExpMacroAssemblerMIPS::Succeed() {
1004c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ jmp(&success_label_);
1005777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org  return global();
10067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
10077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::WriteCurrentPositionToRegister(int reg,
101028faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                                              int cp_offset) {
1011c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (cp_offset == 0) {
1012c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ sw(current_input_offset(), register_location(reg));
1013c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
1014c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Addu(a0, current_input_offset(), Operand(cp_offset * char_size()));
1015c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ sw(a0, register_location(reg));
1016c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
10177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
10187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::ClearRegisters(int reg_from, int reg_to) {
1021e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(reg_from <= reg_to);
1022c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a0, MemOperand(frame_pointer(), kInputStartMinusOne));
1023c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  for (int reg = reg_from; reg <= reg_to; reg++) {
1024c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ sw(a0, register_location(reg));
1025c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
10267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
10277516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10287516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10297516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::WriteStackPointerToRegister(int reg) {
1030c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a1, MemOperand(frame_pointer(), kStackHighEnd));
1031c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Subu(a0, backtrack_stackpointer(), a1);
1032c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ sw(a0, register_location(reg));
10337516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
10347516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10357516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
103689e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.orgbool RegExpMacroAssemblerMIPS::CanReadUnaligned() {
103789e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  return false;
103889e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org}
103989e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org
104089e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org
10417516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// Private methods:
10427516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10437516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CallCheckStackGuardState(Register scratch) {
10445de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  int stack_alignment = base::OS::ActivationFrameAlignment();
10453d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
10463d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // Align the stack pointer and save the original sp value on the stack.
10473d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  __ mov(scratch, sp);
10483d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  __ Subu(sp, sp, Operand(kPointerSize));
104921d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  DCHECK(base::bits::IsPowerOfTwo32(stack_alignment));
10503d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  __ And(sp, sp, Operand(-stack_alignment));
10513d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  __ sw(scratch, MemOperand(sp));
10523d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
1053c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ mov(a2, frame_pointer());
1054c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Code* of self.
105588aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  __ li(a1, Operand(masm_->CodeObject()), CONSTANT_SIZE);
10563d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
10573d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // We need to make room for the return address on the stack.
1058e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(IsAligned(stack_alignment, kPointerSize));
10593d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  __ Subu(sp, sp, Operand(stack_alignment));
10603d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
10613d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // Stack pointer now points to cell where return address is to be written.
10623d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // Arguments are in registers, meaning we teat the return address as
10633d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // argument 5. Since DirectCEntryStub will handleallocating space for the C
10643d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // argument slots, we don't need to care about that here. This is how the
10653d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // stack will look (sp meaning the value of sp at this moment):
10663d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // [sp + 3] - empty slot if needed for alignment.
10673d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // [sp + 2] - saved sp.
10683d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // [sp + 1] - second word reserved for return value.
10693d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // [sp + 0] - first word reserved for return value.
10703d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
10713d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // a0 will point to the return address, placed by DirectCEntry.
10723d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  __ mov(a0, sp);
10733d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
1074c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ExternalReference stack_guard_check =
1075c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      ExternalReference::re_check_stack_guard_state(masm_->isolate());
10763d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  __ li(t9, Operand(stack_guard_check));
1077f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  DirectCEntryStub stub(isolate());
10783d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  stub.GenerateCall(masm_, t9);
10793d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
10803d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // DirectCEntryStub allocated space for the C argument slots so we have to
10813d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // drop them with the return address from the stack with loading saved sp.
10823d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // At this point stack must look:
10833d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // [sp + 7] - empty slot if needed for alignment.
10843d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // [sp + 6] - saved sp.
10853d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // [sp + 5] - second word reserved for return value.
10863d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // [sp + 4] - first word reserved for return value.
10873d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // [sp + 3] - C argument slot.
10883d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // [sp + 2] - C argument slot.
10893d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // [sp + 1] - C argument slot.
10903d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // [sp + 0] - C argument slot.
10913d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  __ lw(sp, MemOperand(sp, stack_alignment + kCArgsSlotsSize));
10923d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org
10933d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  __ li(code_pointer(), Operand(masm_->CodeObject()));
10947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
10957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
10977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org// Helper function for reading a value out of a stack frame.
10987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgtemplate <typename T>
10997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgstatic T& frame_entry(Address re_frame, int frame_offset) {
11007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset));
11017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
11027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
11037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
11047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgint RegExpMacroAssemblerMIPS::CheckStackGuardState(Address* return_address,
1105c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                                                   Code* re_code,
1106c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                                                   Address re_frame) {
1107c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
11083ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  StackLimitCheck check(isolate);
11093ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  if (check.JsHasOverflowed()) {
1110c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    isolate->StackOverflow();
1111c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return EXCEPTION;
1112c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1113c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1114c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If not real stack overflow the stack guard was used to interrupt
1115c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // execution for another purpose.
1116c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1117c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // If this is a direct call from JavaScript retry the RegExp forcing the call
1118c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // through the runtime system. Currently the direct call cannot handle a GC.
1119c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (frame_entry<int>(re_frame, kDirectCall) == 1) {
1120c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return RETRY;
1121c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1122c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1123c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Prepare for possible GC.
11244668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  HandleScope handles(isolate);
1125c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Handle<Code> code_handle(re_code);
1126c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1127c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
1128c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Current string.
11292c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  bool is_one_byte = subject->IsOneByteRepresentationUnderneath();
1130c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1131e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(re_code->instruction_start() <= *return_address);
1132e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(*return_address <=
1133c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      re_code->instruction_start() + re_code->instruction_size());
1134c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
11353c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  Object* result = isolate->stack_guard()->HandleInterrupts();
1136c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1137c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (*code_handle != re_code) {  // Return address no longer valid.
113880c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    int delta = code_handle->address() - re_code->address();
1139c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // Overwrite the return address on the stack.
1140c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    *return_address += delta;
1141c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1142c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1143c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (result->IsException()) {
1144c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return EXCEPTION;
1145c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1146c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
11474668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  Handle<String> subject_tmp = subject;
11484668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  int slice_offset = 0;
11494668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
11504668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // Extract the underlying string and the slice offset.
11514668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  if (StringShape(*subject_tmp).IsCons()) {
11524668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
11534668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  } else if (StringShape(*subject_tmp).IsSliced()) {
11544668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    SlicedString* slice = SlicedString::cast(*subject_tmp);
11554668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    subject_tmp = Handle<String>(slice->parent());
11564668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    slice_offset = slice->offset();
11574668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  }
11584668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
1159c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // String might have changed.
11602c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  if (subject_tmp->IsOneByteRepresentation() != is_one_byte) {
11612c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    // If we changed between an Latin1 and an UC16 string, the specialized
1162c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // code cannot be used, and we need to restart regexp matching from
1163c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // scratch (including, potentially, compiling a new version of the code).
1164c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return RETRY;
1165c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1166c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1167c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Otherwise, the content of the string might have moved. It must still
1168c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // be a sequential or external string with the same content.
1169c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Update the start and end pointers in the stack frame to the current
1170c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // location (whether it has actually moved or not).
1171e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(StringShape(*subject_tmp).IsSequential() ||
11724668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org      StringShape(*subject_tmp).IsExternal());
1173c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1174c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // The original start address of the characters to match.
1175c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
1176c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1177c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Find the current start address of the same character at the current string
1178c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // position.
1179c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  int start_index = frame_entry<int>(re_frame, kStartIndex);
11804668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  const byte* new_address = StringCharacterPosition(*subject_tmp,
11814668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org                                                    start_index + slice_offset);
1182c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1183c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (start_address != new_address) {
1184c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // If there is a difference, update the object pointer and start and end
1185c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    // addresses in the RegExp stack frame to match the new value.
1186c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
11874668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    int byte_length = static_cast<int>(end_address - start_address);
1188c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    frame_entry<const String*>(re_frame, kInputString) = *subject;
1189c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    frame_entry<const byte*>(re_frame, kInputStart) = new_address;
1190c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
1191394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  } else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
1192394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Subject string might have been a ConsString that underwent
1193394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // short-circuiting during GC. That will not change start_address but
1194394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // will change pointer inside the subject handle.
1195394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    frame_entry<const String*>(re_frame, kInputString) = *subject;
1196c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1197c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
11987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  return 0;
11997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
12007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgMemOperand RegExpMacroAssemblerMIPS::register_location(int register_index) {
1203e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(register_index < (1<<30));
1204c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (num_registers_ <= register_index) {
1205c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    num_registers_ = register_index + 1;
1206c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1207c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  return MemOperand(frame_pointer(),
1208c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                    kRegisterZero - register_index * kPointerSize);
12097516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
12107516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12117516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12127516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckPosition(int cp_offset,
121328faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                             Label* on_outside_input) {
1214c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  BranchOrBacktrack(on_outside_input,
1215c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                    ge,
1216c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                    current_input_offset(),
1217c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org                    Operand(-cp_offset * char_size()));
12187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
12197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::BranchOrBacktrack(Label* to,
12227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                                 Condition condition,
12237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                                 Register rs,
12247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org                                                 const Operand& rt) {
1225c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (condition == al) {  // Unconditional.
1226c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    if (to == NULL) {
1227c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      Backtrack();
1228c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      return;
1229c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    }
1230c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ jmp(to);
1231c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return;
1232c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1233c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (to == NULL) {
1234c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ Branch(&backtrack_label_, condition, rs, rt);
1235c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    return;
1236c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1237c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Branch(to, condition, rs, rt);
12387516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
12397516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12407516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
124128faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.orgvoid RegExpMacroAssemblerMIPS::SafeCall(Label* to,
124228faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                        Condition cond,
124328faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                        Register rs,
124428faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                        const Operand& rt) {
1245c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ BranchAndLink(to, cond, rs, rt);
12467516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
12477516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12487516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12497516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::SafeReturn() {
1250c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ pop(ra);
1251c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(t5, ra, Operand(masm_->CodeObject()));
1252c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Jump(t5);
12537516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
12547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::SafeCallTarget(Label* name) {
1257c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ bind(name);
1258c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Subu(ra, ra, Operand(masm_->CodeObject()));
1259c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ push(ra);
12607516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
12617516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12637516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::Push(Register source) {
1264e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!source.is(backtrack_stackpointer()));
1265c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(backtrack_stackpointer(),
1266c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          backtrack_stackpointer(),
1267c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org          Operand(-kPointerSize));
1268c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ sw(source, MemOperand(backtrack_stackpointer()));
12697516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
12707516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12717516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12727516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::Pop(Register target) {
1273e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!target.is(backtrack_stackpointer()));
1274c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(target, MemOperand(backtrack_stackpointer()));
1275c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(backtrack_stackpointer(), backtrack_stackpointer(), kPointerSize);
12767516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
12777516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12787516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12797516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckPreemption() {
1280c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // Check for preemption.
1281c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ExternalReference stack_limit =
1282c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      ExternalReference::address_of_stack_limit(masm_->isolate());
1283c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ li(a0, Operand(stack_limit));
1284c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a0, MemOperand(a0));
1285c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  SafeCall(&check_preempt_label_, ls, sp, Operand(a0));
12867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
12877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::CheckStackLimit() {
1290c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  ExternalReference stack_limit =
1291c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org      ExternalReference::address_of_regexp_stack_limit(masm_->isolate());
1292c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org
1293c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ li(a0, Operand(stack_limit));
1294c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ lw(a0, MemOperand(a0));
1295c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  SafeCall(&stack_overflow_label_, ls, backtrack_stackpointer(), Operand(a0));
12967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
12977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
12997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid RegExpMacroAssemblerMIPS::LoadCurrentCharacterUnchecked(int cp_offset,
130028faa982749c4aa9c090939453dea14bb118f613jkummerow@chromium.org                                                             int characters) {
1301c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  Register offset = current_input_offset();
1302c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  if (cp_offset != 0) {
1303777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    // t7 is not being used to store the capture start index at this point.
1304777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    __ Addu(t7, current_input_offset(), Operand(cp_offset * char_size()));
1305777db6f4249aa13ebf060a0d290d34936a41eb75jkummerow@chromium.org    offset = t7;
1306c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
1307c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // We assume that we cannot do unaligned loads on MIPS, so this function
1308c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  // must only be used to load a single character at a time.
1309e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(characters == 1);
1310c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  __ Addu(t5, end_of_input_address(), Operand(offset));
13112c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  if (mode_ == LATIN1) {
1312c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lbu(current_character(), MemOperand(t5, 0));
1313c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  } else {
1314e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(mode_ == UC16);
1315c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org    __ lhu(current_character(), MemOperand(t5, 0));
1316c53e10d01c5495df3896b9d318910b58688c6929kmillikin@chromium.org  }
13177516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}
13187516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13197516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13207516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org#undef __
13217516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13227516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org#endif  // V8_INTERPRETED_REGEXP
13237516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13247516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org}}  // namespace v8::internal
13257516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
13267516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org#endif  // V8_TARGET_ARCH_MIPS
1327