115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
29a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// Redistribution and use in source and binary forms, with or without
39a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// modification, are permitted provided that the following conditions are
49a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// met:
59a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//
69a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//     * Redistributions of source code must retain the above copyright
79a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//       notice, this list of conditions and the following disclaimer.
89a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//     * Redistributions in binary form must reproduce the above
99a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//       copyright notice, this list of conditions and the following
109a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//       disclaimer in the documentation and/or other materials provided
119a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//       with the distribution.
129a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//     * Neither the name of Google Inc. nor the names of its
139a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//       contributors may be used to endorse or promote products derived
149a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//       from this software without specific prior written permission.
159a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com//
169a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
179a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
189a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
199a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
209a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
219a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
229a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
269a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
28a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include "v8.h"
299dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3093a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_ARM
319dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org#include "cpu-profiler.h"
3318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org#include "unicode.h"
3418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org#include "log.h"
353811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org#include "code-stubs.h"
3618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org#include "regexp-stack.h"
3718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org#include "macro-assembler.h"
38a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include "regexp-macro-assembler.h"
393a37e9b96c768f6b5b6b09542e1cb1a1ece7a022ager@chromium.org#include "arm/regexp-macro-assembler-arm.h"
409a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
4171affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 {
4271affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal {
43a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
44c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org#ifndef V8_INTERPRETED_REGEXP
4518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org/*
4618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * This assembler uses the following register assignment convention
4715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org * - r4 : Temporarily stores the index of capture start after a matching pass
4815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *        for a global regexp.
4918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * - r5 : Pointer to current code object (Code*) including heap object tag.
5018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * - r6 : Current position in input, as negative offset from end of string.
5118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org *        Please notice that this is the byte offset, not the character offset!
5218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * - r7 : Currently loaded character. Must be loaded using
5318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org *        LoadCurrentCharacter before using any of the dispatch methods.
5415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org * - r8 : Points to tip of backtrack stack
5518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * - r9 : Unused, might be used by C code and expected unchanged.
5618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * - r10 : End of input (points to byte after last character in input).
5718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * - r11 : Frame pointer. Used to access arguments, local variables and
5818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org *         RegExp registers.
5918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * - r12 : IP register, used by assembler. Very volatile.
6015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org * - r13/sp : Points to tip of C stack.
6118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org *
6218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * The remaining registers are free for computations.
6318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * Each call to a public method should retain this convention.
6449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *
6518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * The stack will have the following structure:
6615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *  - fp[56]  Isolate* isolate   (address of the current isolate)
6715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *  - fp[52]  direct_call        (if 1, direct call from JavaScript code,
6815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *                                if 0, call through the runtime system).
6915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *  - fp[48]  stack_area_base    (high end of the memory area to use as
7015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *                                backtracking stack).
7115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *  - fp[44]  capture array size (may fit multiple sets of matches)
7249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *  - fp[40]  int* capture_array (int[num_saved_registers_], for output).
7349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *  - fp[36]  secondary link/return address used by native call.
7449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *  --- sp when called ---
7515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *  - fp[32]  return address     (lr).
7615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *  - fp[28]  old frame pointer  (r11).
7749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *  - fp[0..24]  backup of registers r4..r10.
7849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *  --- frame pointer ----
7915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *  - fp[-4]  end of input       (address of end of string).
8015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *  - fp[-8]  start of input     (address of first character in string).
8149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *  - fp[-12] start index        (character index of start).
8249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *  - fp[-16] void* input_string (location of a handle containing the string).
8315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *  - fp[-20] success counter    (only for global regexps to count matches).
8415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *  - fp[-24] Offset of location before start of input (effectively character
8549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *            position -1). Used to initialize capture registers to a
8649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *            non-position.
8715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *  - fp[-28] At start (if 1, we are starting at the start of the
8849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *    string, otherwise 0)
8915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *  - fp[-32] register 0         (Only positions must be stored in the first
9049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *  -         register 1          num_saved_registers_ registers)
9149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *  -         ...
9249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *  -         register num_registers-1
9349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *  --- sp ---
9418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org *
9518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * The first num_saved_registers_ registers are initialized to point to
9618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * "character -1" in the string (i.e., char_size() bytes before the first
9718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * character of the string). The remaining registers start out as garbage.
9818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org *
9918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * The data up to the return address must be placed there by the calling
10049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org * code and the remaining arguments are passed in registers, e.g. by calling the
10149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org * code entry as cast to a function with the signature:
10218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * int (*match)(String* input_string,
1030c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org *              int start_index,
10418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org *              Address start,
10518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org *              Address end,
10649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *              Address secondary_return_address,  // Only used by native call.
10718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org *              int* capture_output_array,
1080c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org *              byte* stack_area_base,
10949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org *              bool direct_call = false)
11018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org * The call is performed by NativeRegExpMacroAssembler::Execute()
11149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro
11249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org * in arm/simulator-arm.h.
11349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org * When calling as a non-direct call (i.e., from C++ code), the return address
11449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org * area is overwritten with the LR register by the RegExp code. When doing a
11549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org * direct call from generated code, the return address is placed there by
11649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org * the calling code, as in a normal exit frame.
11718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org */
11818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
11918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org#define __ ACCESS_MASM(masm_)
12018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
12118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgRegExpMacroAssemblerARM::RegExpMacroAssemblerARM(
12218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    Mode mode,
1237028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    int registers_to_save,
1247028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    Zone* zone)
1257028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    : NativeRegExpMacroAssembler(zone),
1261fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      masm_(new MacroAssembler(zone->isolate(), NULL, kRegExpCodeSize)),
12718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      mode_(mode),
12818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      num_registers_(registers_to_save),
12918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      num_saved_registers_(registers_to_save),
13018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      entry_label_(),
13118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      start_label_(),
13218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      success_label_(),
13318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      backtrack_label_(),
13418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      exit_label_() {
13518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ASSERT_EQ(0, registers_to_save % 2);
13618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ jmp(&entry_label_);   // We'll write the entry code later.
13718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ bind(&start_label_);  // And then continue from here.
138a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
139a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
140a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
14118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgRegExpMacroAssemblerARM::~RegExpMacroAssemblerARM() {
14218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  delete masm_;
14318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Unuse labels in case we throw away the assembler without calling GetCode.
14418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  entry_label_.Unuse();
14518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  start_label_.Unuse();
14618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  success_label_.Unuse();
14718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  backtrack_label_.Unuse();
14818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  exit_label_.Unuse();
14918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  check_preempt_label_.Unuse();
15018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  stack_overflow_label_.Unuse();
15118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
15218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
15318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
15418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgint RegExpMacroAssemblerARM::stack_limit_slack()  {
15518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  return RegExpStack::kStackLimitSlack;
15618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
15718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
15818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
15918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::AdvanceCurrentPosition(int by) {
16018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (by != 0) {
16118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ add(current_input_offset(),
16218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org           current_input_offset(), Operand(by * char_size()));
16318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
16418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
16518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
16618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
16718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::AdvanceRegister(int reg, int by) {
16818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ASSERT(reg >= 0);
16918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ASSERT(reg < num_registers_);
17018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (by != 0) {
17118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ ldr(r0, register_location(reg));
17218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ add(r0, r0, Operand(by));
17318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ str(r0, register_location(reg));
17418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
17518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
17618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
17718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
17818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::Backtrack() {
17918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  CheckPreemption();
18018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Pop Code* offset from backtrack stack, add Code* and jump to location.
18118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Pop(r0);
182357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  __ add(pc, r0, Operand(code_pointer()));
18318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
18418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
18518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
18618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::Bind(Label* label) {
18718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ bind(label);
18818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
18918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
19018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
19118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::CheckCharacter(uint32_t c, Label* on_equal) {
19218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(current_character(), Operand(c));
19318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(eq, on_equal);
19418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
19518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
19618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
19718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::CheckCharacterGT(uc16 limit, Label* on_greater) {
19818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(current_character(), Operand(limit));
19918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(gt, on_greater);
20018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
20118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
20218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
20318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::CheckAtStart(Label* on_at_start) {
20418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Label not_at_start;
20518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Did we start the match at the start of the string at all?
20615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ ldr(r0, MemOperand(frame_pointer(), kStartIndex));
20759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(r0, Operand::Zero());
20815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  BranchOrBacktrack(ne, &not_at_start);
20918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
21018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // If we did, are we still at the start of the input?
21118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r1, MemOperand(frame_pointer(), kInputStart));
21218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ add(r0, end_of_input_address(), Operand(current_input_offset()));
21318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(r0, r1);
21418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(eq, on_at_start);
21518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ bind(&not_at_start);
21618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
21718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
21818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
21918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::CheckNotAtStart(Label* on_not_at_start) {
22018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Did we start the match at the start of the string at all?
22115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ ldr(r0, MemOperand(frame_pointer(), kStartIndex));
22259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(r0, Operand::Zero());
22315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  BranchOrBacktrack(ne, on_not_at_start);
22418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // If we did, are we still at the start of the input?
22518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r1, MemOperand(frame_pointer(), kInputStart));
22618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ add(r0, end_of_input_address(), Operand(current_input_offset()));
22718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(r0, r1);
22818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(ne, on_not_at_start);
22918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
23018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
23118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
23218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::CheckCharacterLT(uc16 limit, Label* on_less) {
23318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(current_character(), Operand(limit));
23418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(lt, on_less);
23518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
23618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
23718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
23818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::CheckGreedyLoop(Label* on_equal) {
23918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r0, MemOperand(backtrack_stackpointer(), 0));
24018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(current_input_offset(), r0);
24118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ add(backtrack_stackpointer(),
24218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org         backtrack_stackpointer(), Operand(kPointerSize), LeaveCC, eq);
24318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(eq, on_equal);
24418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
24518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
24618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
24718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::CheckNotBackReferenceIgnoreCase(
24818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    int start_reg,
24918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    Label* on_no_match) {
25018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Label fallthrough;
25118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r0, register_location(start_reg));  // Index of start of capture
25218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r1, register_location(start_reg + 1));  // Index of end of capture
25318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ sub(r1, r1, r0, SetCC);  // Length of capture.
25418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
25518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // If length is zero, either the capture is empty or it is not participating.
25618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // In either case succeed immediately.
25718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ b(eq, &fallthrough);
25818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
25918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Check that there are enough characters left in the input.
26018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmn(r1, Operand(current_input_offset()));
26118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(gt, on_no_match);
26218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
26318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (mode_ == ASCII) {
26418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    Label success;
26518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    Label fail;
26618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    Label loop_check;
26718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
26818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // r0 - offset of start of capture
26918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // r1 - length of capture
27018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ add(r0, r0, Operand(end_of_input_address()));
27118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ add(r2, end_of_input_address(), Operand(current_input_offset()));
27218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ add(r1, r0, Operand(r1));
27318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
27418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // r0 - Address of start of capture.
27518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // r1 - Address of end of capture
27618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // r2 - Address of current input position.
27718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
27818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    Label loop;
27918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ bind(&loop);
28018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ ldrb(r3, MemOperand(r0, char_size(), PostIndex));
28118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ ldrb(r4, MemOperand(r2, char_size(), PostIndex));
28218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ cmp(r4, r3);
28318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ b(eq, &loop_check);
28418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
28518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Mismatch, try case-insensitive match (converting letters to lower-case).
28618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ orr(r3, r3, Operand(0x20));  // Convert capture character to lower-case.
28718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ orr(r4, r4, Operand(0x20));  // Also convert input character.
28818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ cmp(r4, r3);
28918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ b(ne, &fail);
29018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ sub(r3, r3, Operand('a'));
29118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ cmp(r3, Operand('z' - 'a'));  // Is r3 a lowercase letter?
29259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ b(ls, &loop_check);  // In range 'a'-'z'.
29359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    // Latin-1: Check for values in range [224,254] but not 247.
29459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ sub(r3, r3, Operand(224 - 'a'));
29559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ cmp(r3, Operand(254 - 224));
29659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ b(hi, &fail);  // Weren't Latin-1 letters.
29759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ cmp(r3, Operand(247 - 224));  // Check for 247.
29859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ b(eq, &fail);
29918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
30018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ bind(&loop_check);
30118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ cmp(r0, r1);
30218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ b(lt, &loop);
30318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ jmp(&success);
30418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
30518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ bind(&fail);
30618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    BranchOrBacktrack(al, on_no_match);
30718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
30818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ bind(&success);
30918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Compute new value of character position after the matched part.
31018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ sub(current_input_offset(), r2, end_of_input_address());
31118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  } else {
31218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    ASSERT(mode_ == UC16);
313c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    int argument_count = 4;
314357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org    __ PrepareCallCFunction(argument_count, r2);
31518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
31618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // r0 - offset of start of capture
31718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // r1 - length of capture
31818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
31918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Put arguments into arguments registers.
32018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Parameters are
32118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    //   r0: Address byte_offset1 - Address captured substring's start.
32218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    //   r1: Address byte_offset2 - Address of current character position.
32318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    //   r2: size_t byte_length - length of capture in bytes(!)
324c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    //   r3: Isolate* isolate
32518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
32618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Address of start of capture.
32718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ add(r0, r0, Operand(end_of_input_address()));
32818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Length of capture.
32918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ mov(r2, Operand(r1));
33018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Save length in callee-save register for use on return.
33118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ mov(r4, Operand(r1));
33218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Address of current input position.
33318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ add(r1, current_input_offset(), Operand(end_of_input_address()));
334c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    // Isolate.
33532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org    __ mov(r3, Operand(ExternalReference::isolate_address(isolate())));
33618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
337c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
338c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      AllowExternalCallThatCantCauseGC scope(masm_);
339c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ExternalReference function =
34032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org          ExternalReference::re_case_insensitive_compare_uc16(isolate());
341c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ CallCFunction(function, argument_count);
342c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
34318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
34418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Check if function returned non-zero for success or zero for failure.
34559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ cmp(r0, Operand::Zero());
34618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    BranchOrBacktrack(eq, on_no_match);
34718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // On success, increment position by length of capture.
34818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ add(current_input_offset(), current_input_offset(), Operand(r4));
34918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
35018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
35118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ bind(&fallthrough);
35218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
35318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
35418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
35518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::CheckNotBackReference(
35618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    int start_reg,
35718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    Label* on_no_match) {
35818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Label fallthrough;
35918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Label success;
36018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
36118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Find length of back-referenced capture.
36218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r0, register_location(start_reg));
36318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r1, register_location(start_reg + 1));
36418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ sub(r1, r1, r0, SetCC);  // Length to check.
36518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Succeed on empty capture (including no capture).
36618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ b(eq, &fallthrough);
36718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
36818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Check that there are enough characters left in the input.
36918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmn(r1, Operand(current_input_offset()));
37018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(gt, on_no_match);
37118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
37218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Compute pointers to match string and capture string
37318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ add(r0, r0, Operand(end_of_input_address()));
37418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ add(r2, end_of_input_address(), Operand(current_input_offset()));
37518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ add(r1, r1, Operand(r0));
37618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
37718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Label loop;
37818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ bind(&loop);
37918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (mode_ == ASCII) {
38018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ ldrb(r3, MemOperand(r0, char_size(), PostIndex));
38118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ ldrb(r4, MemOperand(r2, char_size(), PostIndex));
38218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  } else {
38318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    ASSERT(mode_ == UC16);
38418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ ldrh(r3, MemOperand(r0, char_size(), PostIndex));
38518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ ldrh(r4, MemOperand(r2, char_size(), PostIndex));
38618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
38718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(r3, r4);
38818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(ne, on_no_match);
38918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(r0, r1);
39018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ b(lt, &loop);
39118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
39218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Move current character position to position after match.
39318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ sub(current_input_offset(), r2, end_of_input_address());
39418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ bind(&fallthrough);
39518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
39618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
39718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
398c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.orgvoid RegExpMacroAssemblerARM::CheckNotCharacter(unsigned c,
39918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                                Label* on_not_equal) {
40018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(current_character(), Operand(c));
40118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(ne, on_not_equal);
40218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
40318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
40418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
40518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::CheckCharacterAfterAnd(uint32_t c,
40618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                                     uint32_t mask,
40718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                                     Label* on_equal) {
4087d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  if (c == 0) {
4097d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ tst(current_character(), Operand(mask));
4107d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  } else {
4117d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ and_(r0, current_character(), Operand(mask));
4127d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ cmp(r0, Operand(c));
4137d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  }
41418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(eq, on_equal);
41518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
41618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
41718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
418c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.orgvoid RegExpMacroAssemblerARM::CheckNotCharacterAfterAnd(unsigned c,
419c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org                                                        unsigned mask,
42018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                                        Label* on_not_equal) {
4217d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  if (c == 0) {
4227d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ tst(current_character(), Operand(mask));
4237d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  } else {
4247d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ and_(r0, current_character(), Operand(mask));
4257d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ cmp(r0, Operand(c));
4267d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  }
42718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(ne, on_not_equal);
42818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
42918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
43018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
43118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::CheckNotCharacterAfterMinusAnd(
43218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    uc16 c,
43318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    uc16 minus,
43418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    uc16 mask,
43518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    Label* on_not_equal) {
436154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org  ASSERT(minus < String::kMaxUtf16CodeUnit);
43718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ sub(r0, current_character(), Operand(minus));
43818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ and_(r0, r0, Operand(mask));
43918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(r0, Operand(c));
44018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(ne, on_not_equal);
44118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
44218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
44318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
4441456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgvoid RegExpMacroAssemblerARM::CheckCharacterInRange(
4451456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    uc16 from,
4461456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    uc16 to,
4471456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    Label* on_in_range) {
4481456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  __ sub(r0, current_character(), Operand(from));
4491456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  __ cmp(r0, Operand(to - from));
4501456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  BranchOrBacktrack(ls, on_in_range);  // Unsigned lower-or-same condition.
4511456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org}
4521456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
4531456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
4541456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgvoid RegExpMacroAssemblerARM::CheckCharacterNotInRange(
4551456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    uc16 from,
4561456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    uc16 to,
4571456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    Label* on_not_in_range) {
4581456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  __ sub(r0, current_character(), Operand(from));
4591456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  __ cmp(r0, Operand(to - from));
4601456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  BranchOrBacktrack(hi, on_not_in_range);  // Unsigned higher condition.
4611456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org}
4621456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
4631456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
4641456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgvoid RegExpMacroAssemblerARM::CheckBitInTable(
4651456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    Handle<ByteArray> table,
4661456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    Label* on_bit_set) {
4671456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  __ mov(r0, Operand(table));
46859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  if (mode_ != ASCII || kTableMask != String::kMaxOneByteCharCode) {
4691456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    __ and_(r1, current_character(), Operand(kTableSize - 1));
4701456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    __ add(r1, r1, Operand(ByteArray::kHeaderSize - kHeapObjectTag));
4711456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  } else {
4721456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    __ add(r1,
4731456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org           current_character(),
4741456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org           Operand(ByteArray::kHeaderSize - kHeapObjectTag));
4751456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  }
4761456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  __ ldrb(r0, MemOperand(r0, r1));
47759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(r0, Operand::Zero());
4781456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  BranchOrBacktrack(ne, on_bit_set);
4791456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org}
4801456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
4811456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
48218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgbool RegExpMacroAssemblerARM::CheckSpecialCharacterClass(uc16 type,
48318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                                         Label* on_no_match) {
48418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Range checks (c in min..max) are generally implemented by an unsigned
48518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // (c - min) <= (max - min) check
48618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  switch (type) {
48718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  case 's':
48818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Match space-characters
48918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    if (mode_ == ASCII) {
4906e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      // One byte space characters are '\t'..'\r', ' ' and \u00a0.
49118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      Label success;
49218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      __ cmp(current_character(), Operand(' '));
49318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      __ b(eq, &success);
49418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      // Check range 0x09..0x0d
49518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      __ sub(r0, current_character(), Operand('\t'));
49618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      __ cmp(r0, Operand('\r' - '\t'));
4976e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      __ b(ls, &success);
4986e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      // \u00a0 (NBSP).
4996e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      __ cmp(r0, Operand(0x00a0 - '\t'));
5006e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      BranchOrBacktrack(ne, on_no_match);
50118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      __ bind(&success);
50218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      return true;
50318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    }
50418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    return false;
50518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  case 'S':
5066e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org    // The emitted code for generic character classes is good enough.
50718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    return false;
50818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  case 'd':
50918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Match ASCII digits ('0'..'9')
51018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ sub(r0, current_character(), Operand('0'));
511dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    __ cmp(r0, Operand('9' - '0'));
51218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    BranchOrBacktrack(hi, on_no_match);
51318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    return true;
51418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  case 'D':
51518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Match non ASCII-digits
51618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ sub(r0, current_character(), Operand('0'));
51718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ cmp(r0, Operand('9' - '0'));
51818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    BranchOrBacktrack(ls, on_no_match);
51918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    return true;
52018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  case '.': {
52118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
52218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ eor(r0, current_character(), Operand(0x01));
52318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
52418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ sub(r0, r0, Operand(0x0b));
52518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ cmp(r0, Operand(0x0c - 0x0b));
52618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    BranchOrBacktrack(ls, on_no_match);
52718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    if (mode_ == UC16) {
52818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      // Compare original value to 0x2028 and 0x2029, using the already
52918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      // computed (current_char ^ 0x01 - 0x0b). I.e., check for
53018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      // 0x201d (0x2028 - 0x0b) or 0x201e.
53118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      __ sub(r0, r0, Operand(0x2028 - 0x0b));
53218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      __ cmp(r0, Operand(1));
53318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      BranchOrBacktrack(ls, on_no_match);
53418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    }
53518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    return true;
53618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
5370c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  case 'n': {
538b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
539b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ eor(r0, current_character(), Operand(0x01));
540b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
541b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ sub(r0, r0, Operand(0x0b));
542b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ cmp(r0, Operand(0x0c - 0x0b));
543b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    if (mode_ == ASCII) {
544b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      BranchOrBacktrack(hi, on_no_match);
545b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    } else {
546b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      Label done;
547b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      __ b(ls, &done);
548b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      // Compare original value to 0x2028 and 0x2029, using the already
549b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      // computed (current_char ^ 0x01 - 0x0b). I.e., check for
550b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      // 0x201d (0x2028 - 0x0b) or 0x201e.
551b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      __ sub(r0, r0, Operand(0x2028 - 0x0b));
552b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      __ cmp(r0, Operand(1));
553b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      BranchOrBacktrack(hi, on_no_match);
554b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      __ bind(&done);
5550c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    }
556b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    return true;
557b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
5580c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  case 'w': {
559b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    if (mode_ != ASCII) {
560b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      // Table is 128 entries, so all ASCII characters can be tested.
561b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      __ cmp(current_character(), Operand('z'));
562b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      BranchOrBacktrack(hi, on_no_match);
563b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
564b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    ExternalReference map = ExternalReference::re_word_character_map();
565b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ mov(r0, Operand(map));
566b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ ldrb(r0, MemOperand(r0, current_character()));
56759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ cmp(r0, Operand::Zero());
568b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    BranchOrBacktrack(eq, on_no_match);
5690c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    return true;
5700c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  }
5710c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  case 'W': {
572b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    Label done;
573b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    if (mode_ != ASCII) {
574b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      // Table is 128 entries, so all ASCII characters can be tested.
575b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      __ cmp(current_character(), Operand('z'));
576b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      __ b(hi, &done);
577b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
578b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    ExternalReference map = ExternalReference::re_word_character_map();
579b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ mov(r0, Operand(map));
580b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ ldrb(r0, MemOperand(r0, current_character()));
58159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ cmp(r0, Operand::Zero());
582b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    BranchOrBacktrack(ne, on_no_match);
583b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    if (mode_ != ASCII) {
584b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      __ bind(&done);
585b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
5860c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    return true;
5870c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  }
58818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  case '*':
58918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Match any character.
59018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    return true;
5910c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  // No custom implementation (yet): s(UC16), S(UC16).
59218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  default:
59318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    return false;
59418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
59518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
59618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
59718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
59818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::Fail() {
59918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ mov(r0, Operand(FAILURE));
60018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ jmp(&exit_label_);
60118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
60218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
60318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
60483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgHandle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
60515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  Label return_r0;
60618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Finalize code - write the entry point code now we know how many
60718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // registers we need.
60818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
60918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Entry code:
61018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ bind(&entry_label_);
611c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
612c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Tell the system that we have a stack frame.  Because the type is MANUAL, no
613c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // is generated.
614c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  FrameScope scope(masm_, StackFrame::MANUAL);
615c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
616c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Actually emit code to start a new stack frame.
61718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Push arguments
61818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Save callee-save registers.
61918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Start new stack frame.
62049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Store link register in existing stack-cell.
62118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Order here should correspond to order of offset constants in header file.
62218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  RegList registers_to_retain = r4.bit() | r5.bit() | r6.bit() |
62318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      r7.bit() | r8.bit() | r9.bit() | r10.bit() | fp.bit();
62418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  RegList argument_registers = r0.bit() | r1.bit() | r2.bit() | r3.bit();
62518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ stm(db_w, sp, argument_registers | registers_to_retain | lr.bit());
62649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // Set frame pointer in space for it if this is not a direct call
62749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  // from generated code.
62818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ add(frame_pointer(), sp, Operand(4 * kPointerSize));
62959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ mov(r0, Operand::Zero());
63015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ push(r0);  // Make room for success counter and initialize it to 0.
63118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ push(r0);  // Make room for "position - 1" constant (value is irrelevant).
63218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Check if we have space on the stack for registers.
63318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Label stack_limit_hit;
63418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Label stack_ok;
63518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
636c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  ExternalReference stack_limit =
63732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ExternalReference::address_of_stack_limit(isolate());
638c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  __ mov(r0, Operand(stack_limit));
63918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r0, MemOperand(r0));
64018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ sub(r0, sp, r0, SetCC);
64118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Handle it if the stack pointer is already below the stack limit.
64218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ b(ls, &stack_limit_hit);
64318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Check if there is room for the variable number of registers above
64418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // the stack limit.
64518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(r0, Operand(num_registers_ * kPointerSize));
64618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ b(hs, &stack_ok);
64718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Exit with OutOfMemory exception. There is not enough space on the stack
64818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // for our working registers.
64918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ mov(r0, Operand(EXCEPTION));
65015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ jmp(&return_r0);
65118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
65218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ bind(&stack_limit_hit);
65318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  CallCheckStackGuardState(r0);
65459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(r0, Operand::Zero());
65518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // If returned value is non-zero, we exit with the returned value as result.
65615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ b(ne, &return_r0);
65718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
65818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ bind(&stack_ok);
65918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
66018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Allocate space on stack for registers.
66118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ sub(sp, sp, Operand(num_registers_ * kPointerSize));
66218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Load string end.
66318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
66418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Load input start.
66518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r0, MemOperand(frame_pointer(), kInputStart));
66618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Find negative length (offset of start relative to end).
66718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ sub(current_input_offset(), r0, end_of_input_address());
668cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  // Set r0 to address of char before start of the input string
66918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // (effectively string position -1).
670cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  __ ldr(r1, MemOperand(frame_pointer(), kStartIndex));
67118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ sub(r0, current_input_offset(), Operand(char_size()));
672cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  __ sub(r0, r0, Operand(r1, LSL, (mode_ == UC16) ? 1 : 0));
67318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Store this value in a local variable, for use when clearing
67418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // position registers.
67518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ str(r0, MemOperand(frame_pointer(), kInputStartMinusOne));
676b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
67715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Initialize code pointer register
67815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ mov(code_pointer(), Operand(masm_->CodeObject()));
67915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
68015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  Label load_char_start_regexp, start_regexp;
68115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Load newline if index is at start, previous character otherwise.
68259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(r1, Operand::Zero());
68315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ b(ne, &load_char_start_regexp);
68415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ mov(current_character(), Operand('\n'), LeaveCC, eq);
68515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ jmp(&start_regexp);
68615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
68715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Global regexp restarts matching here.
68815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ bind(&load_char_start_regexp);
68915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Load previous char as initial value of current character register.
69015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  LoadCurrentCharacterUnchecked(-1, 1);
69115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ bind(&start_regexp);
692b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
69315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Initialize on-stack registers.
69418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (num_saved_registers_ > 0) {  // Always is, if generated from a regexp.
69518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Fill saved registers with initial value = start offset - 1
69615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    if (num_saved_registers_ > 8) {
69715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      // Address of register 0.
69815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ add(r1, frame_pointer(), Operand(kRegisterZero));
69915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ mov(r2, Operand(num_saved_registers_));
70015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      Label init_loop;
70115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ bind(&init_loop);
70215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ str(r0, MemOperand(r1, kPointerSize, NegPostIndex));
70315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ sub(r2, r2, Operand(1), SetCC);
70415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ b(ne, &init_loop);
70515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    } else {
70615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      for (int i = 0; i < num_saved_registers_; i++) {
70715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org        __ str(r0, register_location(i));
70815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      }
70915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    }
71018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
71118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
71218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Initialize backtrack stack pointer.
71318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd));
71418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
71515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ jmp(&start_label_);
71618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
71718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Exit code:
71818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (success_label_.is_linked()) {
71918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Save captures when successful.
72018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ bind(&success_label_);
72118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    if (num_saved_registers_ > 0) {
72218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      // copy captures to output
72318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      __ ldr(r1, MemOperand(frame_pointer(), kInputStart));
72418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      __ ldr(r0, MemOperand(frame_pointer(), kRegisterOutput));
725cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org      __ ldr(r2, MemOperand(frame_pointer(), kStartIndex));
72618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      __ sub(r1, end_of_input_address(), r1);
72718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      // r1 is length of input in bytes.
72818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      if (mode_ == UC16) {
72918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org        __ mov(r1, Operand(r1, LSR, 1));
73018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      }
73118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      // r1 is length of input in characters.
732cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org      __ add(r1, r1, Operand(r2));
733cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org      // r1 is length of string in characters.
73418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
73518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      ASSERT_EQ(0, num_saved_registers_ % 2);
73618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      // Always an even number of capture registers. This allows us to
73718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      // unroll the loop once to add an operation between a load of a register
73818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      // and the following use of that register.
73918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      for (int i = 0; i < num_saved_registers_; i += 2) {
74018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org        __ ldr(r2, register_location(i));
74118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org        __ ldr(r3, register_location(i + 1));
742400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        if (i == 0 && global_with_zero_length_check()) {
74315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org          // Keep capture start in r4 for the zero-length check later.
74415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org          __ mov(r4, r2);
74515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org        }
74618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org        if (mode_ == UC16) {
74718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org          __ add(r2, r1, Operand(r2, ASR, 1));
74818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org          __ add(r3, r1, Operand(r3, ASR, 1));
74918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org        } else {
75018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org          __ add(r2, r1, Operand(r2));
75118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org          __ add(r3, r1, Operand(r3));
75218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org        }
75318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org        __ str(r2, MemOperand(r0, kPointerSize, PostIndex));
75418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org        __ str(r3, MemOperand(r0, kPointerSize, PostIndex));
75518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      }
75618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    }
75715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
75815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    if (global()) {
75915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      // Restart matching if the regular expression is flagged as global.
76015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ ldr(r0, MemOperand(frame_pointer(), kSuccessfulCaptures));
76115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ ldr(r1, MemOperand(frame_pointer(), kNumOutputRegisters));
76215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ ldr(r2, MemOperand(frame_pointer(), kRegisterOutput));
76315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      // Increment success counter.
76415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ add(r0, r0, Operand(1));
76515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ str(r0, MemOperand(frame_pointer(), kSuccessfulCaptures));
76615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      // Capture results have been stored, so the number of remaining global
76715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      // output registers is reduced by the number of stored captures.
76815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ sub(r1, r1, Operand(num_saved_registers_));
76915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      // Check whether we have enough room for another set of capture results.
77015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ cmp(r1, Operand(num_saved_registers_));
77115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ b(lt, &return_r0);
77215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
77315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ str(r1, MemOperand(frame_pointer(), kNumOutputRegisters));
77415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      // Advance the location for output.
77515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ add(r2, r2, Operand(num_saved_registers_ * kPointerSize));
77615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ str(r2, MemOperand(frame_pointer(), kRegisterOutput));
77715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
77815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      // Prepare r0 to initialize registers with its value in the next run.
77915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ ldr(r0, MemOperand(frame_pointer(), kInputStartMinusOne));
780400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org
781400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org      if (global_with_zero_length_check()) {
782400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        // Special case for zero-length matches.
783400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        // r4: capture start index
784400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        __ cmp(current_input_offset(), r4);
785400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        // Not a zero-length match, restart.
786400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        __ b(ne, &load_char_start_regexp);
787400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        // Offset from the end is zero if we already reached the end.
78859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org        __ cmp(current_input_offset(), Operand::Zero());
789400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        __ b(eq, &exit_label_);
790400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        // Advance current position after a zero-length match.
791400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        __ add(current_input_offset(),
792400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org               current_input_offset(),
793400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org               Operand((mode_ == UC16) ? 2 : 1));
794400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org      }
795400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org
79615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ b(&load_char_start_regexp);
79715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    } else {
79815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ mov(r0, Operand(SUCCESS));
79915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    }
80018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
80115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
80218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Exit and return r0
80318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ bind(&exit_label_);
80415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  if (global()) {
80515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    __ ldr(r0, MemOperand(frame_pointer(), kSuccessfulCaptures));
80615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  }
80715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
80815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ bind(&return_r0);
80918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Skip sp past regexp registers and local variables..
81018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ mov(sp, frame_pointer());
81118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Restore registers r4..r11 and return (restoring lr to pc).
81218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldm(ia_w, sp, registers_to_retain | pc.bit());
81318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
81418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Backtrack code (branch target for conditional backtracks).
81518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (backtrack_label_.is_linked()) {
81618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ bind(&backtrack_label_);
81718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    Backtrack();
81818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
81918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
82018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Label exit_with_exception;
82118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
82218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Preempt-code
82318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (check_preempt_label_.is_linked()) {
82418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    SafeCallTarget(&check_preempt_label_);
82518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
82618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    CallCheckStackGuardState(r0);
82759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ cmp(r0, Operand::Zero());
82818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // If returning non-zero, we should end execution with the given
82918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // result as return value.
83015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    __ b(ne, &return_r0);
83118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
83218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // String might have moved: Reload end of string from frame.
83318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ ldr(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
83418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    SafeReturn();
83518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
83618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
83718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Backtrack stack overflow code.
83818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (stack_overflow_label_.is_linked()) {
83918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    SafeCallTarget(&stack_overflow_label_);
84018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Reached if the backtrack-stack limit has been hit.
84118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    Label grow_failed;
84218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
84349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org    // Call GrowStack(backtrack_stackpointer(), &stack_base)
844c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    static const int num_arguments = 3;
845357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org    __ PrepareCallCFunction(num_arguments, r0);
84618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ mov(r0, backtrack_stackpointer());
84718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ add(r1, frame_pointer(), Operand(kStackHighEnd));
84832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org    __ mov(r2, Operand(ExternalReference::isolate_address(isolate())));
84918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    ExternalReference grow_stack =
85032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        ExternalReference::re_grow_stack(isolate());
851357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org    __ CallCFunction(grow_stack, num_arguments);
85218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // If return NULL, we have failed to grow the stack, and
85318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // must exit with a stack-overflow exception.
85459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ cmp(r0, Operand::Zero());
85518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ b(eq, &exit_with_exception);
85618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Otherwise use return value as new stack pointer.
85718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ mov(backtrack_stackpointer(), r0);
85818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Restore saved registers and continue.
85918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    SafeReturn();
86018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
86118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
86218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (exit_with_exception.is_linked()) {
86318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // If any of the code above needed to exit with an exception.
86418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ bind(&exit_with_exception);
86518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Exit with Result EXCEPTION(-1) to signal thrown exception.
86618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ mov(r0, Operand(EXCEPTION));
86715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    __ jmp(&return_r0);
86818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
86918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
87018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  CodeDesc code_desc;
87118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  masm_->GetCode(&code_desc);
872d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  Handle<Code> code = isolate()->factory()->NewCode(
873d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org      code_desc, Code::ComputeFlags(Code::REGEXP), masm_->CodeObject());
874e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org  PROFILE(masm_->isolate(), RegExpCodeCreateEvent(*code, *source));
87583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return Handle<HeapObject>::cast(code);
87618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
87718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
87818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
87918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::GoTo(Label* to) {
88018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(al, to);
88118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
88218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
88318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
88418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::IfRegisterGE(int reg,
88518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                           int comparand,
88618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                           Label* if_ge) {
88718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r0, register_location(reg));
88818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(r0, Operand(comparand));
88918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(ge, if_ge);
89018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
89118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
89218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
89318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::IfRegisterLT(int reg,
89418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                           int comparand,
89518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                           Label* if_lt) {
89618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r0, register_location(reg));
89718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(r0, Operand(comparand));
89818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(lt, if_lt);
89918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
900a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
9019a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
90218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::IfRegisterEqPos(int reg,
90318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                              Label* if_eq) {
90418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r0, register_location(reg));
90518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(r0, Operand(current_input_offset()));
90618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(eq, if_eq);
90718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
90818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
90918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
91018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgRegExpMacroAssembler::IrregexpImplementation
91118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    RegExpMacroAssemblerARM::Implementation() {
91218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  return kARMImplementation;
91318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
91418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
91518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
91618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::LoadCurrentCharacter(int cp_offset,
91718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                                   Label* on_end_of_input,
91818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                                   bool check_bounds,
91918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                                   int characters) {
92018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ASSERT(cp_offset >= -1);      // ^ and \b can look behind one character.
92118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ASSERT(cp_offset < (1<<30));  // Be sane! (And ensure negation works)
92218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (check_bounds) {
92318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    CheckPosition(cp_offset + characters - 1, on_end_of_input);
92418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
92518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  LoadCurrentCharacterUnchecked(cp_offset, characters);
92618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
92718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
92818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
92918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::PopCurrentPosition() {
93018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Pop(current_input_offset());
93118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
93218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
93318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
93418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::PopRegister(int register_index) {
93518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Pop(r0);
93618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ str(r0, register_location(register_index));
93718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
93818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
93918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
94018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::PushBacktrack(Label* label) {
9414a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ mov_label_offset(r0, label);
94218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Push(r0);
94318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  CheckStackLimit();
94418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
94518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
94618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
94718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::PushCurrentPosition() {
94818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Push(current_input_offset());
94918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
95018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
95118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
95218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::PushRegister(int register_index,
95318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                           StackCheckFlag check_stack_limit) {
95418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r0, register_location(register_index));
95518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Push(r0);
95618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (check_stack_limit) CheckStackLimit();
95718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
95818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
95918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
96018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::ReadCurrentPositionFromRegister(int reg) {
96118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(current_input_offset(), register_location(reg));
96218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
96318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
96418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
96518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::ReadStackPointerFromRegister(int reg) {
96618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(backtrack_stackpointer(), register_location(reg));
96718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r0, MemOperand(frame_pointer(), kStackHighEnd));
96818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ add(backtrack_stackpointer(), backtrack_stackpointer(), Operand(r0));
96918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
97018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
97118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
9724a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.orgvoid RegExpMacroAssemblerARM::SetCurrentPositionFromEnd(int by) {
9734a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  Label after_position;
9744a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  __ cmp(current_input_offset(), Operand(-by * char_size()));
9754a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  __ b(ge, &after_position);
9764a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  __ mov(current_input_offset(), Operand(-by * char_size()));
9774a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  // On RegExp code entry (where this operation is used), the character before
9784a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  // the current position is expected to be already loaded.
9794a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  // We have advanced the position, so it's safe to read backwards.
9804a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  LoadCurrentCharacterUnchecked(-1, 1);
9814a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  __ bind(&after_position);
9824a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org}
9834a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org
9844a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org
98518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::SetRegister(int register_index, int to) {
98618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ASSERT(register_index >= num_saved_registers_);  // Reserved for positions!
98718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ mov(r0, Operand(to));
98818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ str(r0, register_location(register_index));
98918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
99018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
99118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
99215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.orgbool RegExpMacroAssemblerARM::Succeed() {
99318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ jmp(&success_label_);
99415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  return global();
99518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
99618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
99718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
99818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::WriteCurrentPositionToRegister(int reg,
99918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                                             int cp_offset) {
100018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (cp_offset == 0) {
100118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ str(current_input_offset(), register_location(reg));
100218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  } else {
100318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ add(r0, current_input_offset(), Operand(cp_offset * char_size()));
100418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ str(r0, register_location(reg));
100518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
100618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
100718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
100818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
100918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::ClearRegisters(int reg_from, int reg_to) {
101018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ASSERT(reg_from <= reg_to);
101118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r0, MemOperand(frame_pointer(), kInputStartMinusOne));
101218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  for (int reg = reg_from; reg <= reg_to; reg++) {
101318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ str(r0, register_location(reg));
101418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
101518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
101618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
101718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
101818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::WriteStackPointerToRegister(int reg) {
101918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r1, MemOperand(frame_pointer(), kStackHighEnd));
102018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ sub(r0, backtrack_stackpointer(), r1);
102118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ str(r0, register_location(reg));
102218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
102318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
102418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
102518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org// Private methods:
102618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
102718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::CallCheckStackGuardState(Register scratch) {
1028c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ PrepareCallCFunction(3, scratch);
1029c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
103018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // RegExp code frame pointer.
103118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ mov(r2, frame_pointer());
103218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Code* of self.
103318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ mov(r1, Operand(masm_->CodeObject()));
1034c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
1035c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // We need to make room for the return address on the stack.
1036c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  int stack_alignment = OS::ActivationFrameAlignment();
1037c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  ASSERT(IsAligned(stack_alignment, kPointerSize));
1038c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ sub(sp, sp, Operand(stack_alignment));
1039c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
1040c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // r0 will point to the return address, placed by DirectCEntry.
1041c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ mov(r0, sp);
1042c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
104318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ExternalReference stack_guard_check =
104432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ExternalReference::re_check_stack_guard_state(isolate());
1045c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ mov(ip, Operand(stack_guard_check));
1046c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  DirectCEntryStub stub;
1047c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  stub.GenerateCall(masm_, ip);
1048c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
1049c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // Drop the return address from the stack.
1050c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ add(sp, sp, Operand(stack_alignment));
1051c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
1052c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  ASSERT(stack_alignment != 0);
1053c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ ldr(sp, MemOperand(sp, 0));
1054c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
1055c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ mov(code_pointer(), Operand(masm_->CodeObject()));
105618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
105718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
105818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
105918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org// Helper function for reading a value out of a stack frame.
106018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgtemplate <typename T>
106118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgstatic T& frame_entry(Address re_frame, int frame_offset) {
106218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset));
106318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
106418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
106518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
106618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgint RegExpMacroAssemblerARM::CheckStackGuardState(Address* return_address,
106718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                                  Code* re_code,
106818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                                  Address re_frame) {
1069ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
1070ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (isolate->stack_guard()->IsStackOverflow()) {
1071ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    isolate->StackOverflow();
107218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    return EXCEPTION;
107318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
107418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
107518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // If not real stack overflow the stack guard was used to interrupt
107618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // execution for another purpose.
107718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
1078c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  // If this is a direct call from JavaScript retry the RegExp forcing the call
1079c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  // through the runtime system. Currently the direct call cannot handle a GC.
1080c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  if (frame_entry<int>(re_frame, kDirectCall) == 1) {
1081c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org    return RETRY;
1082c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org  }
1083c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
108418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Prepare for possible GC.
10854668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  HandleScope handles(isolate);
108618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Handle<Code> code_handle(re_code);
108718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
108818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
10894668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
109018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Current string.
10918e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  bool is_ascii = subject->IsOneByteRepresentationUnderneath();
109218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
109318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ASSERT(re_code->instruction_start() <= *return_address);
109418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ASSERT(*return_address <=
109518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      re_code->instruction_start() + re_code->instruction_size());
109618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
1097812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
109818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
109918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (*code_handle != re_code) {  // Return address no longer valid
110080c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    int delta = code_handle->address() - re_code->address();
110118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // Overwrite the return address on the stack.
110218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    *return_address += delta;
110318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
110418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
110518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (result->IsException()) {
110618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    return EXCEPTION;
110718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
110818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
11094668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  Handle<String> subject_tmp = subject;
11104668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  int slice_offset = 0;
11114668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
11124668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // Extract the underlying string and the slice offset.
11134668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  if (StringShape(*subject_tmp).IsCons()) {
11144668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
11154668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  } else if (StringShape(*subject_tmp).IsSliced()) {
11164668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    SlicedString* slice = SlicedString::cast(*subject_tmp);
11174668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    subject_tmp = Handle<String>(slice->parent());
11184668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    slice_offset = slice->offset();
11194668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  }
11204668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
112118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // String might have changed.
11228e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  if (subject_tmp->IsOneByteRepresentation() != is_ascii) {
112318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // If we changed between an ASCII and an UC16 string, the specialized
112418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // code cannot be used, and we need to restart regexp matching from
112518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // scratch (including, potentially, compiling a new version of the code).
112618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    return RETRY;
112718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
112818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
112918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Otherwise, the content of the string might have moved. It must still
113018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // be a sequential or external string with the same content.
113118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Update the start and end pointers in the stack frame to the current
113218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // location (whether it has actually moved or not).
11334668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  ASSERT(StringShape(*subject_tmp).IsSequential() ||
11344668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org      StringShape(*subject_tmp).IsExternal());
113518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
113618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // The original start address of the characters to match.
113718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
113818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
113918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Find the current start address of the same character at the current string
114018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // position.
114118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  int start_index = frame_entry<int>(re_frame, kStartIndex);
11424668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  const byte* new_address = StringCharacterPosition(*subject_tmp,
11434668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org                                                    start_index + slice_offset);
114418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
114518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (start_address != new_address) {
114618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // If there is a difference, update the object pointer and start and end
114718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    // addresses in the RegExp stack frame to match the new value.
114818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
11494668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    int byte_length = static_cast<int>(end_address - start_address);
115018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    frame_entry<const String*>(re_frame, kInputString) = *subject;
115118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    frame_entry<const byte*>(re_frame, kInputStart) = new_address;
115218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
1153394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  } else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
1154394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Subject string might have been a ConsString that underwent
1155394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // short-circuiting during GC. That will not change start_address but
1156394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // will change pointer inside the subject handle.
1157394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    frame_entry<const String*>(re_frame, kInputString) = *subject;
115818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
115918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
116018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  return 0;
116118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
116218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
116318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
116418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgMemOperand RegExpMacroAssemblerARM::register_location(int register_index) {
116518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ASSERT(register_index < (1<<30));
116618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (num_registers_ <= register_index) {
116718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    num_registers_ = register_index + 1;
116818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
116918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  return MemOperand(frame_pointer(),
117018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                    kRegisterZero - register_index * kPointerSize);
117118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
117218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
117318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
117418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::CheckPosition(int cp_offset,
117518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                            Label* on_outside_input) {
117618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(current_input_offset(), Operand(-cp_offset * char_size()));
117718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  BranchOrBacktrack(ge, on_outside_input);
117818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
117918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
118018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
118118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::BranchOrBacktrack(Condition condition,
118218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                                Label* to) {
118318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (condition == al) {  // Unconditional.
118418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    if (to == NULL) {
118518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      Backtrack();
118618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org      return;
118718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    }
118818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ jmp(to);
118918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    return;
119018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
119118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (to == NULL) {
119218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    __ b(condition, &backtrack_label_);
119318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    return;
119418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
119518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ b(condition, to);
119618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
119718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
119818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
119918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::SafeCall(Label* to, Condition cond) {
120018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ bl(to, cond);
120118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
120218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
120318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
120418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::SafeReturn() {
120518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ pop(lr);
120618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ add(pc, lr, Operand(masm_->CodeObject()));
120718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
120818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
120918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
121018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::SafeCallTarget(Label* name) {
121118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ bind(name);
121218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ sub(lr, lr, Operand(masm_->CodeObject()));
121318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ push(lr);
121418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
121518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
121618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
121718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::Push(Register source) {
121818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ASSERT(!source.is(backtrack_stackpointer()));
121918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ str(source,
122018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org         MemOperand(backtrack_stackpointer(), kPointerSize, NegPreIndex));
122118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
122218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
122318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
122418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::Pop(Register target) {
122518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ASSERT(!target.is(backtrack_stackpointer()));
122618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(target,
122718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org         MemOperand(backtrack_stackpointer(), kPointerSize, PostIndex));
122818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
122918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
123018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
123118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::CheckPreemption() {
123218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  // Check for preemption.
1233c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  ExternalReference stack_limit =
123432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ExternalReference::address_of_stack_limit(isolate());
1235c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  __ mov(r0, Operand(stack_limit));
123618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ ldr(r0, MemOperand(r0));
123718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  __ cmp(sp, r0);
123818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  SafeCall(&check_preempt_label_, ls);
123918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
124018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
124118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
124218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::CheckStackLimit() {
12433811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ExternalReference stack_limit =
124432d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ExternalReference::address_of_regexp_stack_limit(isolate());
12453811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  __ mov(r0, Operand(stack_limit));
12463811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  __ ldr(r0, MemOperand(r0));
12473811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  __ cmp(backtrack_stackpointer(), Operand(r0));
12483811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  SafeCall(&stack_overflow_label_, ls);
124918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
125018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
125118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
125289e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.orgbool RegExpMacroAssemblerARM::CanReadUnaligned() {
125389e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  return CpuFeatures::IsSupported(UNALIGNED_ACCESSES) && !slow_safe();
125489e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org}
125589e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org
125689e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org
125718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.orgvoid RegExpMacroAssemblerARM::LoadCurrentCharacterUnchecked(int cp_offset,
125818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org                                                            int characters) {
125918ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  Register offset = current_input_offset();
126018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (cp_offset != 0) {
126115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    // r4 is not being used to store the capture start index at this point.
126215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    __ add(r4, current_input_offset(), Operand(cp_offset * char_size()));
126315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    offset = r4;
126418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
1265720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org  // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU
1266720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org  // and the operating system running on the target allow it.
1267720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org  // If unaligned load/stores are not supported then this function must only
1268720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org  // be used to load a single character at a time.
126989e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  if (!CanReadUnaligned()) {
127089e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org    ASSERT(characters == 1);
127189e18f5599cb4cd462cb1ed324addd7388fb4d60rossberg@chromium.org  }
1272720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org
127318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (mode_ == ASCII) {
1274720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org    if (characters == 4) {
1275720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org      __ ldr(current_character(), MemOperand(end_of_input_address(), offset));
1276720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org    } else if (characters == 2) {
1277720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org      __ ldrh(current_character(), MemOperand(end_of_input_address(), offset));
1278720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org    } else {
1279720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org      ASSERT(characters == 1);
1280720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org      __ ldrb(current_character(), MemOperand(end_of_input_address(), offset));
1281720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org    }
128218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  } else {
128318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    ASSERT(mode_ == UC16);
1284720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org    if (characters == 2) {
1285720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org      __ ldr(current_character(), MemOperand(end_of_input_address(), offset));
1286720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org    } else {
1287720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org      ASSERT(characters == 1);
1288720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org      __ ldrh(current_character(), MemOperand(end_of_input_address(), offset));
1289720dc0bc17114e33b9b2177fcb6726bda9cabd62sgjesse@chromium.org    }
129018ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
129118ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}
129218ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
129318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
129418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org#undef __
129518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
1296c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org#endif  // V8_INTERPRETED_REGEXP
129718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org
129818ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org}}  // namespace v8::internal
12999dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
13009dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif  // V8_TARGET_ARCH_ARM
1301