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