1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_ARM)
31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "unicode.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "log.h"
34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "code-stubs.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "regexp-stack.h"
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "macro-assembler.h"
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "regexp-macro-assembler.h"
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "arm/regexp-macro-assembler-arm.h"
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifndef V8_INTERPRETED_REGEXP
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/*
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * This assembler uses the following register assignment convention
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r5 : Pointer to current code object (Code*) including heap object tag.
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r6 : Current position in input, as negative offset from end of string.
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *        Please notice that this is the byte offset, not the character offset!
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r7 : Currently loaded character. Must be loaded using
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *        LoadCurrentCharacter before using any of the dispatch methods.
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r8 : points to tip of backtrack stack
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r9 : Unused, might be used by C code and expected unchanged.
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r10 : End of input (points to byte after last character in input).
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r11 : Frame pointer. Used to access arguments, local variables and
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *         RegExp registers.
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r12 : IP register, used by assembler. Very volatile.
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r13/sp : points to tip of C stack.
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The remaining registers are free for computations.
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Each call to a public method should retain this convention.
61e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The stack will have the following structure:
6344f0eee88ff00398ff7f715fab053374d808c90dSteve Block *  - fp[52]  Isolate* isolate   (Address of the current isolate)
64e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  - fp[48]  direct_call  (if 1, direct call from JavaScript code,
65e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *                          if 0, call through the runtime system).
66e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  - fp[44]  stack_area_base (High end of the memory area to use as
67e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *                             backtracking stack).
68e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  - fp[40]  int* capture_array (int[num_saved_registers_], for output).
69e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  - fp[36]  secondary link/return address used by native call.
70e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  --- sp when called ---
71e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  - fp[32]  return address (lr).
72e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  - fp[28]  old frame pointer (r11).
73e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  - fp[0..24]  backup of registers r4..r10.
74e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  --- frame pointer ----
75e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  - fp[-4]  end of input       (Address of end of string).
76e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  - fp[-8]  start of input     (Address of first character in string).
77e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  - fp[-12] start index        (character index of start).
78e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  - fp[-16] void* input_string (location of a handle containing the string).
79e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  - fp[-20] Offset of location before start of input (effectively character
80e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *            position -1). Used to initialize capture registers to a
81e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *            non-position.
82e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  - fp[-24] At start (if 1, we are starting at the start of the
83e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *    string, otherwise 0)
84e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  - fp[-28] register 0         (Only positions must be stored in the first
85e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  -         register 1          num_saved_registers_ registers)
86e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  -         ...
87e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  -         register num_registers-1
88e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *  --- sp ---
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The first num_saved_registers_ registers are initialized to point to
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * "character -1" in the string (i.e., char_size() bytes before the first
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * character of the string). The remaining registers start out as garbage.
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The data up to the return address must be placed there by the calling
95e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * code and the remaining arguments are passed in registers, e.g. by calling the
96e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * code entry as cast to a function with the signature:
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * int (*match)(String* input_string,
98e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke *              int start_index,
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *              Address start,
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *              Address end,
101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *              Address secondary_return_address,  // Only used by native call.
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *              int* capture_output_array,
103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke *              byte* stack_area_base,
104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *              bool direct_call = false)
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The call is performed by NativeRegExpMacroAssembler::Execute()
106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro
107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * in arm/simulator-arm.h.
108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * When calling as a non-direct call (i.e., from C++ code), the return address
109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * area is overwritten with the LR register by the RegExp code. When doing a
110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * direct call from generated code, the return address is placed there by
111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * the calling code, as in a normal exit frame.
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm_)
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssemblerARM::RegExpMacroAssemblerARM(
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Mode mode,
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int registers_to_save)
1198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : masm_(new MacroAssembler(Isolate::Current(), NULL, kRegExpCodeSize)),
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      mode_(mode),
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      num_registers_(registers_to_save),
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      num_saved_registers_(registers_to_save),
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      entry_label_(),
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      start_label_(),
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      success_label_(),
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      backtrack_label_(),
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      exit_label_() {
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, registers_to_save % 2);
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&entry_label_);   // We'll write the entry code later.
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EmitBacktrackConstantPool();
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&start_label_);  // And then continue from here.
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssemblerARM::~RegExpMacroAssemblerARM() {
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  delete masm_;
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Unuse labels in case we throw away the assembler without calling GetCode.
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  entry_label_.Unuse();
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  start_label_.Unuse();
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  success_label_.Unuse();
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  backtrack_label_.Unuse();
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  exit_label_.Unuse();
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  check_preempt_label_.Unuse();
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stack_overflow_label_.Unuse();
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerARM::stack_limit_slack()  {
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return RegExpStack::kStackLimitSlack;
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::AdvanceCurrentPosition(int by) {
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (by != 0) {
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(current_input_offset(),
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block           current_input_offset(), Operand(by * char_size()));
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::AdvanceRegister(int reg, int by) {
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(reg >= 0);
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(reg < num_registers_);
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (by != 0) {
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(r0, register_location(reg));
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, r0, Operand(by));
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r0, register_location(reg));
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::Backtrack() {
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckPreemption();
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Pop Code* offset from backtrack stack, add Code* and jump to location.
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Pop(r0);
1766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ add(pc, r0, Operand(code_pointer()));
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::Bind(Label* label) {
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(label);
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckCharacter(uint32_t c, Label* on_equal) {
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(current_character(), Operand(c));
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(eq, on_equal);
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckCharacterGT(uc16 limit, Label* on_greater) {
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(current_character(), Operand(limit));
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(gt, on_greater);
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckAtStart(Label* on_at_start) {
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label not_at_start;
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Did we start the match at the start of the string at all?
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(frame_pointer(), kAtStart));
2019ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  __ cmp(r0, Operand(0, RelocInfo::NONE));
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(eq, &not_at_start);
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we did, are we still at the start of the input?
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(frame_pointer(), kInputStart));
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r0, end_of_input_address(), Operand(current_input_offset()));
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, r1);
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(eq, on_at_start);
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&not_at_start);
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckNotAtStart(Label* on_not_at_start) {
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Did we start the match at the start of the string at all?
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(frame_pointer(), kAtStart));
2169ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  __ cmp(r0, Operand(0, RelocInfo::NONE));
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(eq, on_not_at_start);
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we did, are we still at the start of the input?
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(frame_pointer(), kInputStart));
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r0, end_of_input_address(), Operand(current_input_offset()));
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, r1);
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(ne, on_not_at_start);
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckCharacterLT(uc16 limit, Label* on_less) {
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(current_character(), Operand(limit));
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(lt, on_less);
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckCharacters(Vector<const uc16> str,
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              int cp_offset,
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              Label* on_failure,
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              bool check_end_of_string) {
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (on_failure == NULL) {
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Instead of inlining a backtrack for each test, (re)use the global
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // backtrack target.
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    on_failure = &backtrack_label_;
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (check_end_of_string) {
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Is last character of required match inside string.
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckPosition(cp_offset + str.length() - 1, on_failure);
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r0, end_of_input_address(), Operand(current_input_offset()));
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (cp_offset != 0) {
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int byte_offset = cp_offset * char_size();
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, r0, Operand(byte_offset));
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0 : Address of characters to match against str.
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int stored_high_byte = 0;
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < str.length(); i++) {
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (mode_ == ASCII) {
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ ldrb(r1, MemOperand(r0, char_size(), PostIndex));
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(str[i] <= String::kMaxAsciiCharCode);
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(r1, Operand(str[i]));
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ ldrh(r1, MemOperand(r0, char_size(), PostIndex));
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      uc16 match_char = str[i];
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int match_high_byte = (match_char >> 8);
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (match_high_byte == 0) {
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ cmp(r1, Operand(str[i]));
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (match_high_byte != stored_high_byte) {
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          __ mov(r2, Operand(match_high_byte));
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          stored_high_byte = match_high_byte;
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ add(r3, r2, Operand(match_char & 0xff));
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ cmp(r1, r3);
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    BranchOrBacktrack(ne, on_failure);
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckGreedyLoop(Label* on_equal) {
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(backtrack_stackpointer(), 0));
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(current_input_offset(), r0);
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(backtrack_stackpointer(),
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         backtrack_stackpointer(), Operand(kPointerSize), LeaveCC, eq);
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(eq, on_equal);
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckNotBackReferenceIgnoreCase(
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int start_reg,
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label* on_no_match) {
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label fallthrough;
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, register_location(start_reg));  // Index of start of capture
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, register_location(start_reg + 1));  // Index of end of capture
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(r1, r1, r0, SetCC);  // Length of capture.
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If length is zero, either the capture is empty or it is not participating.
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // In either case succeed immediately.
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &fallthrough);
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that there are enough characters left in the input.
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmn(r1, Operand(current_input_offset()));
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(gt, on_no_match);
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (mode_ == ASCII) {
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label success;
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label fail;
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label loop_check;
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0 - offset of start of capture
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1 - length of capture
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, r0, Operand(end_of_input_address()));
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r2, end_of_input_address(), Operand(current_input_offset()));
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r1, r0, Operand(r1));
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0 - Address of start of capture.
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1 - Address of end of capture
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r2 - Address of current input position.
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label loop;
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&loop);
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldrb(r3, MemOperand(r0, char_size(), PostIndex));
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldrb(r4, MemOperand(r2, char_size(), PostIndex));
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r4, r3);
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &loop_check);
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Mismatch, try case-insensitive match (converting letters to lower-case).
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ orr(r3, r3, Operand(0x20));  // Convert capture character to lower-case.
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ orr(r4, r4, Operand(0x20));  // Also convert input character.
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r4, r3);
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &fail);
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r3, r3, Operand('a'));
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r3, Operand('z' - 'a'));  // Is r3 a lowercase letter?
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(hi, &fail);
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&loop_check);
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r0, r1);
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(lt, &loop);
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ jmp(&success);
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&fail);
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    BranchOrBacktrack(al, on_no_match);
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&success);
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Compute new value of character position after the matched part.
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(current_input_offset(), r2, end_of_input_address());
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(mode_ == UC16);
3508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    int argument_count = 4;
3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ PrepareCallCFunction(argument_count, r2);
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r0 - offset of start of capture
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // r1 - length of capture
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Put arguments into arguments registers.
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Parameters are
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //   r0: Address byte_offset1 - Address captured substring's start.
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //   r1: Address byte_offset2 - Address of current character position.
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //   r2: size_t byte_length - length of capture in bytes(!)
3618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    //   r3: Isolate* isolate
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Address of start of capture.
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, r0, Operand(end_of_input_address()));
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Length of capture.
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r2, Operand(r1));
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Save length in callee-save register for use on return.
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r4, Operand(r1));
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Address of current input position.
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r1, current_input_offset(), Operand(end_of_input_address()));
3718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // Isolate.
3728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ mov(r3, Operand(ExternalReference::isolate_address()));
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    {
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      AllowExternalCallThatCantCauseGC scope(masm_);
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalReference function =
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate());
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CallCFunction(function, argument_count);
3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check if function returned non-zero for success or zero for failure.
3829ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    __ cmp(r0, Operand(0, RelocInfo::NONE));
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    BranchOrBacktrack(eq, on_no_match);
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // On success, increment position by length of capture.
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(current_input_offset(), current_input_offset(), Operand(r4));
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&fallthrough);
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckNotBackReference(
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int start_reg,
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label* on_no_match) {
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label fallthrough;
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label success;
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Find length of back-referenced capture.
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, register_location(start_reg));
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, register_location(start_reg + 1));
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(r1, r1, r0, SetCC);  // Length to check.
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Succeed on empty capture (including no capture).
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(eq, &fallthrough);
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that there are enough characters left in the input.
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmn(r1, Operand(current_input_offset()));
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(gt, on_no_match);
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute pointers to match string and capture string
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r0, r0, Operand(end_of_input_address()));
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r2, end_of_input_address(), Operand(current_input_offset()));
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r1, r1, Operand(r0));
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label loop;
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&loop);
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (mode_ == ASCII) {
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldrb(r3, MemOperand(r0, char_size(), PostIndex));
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldrb(r4, MemOperand(r2, char_size(), PostIndex));
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(mode_ == UC16);
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldrh(r3, MemOperand(r0, char_size(), PostIndex));
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldrh(r4, MemOperand(r2, char_size(), PostIndex));
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r3, r4);
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(ne, on_no_match);
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, r1);
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(lt, &loop);
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Move current character position to position after match.
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(current_input_offset(), r2, end_of_input_address());
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&fallthrough);
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckNotRegistersEqual(int reg1,
436b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                                     int reg2,
437b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                                     Label* on_not_equal) {
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, register_location(reg1));
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, register_location(reg2));
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, r1);
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(ne, on_not_equal);
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
445b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid RegExpMacroAssemblerARM::CheckNotCharacter(unsigned c,
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                Label* on_not_equal) {
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(current_character(), Operand(c));
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(ne, on_not_equal);
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckCharacterAfterAnd(uint32_t c,
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     uint32_t mask,
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                     Label* on_equal) {
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(r0, current_character(), Operand(mask));
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, Operand(c));
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(eq, on_equal);
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
461b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid RegExpMacroAssemblerARM::CheckNotCharacterAfterAnd(unsigned c,
462b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                                        unsigned mask,
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                        Label* on_not_equal) {
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(r0, current_character(), Operand(mask));
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, Operand(c));
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(ne, on_not_equal);
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckNotCharacterAfterMinusAnd(
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uc16 c,
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uc16 minus,
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uc16 mask,
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label* on_not_equal) {
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(minus < String::kMaxUtf16CodeUnit);
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(r0, current_character(), Operand(minus));
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ and_(r0, r0, Operand(mask));
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, Operand(c));
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(ne, on_not_equal);
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpMacroAssemblerARM::CheckSpecialCharacterClass(uc16 type,
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                         Label* on_no_match) {
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Range checks (c in min..max) are generally implemented by an unsigned
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // (c - min) <= (max - min) check
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (type) {
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  case 's':
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Match space-characters
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (mode_ == ASCII) {
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // ASCII space characters are '\t'..'\r' and ' '.
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Label success;
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(current_character(), Operand(' '));
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ b(eq, &success);
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check range 0x09..0x0d
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ sub(r0, current_character(), Operand('\t'));
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(r0, Operand('\r' - '\t'));
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      BranchOrBacktrack(hi, on_no_match);
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ bind(&success);
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return true;
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  case 'S':
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Match non-space characters.
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (mode_ == ASCII) {
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // ASCII space characters are '\t'..'\r' and ' '.
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(current_character(), Operand(' '));
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      BranchOrBacktrack(eq, on_no_match);
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ sub(r0, current_character(), Operand('\t'));
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(r0, Operand('\r' - '\t'));
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      BranchOrBacktrack(ls, on_no_match);
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return true;
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  case 'd':
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Match ASCII digits ('0'..'9')
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r0, current_character(), Operand('0'));
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(current_character(), Operand('9' - '0'));
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    BranchOrBacktrack(hi, on_no_match);
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return true;
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  case 'D':
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Match non ASCII-digits
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r0, current_character(), Operand('0'));
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r0, Operand('9' - '0'));
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    BranchOrBacktrack(ls, on_no_match);
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return true;
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  case '.': {
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ eor(r0, current_character(), Operand(0x01));
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r0, r0, Operand(0x0b));
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ cmp(r0, Operand(0x0c - 0x0b));
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    BranchOrBacktrack(ls, on_no_match);
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (mode_ == UC16) {
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Compare original value to 0x2028 and 0x2029, using the already
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // computed (current_char ^ 0x01 - 0x0b). I.e., check for
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // 0x201d (0x2028 - 0x0b) or 0x201e.
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ sub(r0, r0, Operand(0x2028 - 0x0b));
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ cmp(r0, Operand(1));
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      BranchOrBacktrack(ls, on_no_match);
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return true;
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
544e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  case 'n': {
545e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ eor(r0, current_character(), Operand(0x01));
547e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
548e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ sub(r0, r0, Operand(0x0b));
549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ cmp(r0, Operand(0x0c - 0x0b));
550e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (mode_ == ASCII) {
551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      BranchOrBacktrack(hi, on_no_match);
552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Label done;
554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ b(ls, &done);
555e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Compare original value to 0x2028 and 0x2029, using the already
556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // computed (current_char ^ 0x01 - 0x0b). I.e., check for
557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // 0x201d (0x2028 - 0x0b) or 0x201e.
558e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ sub(r0, r0, Operand(0x2028 - 0x0b));
559e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ cmp(r0, Operand(1));
560e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      BranchOrBacktrack(hi, on_no_match);
561e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(&done);
562e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return true;
564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  case 'w': {
566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (mode_ != ASCII) {
567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Table is 128 entries, so all ASCII characters can be tested.
568e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ cmp(current_character(), Operand('z'));
569e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      BranchOrBacktrack(hi, on_no_match);
570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
571e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ExternalReference map = ExternalReference::re_word_character_map();
572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ mov(r0, Operand(map));
573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ ldrb(r0, MemOperand(r0, current_character()));
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(r0, Operand(0));
575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    BranchOrBacktrack(eq, on_no_match);
576e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return true;
577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  case 'W': {
579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    Label done;
580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (mode_ != ASCII) {
581e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // Table is 128 entries, so all ASCII characters can be tested.
582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ cmp(current_character(), Operand('z'));
583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ b(hi, &done);
584e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ExternalReference map = ExternalReference::re_word_character_map();
586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ mov(r0, Operand(map));
587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    __ ldrb(r0, MemOperand(r0, current_character()));
5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cmp(r0, Operand(0));
589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    BranchOrBacktrack(ne, on_no_match);
590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (mode_ != ASCII) {
591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      __ bind(&done);
592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return true;
594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  case '*':
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Match any character.
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return true;
598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // No custom implementation (yet): s(UC16), S(UC16).
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  default:
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::Fail() {
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(FAILURE));
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&exit_label_);
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
611053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve BlockHandle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Finalize code - write the entry point code now we know how many
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // registers we need.
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Entry code:
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&entry_label_);
6173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Tell the system that we have a stack frame.  Because the type is MANUAL, no
6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // is generated.
6203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameScope scope(masm_, StackFrame::MANUAL);
6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Actually emit code to start a new stack frame.
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push arguments
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Save callee-save registers.
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Start new stack frame.
626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Store link register in existing stack-cell.
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Order here should correspond to order of offset constants in header file.
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegList registers_to_retain = r4.bit() | r5.bit() | r6.bit() |
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      r7.bit() | r8.bit() | r9.bit() | r10.bit() | fp.bit();
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegList argument_registers = r0.bit() | r1.bit() | r2.bit() | r3.bit();
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ stm(db_w, sp, argument_registers | registers_to_retain | lr.bit());
632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Set frame pointer in space for it if this is not a direct call
633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // from generated code.
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(frame_pointer(), sp, Operand(4 * kPointerSize));
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(r0);  // Make room for "position - 1" constant (value is irrelevant).
636d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ push(r0);  // Make room for "at start" constant (value is irrelevant).
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if we have space on the stack for registers.
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label stack_limit_hit;
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label stack_ok;
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ExternalReference stack_limit =
64244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::address_of_stack_limit(masm_->isolate());
643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(r0, Operand(stack_limit));
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(r0));
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(r0, sp, r0, SetCC);
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Handle it if the stack pointer is already below the stack limit.
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ls, &stack_limit_hit);
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if there is room for the variable number of registers above
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the stack limit.
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, Operand(num_registers_ * kPointerSize));
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(hs, &stack_ok);
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exit with OutOfMemory exception. There is not enough space on the stack
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // for our working registers.
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(EXCEPTION));
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&exit_label_);
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&stack_limit_hit);
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallCheckStackGuardState(r0);
6599ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  __ cmp(r0, Operand(0, RelocInfo::NONE));
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If returned value is non-zero, we exit with the returned value as result.
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &exit_label_);
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&stack_ok);
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate space on stack for registers.
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(sp, sp, Operand(num_registers_ * kPointerSize));
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load string end.
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load input start.
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(frame_pointer(), kInputStart));
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Find negative length (offset of start relative to end).
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(current_input_offset(), r0, end_of_input_address());
6736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set r0 to address of char before start of the input string
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // (effectively string position -1).
6756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ ldr(r1, MemOperand(frame_pointer(), kStartIndex));
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(r0, current_input_offset(), Operand(char_size()));
6776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ sub(r0, r0, Operand(r1, LSL, (mode_ == UC16) ? 1 : 0));
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Store this value in a local variable, for use when clearing
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // position registers.
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r0, MemOperand(frame_pointer(), kInputStartMinusOne));
681d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
682d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Determine whether the start index is zero, that is at the start of the
683d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // string, and store that value in a local variable.
6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(r1, Operand(0));
685d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ mov(r1, Operand(1), LeaveCC, eq);
6869ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  __ mov(r1, Operand(0, RelocInfo::NONE), LeaveCC, ne);
687d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ str(r1, MemOperand(frame_pointer(), kAtStart));
688d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_saved_registers_ > 0) {  // Always is, if generated from a regexp.
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Fill saved registers with initial value = start offset - 1
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Address of register 0.
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r1, frame_pointer(), Operand(kRegisterZero));
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r2, Operand(num_saved_registers_));
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label init_loop;
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&init_loop);
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r0, MemOperand(r1, kPointerSize, NegPostIndex));
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ sub(r2, r2, Operand(1), SetCC);
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &init_loop);
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initialize backtrack stack pointer.
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd));
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initialize code pointer register
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(code_pointer(), Operand(masm_->CodeObject()));
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Load previous char as initial value of current character register.
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label at_start;
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(frame_pointer(), kAtStart));
7099ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  __ cmp(r0, Operand(0, RelocInfo::NONE));
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &at_start);
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadCurrentCharacterUnchecked(-1, 1);  // Load previous char.
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&start_label_);
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&at_start);
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(current_character(), Operand('\n'));
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&start_label_);
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exit code:
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (success_label_.is_linked()) {
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Save captures when successful.
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&success_label_);
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (num_saved_registers_ > 0) {
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // copy captures to output
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ ldr(r1, MemOperand(frame_pointer(), kInputStart));
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ ldr(r0, MemOperand(frame_pointer(), kRegisterOutput));
7266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ ldr(r2, MemOperand(frame_pointer(), kStartIndex));
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ sub(r1, end_of_input_address(), r1);
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // r1 is length of input in bytes.
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (mode_ == UC16) {
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ mov(r1, Operand(r1, LSR, 1));
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // r1 is length of input in characters.
7336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      __ add(r1, r1, Operand(r2));
7346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // r1 is length of string in characters.
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT_EQ(0, num_saved_registers_ % 2);
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Always an even number of capture registers. This allows us to
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // unroll the loop once to add an operation between a load of a register
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // and the following use of that register.
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (int i = 0; i < num_saved_registers_; i += 2) {
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ ldr(r2, register_location(i));
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ ldr(r3, register_location(i + 1));
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (mode_ == UC16) {
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          __ add(r2, r1, Operand(r2, ASR, 1));
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          __ add(r3, r1, Operand(r3, ASR, 1));
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          __ add(r2, r1, Operand(r2));
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          __ add(r3, r1, Operand(r3));
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ str(r2, MemOperand(r0, kPointerSize, PostIndex));
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        __ str(r3, MemOperand(r0, kPointerSize, PostIndex));
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r0, Operand(SUCCESS));
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exit and return r0
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&exit_label_);
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Skip sp past regexp registers and local variables..
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(sp, frame_pointer());
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Restore registers r4..r11 and return (restoring lr to pc).
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldm(ia_w, sp, registers_to_retain | pc.bit());
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Backtrack code (branch target for conditional backtracks).
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (backtrack_label_.is_linked()) {
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&backtrack_label_);
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Backtrack();
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label exit_with_exception;
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Preempt-code
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (check_preempt_label_.is_linked()) {
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SafeCallTarget(&check_preempt_label_);
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CallCheckStackGuardState(r0);
7769ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    __ cmp(r0, Operand(0, RelocInfo::NONE));
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If returning non-zero, we should end execution with the given
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // result as return value.
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(ne, &exit_label_);
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // String might have moved: Reload end of string from frame.
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SafeReturn();
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Backtrack stack overflow code.
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (stack_overflow_label_.is_linked()) {
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SafeCallTarget(&stack_overflow_label_);
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Reached if the backtrack-stack limit has been hit.
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Label grow_failed;
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
792e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Call GrowStack(backtrack_stackpointer(), &stack_base)
7938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    static const int num_arguments = 3;
7946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ PrepareCallCFunction(num_arguments, r0);
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r0, backtrack_stackpointer());
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r1, frame_pointer(), Operand(kStackHighEnd));
7978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    __ mov(r2, Operand(ExternalReference::isolate_address()));
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ExternalReference grow_stack =
79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ExternalReference::re_grow_stack(masm_->isolate());
8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    __ CallCFunction(grow_stack, num_arguments);
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If return NULL, we have failed to grow the stack, and
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // must exit with a stack-overflow exception.
8039ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    __ cmp(r0, Operand(0, RelocInfo::NONE));
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(eq, &exit_with_exception);
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Otherwise use return value as new stack pointer.
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(backtrack_stackpointer(), r0);
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Restore saved registers and continue.
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SafeReturn();
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (exit_with_exception.is_linked()) {
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If any of the code above needed to exit with an exception.
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ bind(&exit_with_exception);
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Exit with Result EXCEPTION(-1) to signal thrown exception.
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r0, Operand(EXCEPTION));
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ jmp(&exit_label_);
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CodeDesc code_desc;
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  masm_->GetCode(&code_desc);
82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> code = FACTORY->NewCode(code_desc,
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Code::ComputeFlags(Code::REGEXP),
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       masm_->CodeObject());
82444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  PROFILE(Isolate::Current(), RegExpCodeCreateEvent(*code, *source));
825053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  return Handle<HeapObject>::cast(code);
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::GoTo(Label* to) {
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(al, to);
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::IfRegisterGE(int reg,
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           int comparand,
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* if_ge) {
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, register_location(reg));
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, Operand(comparand));
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(ge, if_ge);
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::IfRegisterLT(int reg,
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           int comparand,
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           Label* if_lt) {
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, register_location(reg));
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, Operand(comparand));
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(lt, if_lt);
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::IfRegisterEqPos(int reg,
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              Label* if_eq) {
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, register_location(reg));
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(r0, Operand(current_input_offset()));
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(eq, if_eq);
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssembler::IrregexpImplementation
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RegExpMacroAssemblerARM::Implementation() {
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return kARMImplementation;
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::LoadCurrentCharacter(int cp_offset,
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   Label* on_end_of_input,
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   bool check_bounds,
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                   int characters) {
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(cp_offset >= -1);      // ^ and \b can look behind one character.
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(cp_offset < (1<<30));  // Be sane! (And ensure negation works)
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (check_bounds) {
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CheckPosition(cp_offset + characters - 1, on_end_of_input);
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LoadCurrentCharacterUnchecked(cp_offset, characters);
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::PopCurrentPosition() {
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Pop(current_input_offset());
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::PopRegister(int register_index) {
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Pop(r0);
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r0, register_location(register_index));
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool is_valid_memory_offset(int value) {
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (value < 0) value = -value;
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return value < (1<<12);
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::PushBacktrack(Label* label) {
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (label->is_bound()) {
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int target = label->pos();
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ mov(r0, Operand(target + Code::kHeaderSize - kHeapObjectTag));
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int constant_offset = GetBacktrackConstantPoolEntry();
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    masm_->label_at_put(label, constant_offset);
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Reading pc-relative is based on the address 8 bytes ahead of
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the current opcode.
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    unsigned int offset_of_pc_register_read =
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      masm_->pc_offset() + Assembler::kPcLoadDelta;
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int pc_offset_of_constant =
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      constant_offset - offset_of_pc_register_read;
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(pc_offset_of_constant < 0);
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (is_valid_memory_offset(pc_offset_of_constant)) {
9113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Assembler::BlockConstPoolScope block_const_pool(masm_);
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ ldr(r0, MemOperand(pc, pc_offset_of_constant));
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Not a 12-bit offset, so it needs to be loaded from the constant
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // pool.
9163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Assembler::BlockConstPoolScope block_const_pool(masm_);
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ mov(r0, Operand(pc_offset_of_constant + Assembler::kInstrSize));
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      __ ldr(r0, MemOperand(pc, r0));
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Push(r0);
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CheckStackLimit();
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::PushCurrentPosition() {
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Push(current_input_offset());
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::PushRegister(int register_index,
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           StackCheckFlag check_stack_limit) {
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, register_location(register_index));
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Push(r0);
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (check_stack_limit) CheckStackLimit();
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::ReadCurrentPositionFromRegister(int reg) {
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(current_input_offset(), register_location(reg));
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::ReadStackPointerFromRegister(int reg) {
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(backtrack_stackpointer(), register_location(reg));
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(frame_pointer(), kStackHighEnd));
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(backtrack_stackpointer(), backtrack_stackpointer(), Operand(r0));
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
951f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochvoid RegExpMacroAssemblerARM::SetCurrentPositionFromEnd(int by) {
952f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Label after_position;
953f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ cmp(current_input_offset(), Operand(-by * char_size()));
954f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ b(ge, &after_position);
955f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ mov(current_input_offset(), Operand(-by * char_size()));
956f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // On RegExp code entry (where this operation is used), the character before
957f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // the current position is expected to be already loaded.
958f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // We have advanced the position, so it's safe to read backwards.
959f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  LoadCurrentCharacterUnchecked(-1, 1);
960f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ bind(&after_position);
961f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
962f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
963f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::SetRegister(int register_index, int to) {
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(register_index >= num_saved_registers_);  // Reserved for positions!
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(to));
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r0, register_location(register_index));
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::Succeed() {
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&success_label_);
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::WriteCurrentPositionToRegister(int reg,
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                             int cp_offset) {
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (cp_offset == 0) {
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(current_input_offset(), register_location(reg));
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, current_input_offset(), Operand(cp_offset * char_size()));
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r0, register_location(reg));
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::ClearRegisters(int reg_from, int reg_to) {
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(reg_from <= reg_to);
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(frame_pointer(), kInputStartMinusOne));
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int reg = reg_from; reg <= reg_to; reg++) {
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ str(r0, register_location(reg));
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::WriteStackPointerToRegister(int reg) {
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r1, MemOperand(frame_pointer(), kStackHighEnd));
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(r0, backtrack_stackpointer(), r1);
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r0, register_location(reg));
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Private methods:
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CallCheckStackGuardState(Register scratch) {
10066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int num_arguments = 3;
10076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ PrepareCallCFunction(num_arguments, scratch);
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // RegExp code frame pointer.
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, frame_pointer());
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Code* of self.
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r1, Operand(masm_->CodeObject()));
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // r0 becomes return address pointer.
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReference stack_guard_check =
101444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::re_check_stack_guard_state(masm_->isolate());
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CallCFunctionUsingStub(stack_guard_check, num_arguments);
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper function for reading a value out of a stack frame.
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate <typename T>
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic T& frame_entry(Address re_frame, int frame_offset) {
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset));
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerARM::CheckStackGuardState(Address* return_address,
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  Code* re_code,
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                  Address re_frame) {
102944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
103044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(isolate == Isolate::Current());
103144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (isolate->stack_guard()->IsStackOverflow()) {
103244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    isolate->StackOverflow();
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return EXCEPTION;
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If not real stack overflow the stack guard was used to interrupt
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // execution for another purpose.
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // If this is a direct call from JavaScript retry the RegExp forcing the call
10406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // through the runtime system. Currently the direct call cannot handle a GC.
10416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (frame_entry<int>(re_frame, kDirectCall) == 1) {
10426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return RETRY;
10436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Prepare for possible GC.
104669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  HandleScope handles(isolate);
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code_handle(re_code);
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
105069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Current string.
105269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  bool is_ascii = subject->IsAsciiRepresentationUnderneath();
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(re_code->instruction_start() <= *return_address);
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(*return_address <=
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      re_code->instruction_start() + re_code->instruction_size());
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (*code_handle != re_code) {  // Return address no longer valid
106169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int delta = code_handle->address() - re_code->address();
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Overwrite the return address on the stack.
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *return_address += delta;
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (result->IsException()) {
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return EXCEPTION;
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
107069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> subject_tmp = subject;
107169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int slice_offset = 0;
107269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
107369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Extract the underlying string and the slice offset.
107469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (StringShape(*subject_tmp).IsCons()) {
107569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
107669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  } else if (StringShape(*subject_tmp).IsSliced()) {
107769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    SlicedString* slice = SlicedString::cast(*subject_tmp);
107869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    subject_tmp = Handle<String>(slice->parent());
107969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    slice_offset = slice->offset();
108069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
108169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // String might have changed.
108369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (subject_tmp->IsAsciiRepresentation() != is_ascii) {
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If we changed between an ASCII and an UC16 string, the specialized
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // code cannot be used, and we need to restart regexp matching from
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // scratch (including, potentially, compiling a new version of the code).
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return RETRY;
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Otherwise, the content of the string might have moved. It must still
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // be a sequential or external string with the same content.
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update the start and end pointers in the stack frame to the current
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // location (whether it has actually moved or not).
109469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ASSERT(StringShape(*subject_tmp).IsSequential() ||
109569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      StringShape(*subject_tmp).IsExternal());
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The original start address of the characters to match.
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Find the current start address of the same character at the current string
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // position.
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int start_index = frame_entry<int>(re_frame, kStartIndex);
110369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const byte* new_address = StringCharacterPosition(*subject_tmp,
110469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                                    start_index + slice_offset);
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (start_address != new_address) {
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If there is a difference, update the object pointer and start and end
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // addresses in the RegExp stack frame to match the new value.
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
111069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int byte_length = static_cast<int>(end_address - start_address);
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    frame_entry<const String*>(re_frame, kInputString) = *subject;
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    frame_entry<const byte*>(re_frame, kInputStart) = new_address;
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Subject string might have been a ConsString that underwent
11163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // short-circuiting during GC. That will not change start_address but
11173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // will change pointer inside the subject handle.
11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    frame_entry<const String*>(re_frame, kInputString) = *subject;
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 0;
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand RegExpMacroAssemblerARM::register_location(int register_index) {
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(register_index < (1<<30));
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_registers_ <= register_index) {
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    num_registers_ = register_index + 1;
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return MemOperand(frame_pointer(),
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    kRegisterZero - register_index * kPointerSize);
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckPosition(int cp_offset,
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            Label* on_outside_input) {
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(current_input_offset(), Operand(-cp_offset * char_size()));
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BranchOrBacktrack(ge, on_outside_input);
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::BranchOrBacktrack(Condition condition,
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                Label* to) {
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (condition == al) {  // Unconditional.
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (to == NULL) {
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Backtrack();
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ jmp(to);
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (to == NULL) {
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ b(condition, &backtrack_label_);
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(condition, to);
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::SafeCall(Label* to, Condition cond) {
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bl(to, cond);
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::SafeReturn() {
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ pop(lr);
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(pc, lr, Operand(masm_->CodeObject()));
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::SafeCallTarget(Label* name) {
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(name);
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(lr, lr, Operand(masm_->CodeObject()));
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ push(lr);
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::Push(Register source) {
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!source.is(backtrack_stackpointer()));
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(source,
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MemOperand(backtrack_stackpointer(), kPointerSize, NegPreIndex));
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::Pop(Register target) {
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!target.is(backtrack_stackpointer()));
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(target,
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         MemOperand(backtrack_stackpointer(), kPointerSize, PostIndex));
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckPreemption() {
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for preemption.
1194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ExternalReference stack_limit =
119544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::address_of_stack_limit(masm_->isolate());
1196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(r0, Operand(stack_limit));
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(r0));
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ cmp(sp, r0);
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SafeCall(&check_preempt_label_, ls);
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckStackLimit() {
1204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ExternalReference stack_limit =
120544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference::address_of_regexp_stack_limit(masm_->isolate());
1206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ mov(r0, Operand(stack_limit));
1207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ ldr(r0, MemOperand(r0));
1208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  __ cmp(backtrack_stackpointer(), Operand(r0));
1209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SafeCall(&stack_overflow_label_, ls);
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::EmitBacktrackConstantPool() {
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CheckConstPool(false, false);
12153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Assembler::BlockConstPoolScope block_const_pool(masm_);
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  backtrack_constant_pool_offset_ = masm_->pc_offset();
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < kBacktrackConstantPoolSize; i++) {
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ emit(0);
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  backtrack_constant_pool_capacity_ = kBacktrackConstantPoolSize;
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerARM::GetBacktrackConstantPoolEntry() {
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (backtrack_constant_pool_capacity_ > 0) {
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int offset = backtrack_constant_pool_offset_;
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    backtrack_constant_pool_offset_ += kPointerSize;
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    backtrack_constant_pool_capacity_--;
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (masm_->pc_offset() - offset < 2 * KB) {
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return offset;
1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label new_pool_skip;
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ jmp(&new_pool_skip);
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EmitBacktrackConstantPool();
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&new_pool_skip);
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int offset = backtrack_constant_pool_offset_;
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  backtrack_constant_pool_offset_ += kPointerSize;
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  backtrack_constant_pool_capacity_--;
1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return offset;
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CallCFunctionUsingStub(
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ExternalReference function,
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int num_arguments) {
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Must pass all arguments in registers. The stub pushes on the stack.
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(num_arguments <= 4);
12506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  __ mov(code_pointer(), Operand(function));
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpCEntryStub stub;
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ CallStub(&stub);
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (OS::ActivationFrameAlignment() != 0) {
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ ldr(sp, MemOperand(sp, 0));
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(code_pointer(), Operand(masm_->CodeObject()));
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::LoadCurrentCharacterUnchecked(int cp_offset,
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                            int characters) {
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register offset = current_input_offset();
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (cp_offset != 0) {
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    __ add(r0, current_input_offset(), Operand(cp_offset * char_size()));
1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    offset = r0;
1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
126725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU
126825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // and the operating system running on the target allow it.
126925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // If unaligned load/stores are not supported then this function must only
127025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // be used to load a single character at a time.
127125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen#if !V8_TARGET_CAN_READ_UNALIGNED
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(characters == 1);
127325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen#endif
127425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (mode_ == ASCII) {
127625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    if (characters == 4) {
127725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      __ ldr(current_character(), MemOperand(end_of_input_address(), offset));
127825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    } else if (characters == 2) {
127925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      __ ldrh(current_character(), MemOperand(end_of_input_address(), offset));
128025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    } else {
128125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      ASSERT(characters == 1);
128225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      __ ldrb(current_character(), MemOperand(end_of_input_address(), offset));
128325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    }
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(mode_ == UC16);
128625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    if (characters == 2) {
128725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      __ ldr(current_character(), MemOperand(end_of_input_address(), offset));
128825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    } else {
128925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      ASSERT(characters == 1);
129025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      __ ldrh(current_character(), MemOperand(end_of_input_address(), offset));
129125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    }
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpCEntryStub::Generate(MacroAssembler* masm_) {
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int stack_alignment = OS::ActivationFrameAlignment();
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (stack_alignment < kPointerSize) stack_alignment = kPointerSize;
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stack is already aligned for call, so decrement by alignment
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to make room for storing the link register.
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(lr, MemOperand(sp, stack_alignment, NegPreIndex));
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, sp);
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ Call(r5);
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(pc, MemOperand(sp, stack_alignment, PostIndex));
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif  // V8_INTERPRETED_REGEXP
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}}  // namespace v8::internal
1312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
1314