Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(277)

Side by Side Diff: src/sh4/regexp-macro-assembler-sh4.cc

Issue 11275184: First draft of the sh4 port Base URL: http://github.com/v8/v8.git@master
Patch Set: Use GYP and fixe some typos Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/sh4/regexp-macro-assembler-sh4.h ('k') | src/sh4/simulator-sh4.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2011-2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #if defined(V8_TARGET_ARCH_ARM) 30 #if defined(V8_TARGET_ARCH_SH4)
31 31
32 #include "unicode.h" 32 #include "unicode.h"
33 #include "log.h" 33 #include "log.h"
34 #include "code-stubs.h" 34 #include "code-stubs.h"
35 #include "regexp-stack.h" 35 #include "regexp-stack.h"
36 #include "macro-assembler.h" 36 #include "macro-assembler.h"
37 #include "regexp-macro-assembler.h" 37 #include "regexp-macro-assembler.h"
38 #include "arm/regexp-macro-assembler-arm.h" 38 #include "sh4/regexp-macro-assembler-sh4.h"
39 39
40 namespace v8 { 40 namespace v8 {
41 namespace internal { 41 namespace internal {
42 42
43 #include "map-sh4.h" // For ARM -> SH4 register mapping
44
43 #ifndef V8_INTERPRETED_REGEXP 45 #ifndef V8_INTERPRETED_REGEXP
44 /* 46 /*
45 * This assembler uses the following register assignment convention 47 * This assembler uses the following register assignment convention
46 * - r4 : Temporarily stores the index of capture start after a matching pass 48 * - r4 : Temporarily stores the index of capture start after a matching pass
47 * for a global regexp. 49 * for a global regexp.
48 * - r5 : Pointer to current code object (Code*) including heap object tag. 50 * - r5 : Pointer to current code object (Code*) including heap object tag.
49 * - r6 : Current position in input, as negative offset from end of string. 51 * - r6 : Current position in input, as negative offset from end of string.
50 * Please notice that this is the byte offset, not the character offset! 52 * Please notice that this is the byte offset, not the character offset!
51 * - r7 : Currently loaded character. Must be loaded using 53 * - r7 : Currently loaded character. Must be loaded using
52 * LoadCurrentCharacter before using any of the dispatch methods. 54 * LoadCurrentCharacter before using any of the dispatch methods.
53 * - r8 : Points to tip of backtrack stack 55 * - r8 : points to tip of backtrack stack
54 * - r9 : Unused, might be used by C code and expected unchanged. 56 * - r9 : End of input (points to byte after last character in input).
55 * - r10 : End of input (points to byte after last character in input). 57 * - fp : Frame pointer. Used to access arguments, local variables and
56 * - r11 : Frame pointer. Used to access arguments, local variables and
57 * RegExp registers. 58 * RegExp registers.
58 * - r12 : IP register, used by assembler. Very volatile. 59 * - r10 : IP register, used by assembler. Very volatile.
59 * - r13/sp : Points to tip of C stack. 60 * - sp : points to tip of C stack.
60 * 61 *
61 * The remaining registers are free for computations. 62 * The remaining registers are free for computations.
62 * Each call to a public method should retain this convention. 63 * Each call to a public method should retain this convention.
63 * 64 *
64 * The stack will have the following structure: 65 * The stack will have the following structure:
65 * - fp[56] Isolate* isolate (address of the current isolate) 66 * - fp[62] Isolate* isolate (Address of the current isolate)
66 * - fp[52] direct_call (if 1, direct call from JavaScript code, 67 * - fp[58] direct_call (if 1, direct call from JavaScript code,
67 * if 0, call through the runtime system). 68 * if 0, call through the runtime system).
68 * - fp[48] stack_area_base (high end of the memory area to use as 69 * - fp[54] stack_area_base (High end of the memory area to use as
69 * backtracking stack). 70 * backtracking stack).
70 * - fp[44] capture array size (may fit multiple sets of matches) 71 * - fp[50] capture array size (may fit multiple sets of matches)
71 * - fp[40] int* capture_array (int[num_saved_registers_], for output). 72 * - fp[46] int* capture_array (int[num_saved_registers_], for output).
72 * - fp[36] secondary link/return address used by native call. 73 * - fp[32] secondary link/return address used by native call.
73 * --- sp when called --- 74 * --- sp when called ---
74 * - fp[32] return address (lr). 75 * - fp[28] return address (pr).
75 * - fp[28] old frame pointer (r11). 76 * - fp[24] old frame pointer (r14).
76 * - fp[0..24] backup of registers r4..r10. 77 * - fp[0..20] backup of registers r8..r13.
77 * --- frame pointer ---- 78 * --- frame pointer ----
78 * - fp[-4] end of input (address of end of string). 79 * - fp[-4] end of input (address of end of string).
79 * - fp[-8] start of input (address of first character in string). 80 * - fp[-8] start of input (address of first character in string).
80 * - fp[-12] start index (character index of start). 81 * - fp[-12] start index (character index of start).
81 * - fp[-16] void* input_string (location of a handle containing the string). 82 * - fp[-16] void* input_string (location of a handle containing the string).
82 * - fp[-20] success counter (only for global regexps to count matches). 83 * - fp[-20] success counter (only for global regexps to count matches).
83 * - fp[-24] Offset of location before start of input (effectively character 84 * - fp[-24] Offset of location before start of input (effectively character
84 * position -1). Used to initialize capture registers to a 85 * position -1). Used to initialize capture registers to a
85 * non-position. 86 * non-position.
86 * - fp[-28] At start (if 1, we are starting at the start of the 87 * - fp[-28] At start (if 1, we are starting at the start of the
(...skipping 14 matching lines...) Expand all
101 * int (*match)(String* input_string, 102 * int (*match)(String* input_string,
102 * int start_index, 103 * int start_index,
103 * Address start, 104 * Address start,
104 * Address end, 105 * Address end,
105 * Address secondary_return_address, // Only used by native call. 106 * Address secondary_return_address, // Only used by native call.
106 * int* capture_output_array, 107 * int* capture_output_array,
107 * byte* stack_area_base, 108 * byte* stack_area_base,
108 * bool direct_call = false) 109 * bool direct_call = false)
109 * The call is performed by NativeRegExpMacroAssembler::Execute() 110 * The call is performed by NativeRegExpMacroAssembler::Execute()
110 * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro 111 * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro
111 * in arm/simulator-arm.h. 112 * in sh4/simulator-sh4.h.
112 * When calling as a non-direct call (i.e., from C++ code), the return address 113 * When calling as a non-direct call (i.e., from C++ code), the return address
113 * area is overwritten with the LR register by the RegExp code. When doing a 114 * area is overwritten with the LR register by the RegExp code. When doing a
114 * direct call from generated code, the return address is placed there by 115 * direct call from generated code, the return address is placed there by
115 * the calling code, as in a normal exit frame. 116 * the calling code, as in a normal exit frame.
116 */ 117 */
117 118
118 #define __ ACCESS_MASM(masm_) 119 #define __ ACCESS_MASM(masm_)
119 120
120 RegExpMacroAssemblerARM::RegExpMacroAssemblerARM( 121 RegExpMacroAssemblerSH4::RegExpMacroAssemblerSH4(
121 Mode mode, 122 Mode mode,
122 int registers_to_save, 123 int registers_to_save,
123 Zone* zone) 124 Zone* zone)
124 : NativeRegExpMacroAssembler(zone), 125 : NativeRegExpMacroAssembler(zone),
125 masm_(new MacroAssembler(Isolate::Current(), NULL, kRegExpCodeSize)), 126 masm_(new MacroAssembler(Isolate::Current(), NULL, kRegExpCodeSize)),
126 mode_(mode), 127 mode_(mode),
127 num_registers_(registers_to_save), 128 num_registers_(registers_to_save),
128 num_saved_registers_(registers_to_save), 129 num_saved_registers_(registers_to_save),
129 entry_label_(), 130 entry_label_(),
130 start_label_(), 131 start_label_(),
131 success_label_(), 132 success_label_(),
132 backtrack_label_(), 133 backtrack_label_(),
133 exit_label_() { 134 exit_label_() {
134 ASSERT_EQ(0, registers_to_save % 2); 135 ASSERT_EQ(0, registers_to_save % 2);
135 __ jmp(&entry_label_); // We'll write the entry code later. 136 __ jmp(&entry_label_); // We'll write the entry code later.
136 EmitBacktrackConstantPool();
137 __ bind(&start_label_); // And then continue from here. 137 __ bind(&start_label_); // And then continue from here.
138 } 138 }
139 139
140 140
141 RegExpMacroAssemblerARM::~RegExpMacroAssemblerARM() { 141 RegExpMacroAssemblerSH4::~RegExpMacroAssemblerSH4() {
142 delete masm_; 142 delete masm_;
143 // Unuse labels in case we throw away the assembler without calling GetCode. 143 // Unuse labels in case we throw away the assembler without calling GetCode.
144 entry_label_.Unuse(); 144 entry_label_.Unuse();
145 start_label_.Unuse(); 145 start_label_.Unuse();
146 success_label_.Unuse(); 146 success_label_.Unuse();
147 backtrack_label_.Unuse(); 147 backtrack_label_.Unuse();
148 exit_label_.Unuse(); 148 exit_label_.Unuse();
149 check_preempt_label_.Unuse(); 149 check_preempt_label_.Unuse();
150 stack_overflow_label_.Unuse(); 150 stack_overflow_label_.Unuse();
151 } 151 }
152 152
153 153
154 int RegExpMacroAssemblerARM::stack_limit_slack() { 154 int RegExpMacroAssemblerSH4::stack_limit_slack() {
155 return RegExpStack::kStackLimitSlack; 155 return RegExpStack::kStackLimitSlack;
156 } 156 }
157 157
158 158
159 void RegExpMacroAssemblerARM::AdvanceCurrentPosition(int by) { 159 void RegExpMacroAssemblerSH4::AdvanceCurrentPosition(int by) {
160 if (by != 0) { 160 if (by != 0) {
161 __ add(current_input_offset(), 161 __ add(current_input_offset(),
162 current_input_offset(), Operand(by * char_size())); 162 current_input_offset(), Operand(by * char_size()));
163 } 163 }
164 } 164 }
165 165
166 166
167 void RegExpMacroAssemblerARM::AdvanceRegister(int reg, int by) { 167 void RegExpMacroAssemblerSH4::AdvanceRegister(int reg, int by) {
168 ASSERT(reg >= 0); 168 ASSERT(reg >= 0);
169 ASSERT(reg < num_registers_); 169 ASSERT(reg < num_registers_);
170 if (by != 0) { 170 if (by != 0) {
171 __ ldr(r0, register_location(reg)); 171 __ ldr(r0, register_location(reg));
172 __ add(r0, r0, Operand(by)); 172 __ add(r0, r0, Operand(by));
173 __ str(r0, register_location(reg)); 173 __ str(r0, register_location(reg));
174 } 174 }
175 } 175 }
176 176
177 177
178 void RegExpMacroAssemblerARM::Backtrack() { 178 void RegExpMacroAssemblerSH4::Backtrack() {
179 CheckPreemption(); 179 CheckPreemption();
180 // Pop Code* offset from backtrack stack, add Code* and jump to location. 180 // Pop Code* offset from backtrack stack, add Code* and jump to location.
181 Pop(r0); 181 Pop(r0);
182 __ add(pc, r0, Operand(code_pointer())); 182 __ add(r0, r0, code_pointer());
183 __ jmp(r0);
183 } 184 }
184 185
185 186
186 void RegExpMacroAssemblerARM::Bind(Label* label) { 187 void RegExpMacroAssemblerSH4::Bind(Label* label) {
187 __ bind(label); 188 __ bind(label);
188 } 189 }
189 190
190 191
191 void RegExpMacroAssemblerARM::CheckCharacter(uint32_t c, Label* on_equal) { 192 void RegExpMacroAssemblerSH4::CheckCharacter(uint32_t c, Label* on_equal) {
192 __ cmp(current_character(), Operand(c)); 193 __ cmp(current_character(), Operand(c));
193 BranchOrBacktrack(eq, on_equal); 194 BranchOrBacktrack(eq, on_equal);
194 } 195 }
195 196
196 197
197 void RegExpMacroAssemblerARM::CheckCharacterGT(uc16 limit, Label* on_greater) { 198 void RegExpMacroAssemblerSH4::CheckCharacterGT(uc16 limit, Label* on_greater) {
198 __ cmp(current_character(), Operand(limit)); 199 __ cmpgt(current_character(), Operand(limit));
199 BranchOrBacktrack(gt, on_greater); 200 BranchOrBacktrack(eq, on_greater);
200 } 201 }
201 202
202 203
203 void RegExpMacroAssemblerARM::CheckAtStart(Label* on_at_start) { 204 void RegExpMacroAssemblerSH4::CheckAtStart(Label* on_at_start) {
204 Label not_at_start; 205 Label not_at_start;
205 // Did we start the match at the start of the string at all? 206 // Did we start the match at the start of the string at all?
206 __ ldr(r0, MemOperand(frame_pointer(), kStartIndex)); 207 __ ldr(r0, MemOperand(frame_pointer(), kStartIndex));
207 __ cmp(r0, Operand(0, RelocInfo::NONE)); 208 __ cmp(r0, Operand(0, RelocInfo::NONE));
208 BranchOrBacktrack(ne, &not_at_start); 209 BranchOrBacktrack(ne, &not_at_start);
209 210
210 // If we did, are we still at the start of the input? 211 // If we did, are we still at the start of the input?
211 __ ldr(r1, MemOperand(frame_pointer(), kInputStart)); 212 __ ldr(r1, MemOperand(frame_pointer(), kInputStart));
212 __ add(r0, end_of_input_address(), Operand(current_input_offset())); 213 __ add(r0, end_of_input_address(), current_input_offset());
213 __ cmp(r0, r1); 214 __ cmp(r0, r1);
214 BranchOrBacktrack(eq, on_at_start); 215 BranchOrBacktrack(eq, on_at_start);
215 __ bind(&not_at_start); 216 __ bind(&not_at_start);
216 } 217 }
217 218
218 219
219 void RegExpMacroAssemblerARM::CheckNotAtStart(Label* on_not_at_start) { 220 void RegExpMacroAssemblerSH4::CheckNotAtStart(Label* on_not_at_start) {
220 // Did we start the match at the start of the string at all? 221 // Did we start the match at the start of the string at all?
221 __ ldr(r0, MemOperand(frame_pointer(), kStartIndex)); 222 __ ldr(r0, MemOperand(frame_pointer(), kStartIndex));
222 __ cmp(r0, Operand(0, RelocInfo::NONE)); 223 __ cmp(r0, Operand(0, RelocInfo::NONE));
223 BranchOrBacktrack(ne, on_not_at_start); 224 BranchOrBacktrack(ne, on_not_at_start);
224 // If we did, are we still at the start of the input? 225 // If we did, are we still at the start of the input?
225 __ ldr(r1, MemOperand(frame_pointer(), kInputStart)); 226 __ ldr(r1, MemOperand(frame_pointer(), kInputStart));
226 __ add(r0, end_of_input_address(), Operand(current_input_offset())); 227 __ add(r0, end_of_input_address(), current_input_offset());
227 __ cmp(r0, r1); 228 __ cmp(r0, r1);
228 BranchOrBacktrack(ne, on_not_at_start); 229 BranchOrBacktrack(ne, on_not_at_start);
229 } 230 }
230 231
231 232
232 void RegExpMacroAssemblerARM::CheckCharacterLT(uc16 limit, Label* on_less) { 233 void RegExpMacroAssemblerSH4::CheckCharacterLT(uc16 limit, Label* on_less) {
233 __ cmp(current_character(), Operand(limit)); 234 __ cmpge(current_character(), Operand(limit));
234 BranchOrBacktrack(lt, on_less); 235 BranchOrBacktrack(ne, on_less);
235 } 236 }
236 237
237 238
238 void RegExpMacroAssemblerARM::CheckCharacters(Vector<const uc16> str, 239 void RegExpMacroAssemblerSH4::CheckCharacters(Vector<const uc16> str,
239 int cp_offset, 240 int cp_offset,
240 Label* on_failure, 241 Label* on_failure,
241 bool check_end_of_string) { 242 bool check_end_of_string) {
242 if (on_failure == NULL) { 243 if (on_failure == NULL) {
243 // Instead of inlining a backtrack for each test, (re)use the global 244 // Instead of inlining a backtrack for each test, (re)use the global
244 // backtrack target. 245 // backtrack target.
245 on_failure = &backtrack_label_; 246 on_failure = &backtrack_label_;
246 } 247 }
247 248
248 if (check_end_of_string) { 249 if (check_end_of_string) {
249 // Is last character of required match inside string. 250 // Is last character of required match inside string.
250 CheckPosition(cp_offset + str.length() - 1, on_failure); 251 CheckPosition(cp_offset + str.length() - 1, on_failure);
251 } 252 }
252 253
253 __ add(r0, end_of_input_address(), Operand(current_input_offset())); 254 __ add(r0, end_of_input_address(), current_input_offset());
254 if (cp_offset != 0) { 255 if (cp_offset != 0) {
255 int byte_offset = cp_offset * char_size(); 256 int byte_offset = cp_offset * char_size();
256 __ add(r0, r0, Operand(byte_offset)); 257 __ add(r0, r0, Operand(byte_offset));
257 } 258 }
258 259
259 // r0 : Address of characters to match against str. 260 // r0 : Address of characters to match against str.
260 int stored_high_byte = 0; 261 int stored_high_byte = 0;
261 for (int i = 0; i < str.length(); i++) { 262 for (int i = 0; i < str.length(); i++) {
262 if (mode_ == ASCII) { 263 if (mode_ == ASCII) {
263 __ ldrb(r1, MemOperand(r0, char_size(), PostIndex)); 264 __ ldrb(r1, MemOperand(r0));
265 __ add(r0, r0, Operand(char_size()));
264 ASSERT(str[i] <= String::kMaxAsciiCharCode); 266 ASSERT(str[i] <= String::kMaxAsciiCharCode);
265 __ cmp(r1, Operand(str[i])); 267 __ cmp(r1, Operand(str[i]));
266 } else { 268 } else {
267 __ ldrh(r1, MemOperand(r0, char_size(), PostIndex)); 269 __ ldrh(r1, MemOperand(r0));
270 __ add(r0, r0, Operand(char_size()));
268 uc16 match_char = str[i]; 271 uc16 match_char = str[i];
269 int match_high_byte = (match_char >> 8); 272 int match_high_byte = (match_char >> 8);
270 if (match_high_byte == 0) { 273 if (match_high_byte == 0) {
271 __ cmp(r1, Operand(str[i])); 274 __ cmp(r1, Operand(str[i]));
272 } else { 275 } else {
273 if (match_high_byte != stored_high_byte) { 276 if (match_high_byte != stored_high_byte) {
274 __ mov(r2, Operand(match_high_byte)); 277 __ mov(r2, Operand(match_high_byte));
275 stored_high_byte = match_high_byte; 278 stored_high_byte = match_high_byte;
276 } 279 }
277 __ add(r3, r2, Operand(match_char & 0xff)); 280 __ add(r3, r2, Operand(match_char & 0xff));
278 __ cmp(r1, r3); 281 __ cmp(r1, r3);
279 } 282 }
280 } 283 }
281 BranchOrBacktrack(ne, on_failure); 284 BranchOrBacktrack(ne, on_failure);
282 } 285 }
283 } 286 }
284 287
285 288
286 void RegExpMacroAssemblerARM::CheckGreedyLoop(Label* on_equal) { 289 void RegExpMacroAssemblerSH4::CheckGreedyLoop(Label* on_equal) {
287 __ ldr(r0, MemOperand(backtrack_stackpointer(), 0)); 290 __ ldr(r0, MemOperand(backtrack_stackpointer(), 0));
288 __ cmp(current_input_offset(), r0); 291 __ cmp(current_input_offset(), r0);
292 Label skip;
293 __ b(ne, &skip, Label::kNear);
289 __ add(backtrack_stackpointer(), 294 __ add(backtrack_stackpointer(),
290 backtrack_stackpointer(), Operand(kPointerSize), LeaveCC, eq); 295 backtrack_stackpointer(), Operand(kPointerSize));
296 __ bind(&skip);
291 BranchOrBacktrack(eq, on_equal); 297 BranchOrBacktrack(eq, on_equal);
292 } 298 }
293 299
294 300
295 void RegExpMacroAssemblerARM::CheckNotBackReferenceIgnoreCase( 301 void RegExpMacroAssemblerSH4::CheckNotBackReferenceIgnoreCase(
296 int start_reg, 302 int start_reg,
297 Label* on_no_match) { 303 Label* on_no_match) {
298 Label fallthrough; 304 Label fallthrough;
299 __ ldr(r0, register_location(start_reg)); // Index of start of capture 305 __ ldr(r0, register_location(start_reg)); // Index of start of capture
300 __ ldr(r1, register_location(start_reg + 1)); // Index of end of capture 306 __ ldr(r1, register_location(start_reg + 1)); // Index of end of capture
301 __ sub(r1, r1, r0, SetCC); // Length of capture. 307 __ sub(r1, r1, r0); // Length of capture.
308 __ tst(r1, r1);
302 309
303 // If length is zero, either the capture is empty or it is not participating. 310 // If length is zero, either the capture is empty or it is not participating.
304 // In either case succeed immediately. 311 // In either case succeed immediately.
305 __ b(eq, &fallthrough); 312 __ b(eq, &fallthrough);
306 313
307 // Check that there are enough characters left in the input. 314 // Check that there are enough characters left in the input.
308 __ cmn(r1, Operand(current_input_offset())); 315 __ cmpgt(r1, current_input_offset());
309 BranchOrBacktrack(gt, on_no_match); 316 BranchOrBacktrack(ne, on_no_match);
310 317
311 if (mode_ == ASCII) { 318 if (mode_ == ASCII) {
312 Label success; 319 Label success;
313 Label fail; 320 Label fail;
314 Label loop_check; 321 Label loop_check;
315 322
316 // r0 - offset of start of capture 323 // r0 - offset of start of capture
317 // r1 - length of capture 324 // r1 - length of capture
318 __ add(r0, r0, Operand(end_of_input_address())); 325 __ add(r0, r0, end_of_input_address());
319 __ add(r2, end_of_input_address(), Operand(current_input_offset())); 326 __ add(r2, end_of_input_address(), current_input_offset());
320 __ add(r1, r0, Operand(r1)); 327 __ add(r1, r0, r1);
321 328
322 // r0 - Address of start of capture. 329 // r0 - Address of start of capture.
323 // r1 - Address of end of capture 330 // r1 - Address of end of capture
324 // r2 - Address of current input position. 331 // r2 - Address of current input position.
325 332
326 Label loop; 333 Label loop;
327 __ bind(&loop); 334 __ bind(&loop);
328 __ ldrb(r3, MemOperand(r0, char_size(), PostIndex)); 335 __ ldrb(r3, MemOperand(r0));
329 __ ldrb(r4, MemOperand(r2, char_size(), PostIndex)); 336 __ add(r0, r0, Operand(char_size()));
337 __ ldrb(r4, MemOperand(r2));
338 __ add(r2, r2, Operand(char_size()));
330 __ cmp(r4, r3); 339 __ cmp(r4, r3);
331 __ b(eq, &loop_check); 340 __ b(eq, &loop_check);
332 341
333 // Mismatch, try case-insensitive match (converting letters to lower-case). 342 // Mismatch, try case-insensitive match (converting letters to lower-case).
334 __ orr(r3, r3, Operand(0x20)); // Convert capture character to lower-case. 343 __ orr(r3, r3, Operand(0x20)); // Convert capture character to lower-case.
335 __ orr(r4, r4, Operand(0x20)); // Also convert input character. 344 __ orr(r4, r4, Operand(0x20)); // Also convert input character.
336 __ cmp(r4, r3); 345 __ cmp(r4, r3);
337 __ b(ne, &fail); 346 __ b(ne, &fail);
338 __ sub(r3, r3, Operand('a')); 347 __ sub(r3, r3, Operand('a'));
339 __ cmp(r3, Operand('z' - 'a')); // Is r3 a lowercase letter? 348 __ cmphi(r3, Operand('z' - 'a')); // Is r3 a lowercase letter?
340 __ b(hi, &fail); 349 __ b(eq, &fail);
341 350
342 351
343 __ bind(&loop_check); 352 __ bind(&loop_check);
344 __ cmp(r0, r1); 353 __ cmpge(r0, r1);
345 __ b(lt, &loop); 354 __ b(ne, &loop);
346 __ jmp(&success); 355 __ jmp(&success);
347 356
348 __ bind(&fail); 357 __ bind(&fail);
349 BranchOrBacktrack(al, on_no_match); 358 BranchOrBacktrack(al, on_no_match);
350 359
351 __ bind(&success); 360 __ bind(&success);
352 // Compute new value of character position after the matched part. 361 // Compute new value of character position after the matched part.
353 __ sub(current_input_offset(), r2, end_of_input_address()); 362 __ sub(current_input_offset(), r2, end_of_input_address());
354 } else { 363 } else {
355 ASSERT(mode_ == UC16); 364 ASSERT(mode_ == UC16);
356 int argument_count = 4; 365 int argument_count = 4;
357 __ PrepareCallCFunction(argument_count, r2); 366 __ PrepareCallCFunction(argument_count, r2);
358 367
359 // r0 - offset of start of capture 368 // r0 - offset of start of capture
360 // r1 - length of capture 369 // r1 - length of capture
361 370
362 // Put arguments into arguments registers. 371 // Put arguments into arguments registers.
363 // Parameters are 372 // Parameters are
364 // r0: Address byte_offset1 - Address captured substring's start. 373 // r0: Address byte_offset1 - Address captured substring's start.
365 // r1: Address byte_offset2 - Address of current character position. 374 // r1: Address byte_offset2 - Address of current character position.
366 // r2: size_t byte_length - length of capture in bytes(!) 375 // r2: size_t byte_length - length of capture in bytes(!)
367 // r3: Isolate* isolate 376 // r3: Isolate* isolate
368 377
378 __ Push(r4, r5, r6, r7);
369 // Address of start of capture. 379 // Address of start of capture.
370 __ add(r0, r0, Operand(end_of_input_address())); 380 __ add(r4, r0, end_of_input_address());
381 // Address of current input position.
382 __ add(r5, current_input_offset(), end_of_input_address());
371 // Length of capture. 383 // Length of capture.
372 __ mov(r2, Operand(r1)); 384 __ mov(r6, r1);
373 // Save length in callee-save register for use on return. 385 // Save length on stack for use on return.
374 __ mov(r4, Operand(r1)); 386 __ push(r1);
375 // Address of current input position.
376 __ add(r1, current_input_offset(), Operand(end_of_input_address()));
377 // Isolate. 387 // Isolate.
378 __ mov(r3, Operand(ExternalReference::isolate_address())); 388 __ mov(r7, Operand(ExternalReference::isolate_address()));
379 389
380 { 390 ExternalReference function =
381 AllowExternalCallThatCantCauseGC scope(masm_); 391 ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate());
382 ExternalReference function = 392 __ CallCFunction(function, argument_count);
383 ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate()); 393
384 __ CallCFunction(function, argument_count); 394 __ pop(r1);
385 } 395 __ Pop(r4, r5, r6, r7);
386 396
387 // Check if function returned non-zero for success or zero for failure. 397 // Check if function returned non-zero for success or zero for failure.
388 __ cmp(r0, Operand(0, RelocInfo::NONE)); 398 __ cmp(r0, Operand(0, RelocInfo::NONE));
389 BranchOrBacktrack(eq, on_no_match); 399 BranchOrBacktrack(eq, on_no_match);
390 // On success, increment position by length of capture. 400 // On success, increment position by length of capture.
391 __ add(current_input_offset(), current_input_offset(), Operand(r4)); 401 __ add(current_input_offset(), current_input_offset(), r1);
392 } 402 }
393 403
394 __ bind(&fallthrough); 404 __ bind(&fallthrough);
395 } 405 }
396 406
397 407
398 void RegExpMacroAssemblerARM::CheckNotBackReference( 408 void RegExpMacroAssemblerSH4::CheckNotBackReference(
399 int start_reg, 409 int start_reg,
400 Label* on_no_match) { 410 Label* on_no_match) {
401 Label fallthrough; 411 Label fallthrough;
402 Label success; 412 Label success;
403 413
404 // Find length of back-referenced capture. 414 // Find length of back-referenced capture.
405 __ ldr(r0, register_location(start_reg)); 415 __ ldr(r0, register_location(start_reg));
406 __ ldr(r1, register_location(start_reg + 1)); 416 __ ldr(r1, register_location(start_reg + 1));
407 __ sub(r1, r1, r0, SetCC); // Length to check. 417 __ sub(r1, r1, r0); // Length to check.
418 __ tst(r1, r1);
408 // Succeed on empty capture (including no capture). 419 // Succeed on empty capture (including no capture).
409 __ b(eq, &fallthrough); 420 __ b(eq, &fallthrough);
410 421
411 // Check that there are enough characters left in the input. 422 // Check that there are enough characters left in the input.
412 __ cmn(r1, Operand(current_input_offset())); 423 __ cmpgt(r1, current_input_offset());
413 BranchOrBacktrack(gt, on_no_match); 424 BranchOrBacktrack(ne, on_no_match);
414 425
415 // Compute pointers to match string and capture string 426 // Compute pointers to match string and capture string
416 __ add(r0, r0, Operand(end_of_input_address())); 427 __ add(r0, r0, end_of_input_address());
417 __ add(r2, end_of_input_address(), Operand(current_input_offset())); 428 __ add(r2, end_of_input_address(), current_input_offset());
418 __ add(r1, r1, Operand(r0)); 429 __ add(r1, r1, r0);
419 430
420 Label loop; 431 Label loop;
421 __ bind(&loop); 432 __ bind(&loop);
422 if (mode_ == ASCII) { 433 if (mode_ == ASCII) {
423 __ ldrb(r3, MemOperand(r0, char_size(), PostIndex)); 434 __ ldrb(r3, MemOperand(r0));
424 __ ldrb(r4, MemOperand(r2, char_size(), PostIndex)); 435 __ add(r0, r0, Operand(char_size()));
436 __ ldrb(r4, MemOperand(r2));
437 __ add(r2, r2, Operand(char_size()));
425 } else { 438 } else {
426 ASSERT(mode_ == UC16); 439 ASSERT(mode_ == UC16);
427 __ ldrh(r3, MemOperand(r0, char_size(), PostIndex)); 440 __ ldrh(r3, MemOperand(r0));
428 __ ldrh(r4, MemOperand(r2, char_size(), PostIndex)); 441 __ add(r0, r0, Operand(char_size()));
442 __ ldrh(r4, MemOperand(r2));
443 __ add(r2, r2, Operand(char_size()));
429 } 444 }
430 __ cmp(r3, r4); 445 __ cmp(r3, r4);
431 BranchOrBacktrack(ne, on_no_match); 446 BranchOrBacktrack(ne, on_no_match);
432 __ cmp(r0, r1); 447 __ cmpge(r0, r1);
433 __ b(lt, &loop); 448 __ b(ne, &loop);
434 449
435 // Move current character position to position after match. 450 // Move current character position to position after match.
436 __ sub(current_input_offset(), r2, end_of_input_address()); 451 __ sub(current_input_offset(), r2, end_of_input_address());
437 __ bind(&fallthrough); 452 __ bind(&fallthrough);
438 } 453 }
439 454
440 455
441 void RegExpMacroAssemblerARM::CheckNotCharacter(unsigned c, 456 void RegExpMacroAssemblerSH4::CheckNotCharacter(unsigned c,
442 Label* on_not_equal) { 457 Label* on_not_equal) {
443 __ cmp(current_character(), Operand(c)); 458 __ cmp(current_character(), Operand(c));
444 BranchOrBacktrack(ne, on_not_equal); 459 BranchOrBacktrack(ne, on_not_equal);
445 } 460 }
446 461
447 462
448 void RegExpMacroAssemblerARM::CheckCharacterAfterAnd(uint32_t c, 463 void RegExpMacroAssemblerSH4::CheckCharacterAfterAnd(uint32_t c,
449 uint32_t mask, 464 uint32_t mask,
450 Label* on_equal) { 465 Label* on_equal) {
451 if (c == 0) { 466 if (c == 0) {
452 __ tst(current_character(), Operand(mask)); 467 __ tst(current_character(), Operand(mask));
453 } else { 468 } else {
454 __ and_(r0, current_character(), Operand(mask)); 469 __ land(r0, current_character(), Operand(mask));
455 __ cmp(r0, Operand(c)); 470 __ cmp(r0, Operand(c));
456 } 471 }
457 BranchOrBacktrack(eq, on_equal); 472 BranchOrBacktrack(eq, on_equal);
458 } 473 }
459 474
460 475
461 void RegExpMacroAssemblerARM::CheckNotCharacterAfterAnd(unsigned c, 476 void RegExpMacroAssemblerSH4::CheckNotCharacterAfterAnd(unsigned c,
462 unsigned mask, 477 unsigned mask,
463 Label* on_not_equal) { 478 Label* on_not_equal) {
464 if (c == 0) { 479 if (c == 0) {
465 __ tst(current_character(), Operand(mask)); 480 __ tst(current_character(), Operand(mask));
466 } else { 481 } else {
467 __ and_(r0, current_character(), Operand(mask)); 482 __ land(r0, current_character(), Operand(mask));
468 __ cmp(r0, Operand(c)); 483 __ cmp(r0, Operand(c));
469 } 484 }
470 BranchOrBacktrack(ne, on_not_equal); 485 BranchOrBacktrack(ne, on_not_equal);
471 } 486 }
472 487
473 488
474 void RegExpMacroAssemblerARM::CheckNotCharacterAfterMinusAnd( 489 void RegExpMacroAssemblerSH4::CheckNotCharacterAfterMinusAnd(
475 uc16 c, 490 uc16 c,
476 uc16 minus, 491 uc16 minus,
477 uc16 mask, 492 uc16 mask,
478 Label* on_not_equal) { 493 Label* on_not_equal) {
479 ASSERT(minus < String::kMaxUtf16CodeUnit); 494 ASSERT(minus < String::kMaxUtf16CodeUnit);
480 __ sub(r0, current_character(), Operand(minus)); 495 __ sub(r0, current_character(), Operand(minus));
481 __ and_(r0, r0, Operand(mask)); 496 __ land(r0, r0, Operand(mask));
482 __ cmp(r0, Operand(c)); 497 __ cmp(r0, Operand(c));
483 BranchOrBacktrack(ne, on_not_equal); 498 BranchOrBacktrack(ne, on_not_equal);
484 } 499 }
485 500
486 501
487 void RegExpMacroAssemblerARM::CheckCharacterInRange( 502 void RegExpMacroAssemblerSH4::CheckCharacterInRange(
488 uc16 from, 503 uc16 from,
489 uc16 to, 504 uc16 to,
490 Label* on_in_range) { 505 Label* on_in_range) {
491 __ sub(r0, current_character(), Operand(from)); 506 __ sub(r0, current_character(), Operand(from));
492 __ cmp(r0, Operand(to - from)); 507 __ cmphi(r0, Operand(to - from));
493 BranchOrBacktrack(ls, on_in_range); // Unsigned lower-or-same condition. 508 BranchOrBacktrack(ne, on_in_range); // Unsigned lower-or-same condition.
494 } 509 }
495 510
496 511
497 void RegExpMacroAssemblerARM::CheckCharacterNotInRange( 512 void RegExpMacroAssemblerSH4::CheckCharacterNotInRange(
498 uc16 from, 513 uc16 from,
499 uc16 to, 514 uc16 to,
500 Label* on_not_in_range) { 515 Label* on_not_in_range) {
501 __ sub(r0, current_character(), Operand(from)); 516 __ sub(r0, current_character(), Operand(from));
502 __ cmp(r0, Operand(to - from)); 517 __ cmphi(r0, Operand(to - from));
503 BranchOrBacktrack(hi, on_not_in_range); // Unsigned higher condition. 518 BranchOrBacktrack(eq, on_not_in_range); // Unsigned higher condition.
504 } 519 }
505 520
506 521
507 void RegExpMacroAssemblerARM::CheckBitInTable( 522 void RegExpMacroAssemblerSH4::CheckBitInTable(
508 Handle<ByteArray> table, 523 Handle<ByteArray> table,
509 Label* on_bit_set) { 524 Label* on_bit_set) {
510 __ mov(r0, Operand(table)); 525 __ mov(r0, Operand(table));
511 if (mode_ != ASCII || kTableMask != String::kMaxAsciiCharCode) { 526 if (mode_ != ASCII || kTableMask != String::kMaxAsciiCharCode) {
512 __ and_(r1, current_character(), Operand(kTableSize - 1)); 527 __ land(r1, current_character(), Operand(kTableSize - 1));
513 __ add(r1, r1, Operand(ByteArray::kHeaderSize - kHeapObjectTag)); 528 __ add(r1, r1, Operand(ByteArray::kHeaderSize - kHeapObjectTag));
514 } else { 529 } else {
515 __ add(r1, 530 __ add(r1,
516 current_character(), 531 current_character(),
517 Operand(ByteArray::kHeaderSize - kHeapObjectTag)); 532 Operand(ByteArray::kHeaderSize - kHeapObjectTag));
518 } 533 }
519 __ ldrb(r0, MemOperand(r0, r1)); 534 __ ldrb(r0, MemOperand(r0, r1));
520 __ cmp(r0, Operand(0)); 535 __ cmpeq(r0, Operand(0));
521 BranchOrBacktrack(ne, on_bit_set); 536 BranchOrBacktrack(ne, on_bit_set);
522 } 537 }
523 538
524 539
525 bool RegExpMacroAssemblerARM::CheckSpecialCharacterClass(uc16 type, 540 bool RegExpMacroAssemblerSH4::CheckSpecialCharacterClass(uc16 type,
526 Label* on_no_match) { 541 Label* on_no_match) {
527 // Range checks (c in min..max) are generally implemented by an unsigned 542 // Range checks (c in min..max) are generally implemented by an unsigned
528 // (c - min) <= (max - min) check 543 // (c - min) <= (max - min) check
529 switch (type) { 544 switch (type) {
530 case 's': 545 case 's':
531 // Match space-characters 546 // Match space-characters
532 if (mode_ == ASCII) { 547 if (mode_ == ASCII) {
533 // ASCII space characters are '\t'..'\r' and ' '. 548 // ASCII space characters are '\t'..'\r' and ' '.
534 Label success; 549 Label success;
535 __ cmp(current_character(), Operand(' ')); 550 __ cmp(current_character(), Operand(' '));
536 __ b(eq, &success); 551 __ b(eq, &success);
537 // Check range 0x09..0x0d 552 // Check range 0x09..0x0d
538 __ sub(r0, current_character(), Operand('\t')); 553 __ sub(r0, current_character(), Operand('\t'));
539 __ cmp(r0, Operand('\r' - '\t')); 554 __ cmphi(r0, Operand('\r' - '\t'));
540 BranchOrBacktrack(hi, on_no_match); 555 BranchOrBacktrack(eq, on_no_match);
541 __ bind(&success); 556 __ bind(&success);
542 return true; 557 return true;
543 } 558 }
544 return false; 559 return false;
545 case 'S': 560 case 'S':
546 // Match non-space characters. 561 // Match non-space characters.
547 if (mode_ == ASCII) { 562 if (mode_ == ASCII) {
548 // ASCII space characters are '\t'..'\r' and ' '. 563 // ASCII space characters are '\t'..'\r' and ' '.
549 __ cmp(current_character(), Operand(' ')); 564 __ cmp(current_character(), Operand(' '));
550 BranchOrBacktrack(eq, on_no_match); 565 BranchOrBacktrack(eq, on_no_match);
551 __ sub(r0, current_character(), Operand('\t')); 566 __ sub(r0, current_character(), Operand('\t'));
552 __ cmp(r0, Operand('\r' - '\t')); 567 __ cmphi(r0, Operand('\r' - '\t'));
553 BranchOrBacktrack(ls, on_no_match); 568 BranchOrBacktrack(ne, on_no_match);
554 return true; 569 return true;
555 } 570 }
556 return false; 571 return false;
557 case 'd': 572 case 'd':
558 // Match ASCII digits ('0'..'9') 573 // Match ASCII digits ('0'..'9')
559 __ sub(r0, current_character(), Operand('0')); 574 __ sub(r0, current_character(), Operand('0'));
560 __ cmp(current_character(), Operand('9' - '0')); 575 __ cmphi(current_character(), Operand('9' - '0'));
561 BranchOrBacktrack(hi, on_no_match); 576 BranchOrBacktrack(eq, on_no_match);
562 return true; 577 return true;
563 case 'D': 578 case 'D':
564 // Match non ASCII-digits 579 // Match non ASCII-digits
565 __ sub(r0, current_character(), Operand('0')); 580 __ sub(r0, current_character(), Operand('0'));
566 __ cmp(r0, Operand('9' - '0')); 581 __ cmphi(r0, Operand('9' - '0'));
567 BranchOrBacktrack(ls, on_no_match); 582 BranchOrBacktrack(ne, on_no_match);
568 return true; 583 return true;
569 case '.': { 584 case '.': {
570 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) 585 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
571 __ eor(r0, current_character(), Operand(0x01)); 586 __ eor(r0, current_character(), Operand(0x01));
572 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c 587 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
573 __ sub(r0, r0, Operand(0x0b)); 588 __ sub(r0, r0, Operand(0x0b));
574 __ cmp(r0, Operand(0x0c - 0x0b)); 589 __ cmphi(r0, Operand(0x0c - 0x0b));
575 BranchOrBacktrack(ls, on_no_match); 590 BranchOrBacktrack(ne, on_no_match);
576 if (mode_ == UC16) { 591 if (mode_ == UC16) {
577 // Compare original value to 0x2028 and 0x2029, using the already 592 // Compare original value to 0x2028 and 0x2029, using the already
578 // computed (current_char ^ 0x01 - 0x0b). I.e., check for 593 // computed (current_char ^ 0x01 - 0x0b). I.e., check for
579 // 0x201d (0x2028 - 0x0b) or 0x201e. 594 // 0x201d (0x2028 - 0x0b) or 0x201e.
580 __ sub(r0, r0, Operand(0x2028 - 0x0b)); 595 __ sub(r0, r0, Operand(0x2028 - 0x0b));
581 __ cmp(r0, Operand(1)); 596 __ cmphi(r0, Operand(1));
582 BranchOrBacktrack(ls, on_no_match); 597 BranchOrBacktrack(ne, on_no_match);
583 } 598 }
584 return true; 599 return true;
585 } 600 }
586 case 'n': { 601 case 'n': {
587 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) 602 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
588 __ eor(r0, current_character(), Operand(0x01)); 603 __ eor(r0, current_character(), Operand(0x01));
589 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c 604 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
590 __ sub(r0, r0, Operand(0x0b)); 605 __ sub(r0, r0, Operand(0x0b));
591 __ cmp(r0, Operand(0x0c - 0x0b)); 606 __ cmphi(r0, Operand(0x0c - 0x0b));
592 if (mode_ == ASCII) { 607 if (mode_ == ASCII) {
593 BranchOrBacktrack(hi, on_no_match); 608 BranchOrBacktrack(eq, on_no_match);
594 } else { 609 } else {
595 Label done; 610 Label done;
596 __ b(ls, &done); 611 __ b(ne, &done);
597 // Compare original value to 0x2028 and 0x2029, using the already 612 // Compare original value to 0x2028 and 0x2029, using the already
598 // computed (current_char ^ 0x01 - 0x0b). I.e., check for 613 // computed (current_char ^ 0x01 - 0x0b). I.e., check for
599 // 0x201d (0x2028 - 0x0b) or 0x201e. 614 // 0x201d (0x2028 - 0x0b) or 0x201e.
600 __ sub(r0, r0, Operand(0x2028 - 0x0b)); 615 __ sub(r0, r0, Operand(0x2028 - 0x0b));
601 __ cmp(r0, Operand(1)); 616 __ cmphi(r0, Operand(1));
602 BranchOrBacktrack(hi, on_no_match); 617 BranchOrBacktrack(eq, on_no_match);
603 __ bind(&done); 618 __ bind(&done);
604 } 619 }
605 return true; 620 return true;
606 } 621 }
607 case 'w': { 622 case 'w': {
608 if (mode_ != ASCII) { 623 if (mode_ != ASCII) {
609 // Table is 128 entries, so all ASCII characters can be tested. 624 // Table is 128 entries, so all ASCII characters can be tested.
610 __ cmp(current_character(), Operand('z')); 625 __ cmphi(current_character(), Operand('z'));
611 BranchOrBacktrack(hi, on_no_match); 626 BranchOrBacktrack(eq, on_no_match);
612 } 627 }
613 ExternalReference map = ExternalReference::re_word_character_map(); 628 ExternalReference map = ExternalReference::re_word_character_map();
614 __ mov(r0, Operand(map)); 629 __ mov(r0, Operand(map));
615 __ ldrb(r0, MemOperand(r0, current_character())); 630 __ ldrb(r0, MemOperand(r0, current_character()));
616 __ cmp(r0, Operand(0)); 631 __ cmp(r0, Operand(0));
617 BranchOrBacktrack(eq, on_no_match); 632 BranchOrBacktrack(eq, on_no_match);
618 return true; 633 return true;
619 } 634 }
620 case 'W': { 635 case 'W': {
621 Label done; 636 Label done;
622 if (mode_ != ASCII) { 637 if (mode_ != ASCII) {
623 // Table is 128 entries, so all ASCII characters can be tested. 638 // Table is 128 entries, so all ASCII characters can be tested.
624 __ cmp(current_character(), Operand('z')); 639 __ cmphi(current_character(), Operand('z'));
625 __ b(hi, &done); 640 __ b(eq, &done);
626 } 641 }
627 ExternalReference map = ExternalReference::re_word_character_map(); 642 ExternalReference map = ExternalReference::re_word_character_map();
628 __ mov(r0, Operand(map)); 643 __ mov(r0, Operand(map));
629 __ ldrb(r0, MemOperand(r0, current_character())); 644 __ ldrb(r0, MemOperand(r0, current_character()));
630 __ cmp(r0, Operand(0)); 645 __ cmp(r0, Operand(0));
631 BranchOrBacktrack(ne, on_no_match); 646 BranchOrBacktrack(ne, on_no_match);
632 if (mode_ != ASCII) { 647 if (mode_ != ASCII) {
633 __ bind(&done); 648 __ bind(&done);
634 } 649 }
635 return true; 650 return true;
636 } 651 }
637 case '*': 652 case '*':
638 // Match any character. 653 // Match any character.
639 return true; 654 return true;
640 // No custom implementation (yet): s(UC16), S(UC16). 655 // No custom implementation (yet): s(UC16), S(UC16).
641 default: 656 default:
642 return false; 657 return false;
643 } 658 }
644 } 659 }
645 660
646 661
647 void RegExpMacroAssemblerARM::Fail() { 662 void RegExpMacroAssemblerSH4::Fail() {
648 __ mov(r0, Operand(FAILURE)); 663 __ mov(r0, Operand(FAILURE));
649 __ jmp(&exit_label_); 664 __ jmp(&exit_label_);
650 } 665 }
651 666
652 667
653 Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) { 668 Handle<HeapObject> RegExpMacroAssemblerSH4::GetCode(Handle<String> source) {
654 Label return_r0; 669 Label return_r0;
655 // Finalize code - write the entry point code now we know how many 670 // Finalize code - write the entry point code now we know how many
656 // registers we need. 671 // registers we need.
657 672
658 // Entry code: 673 // Entry code:
659 __ bind(&entry_label_); 674 __ bind(&entry_label_);
660 675
661 // Tell the system that we have a stack frame. Because the type is MANUAL, no 676 // Tell the system that we have a stack frame. Because the type is MANUAL, no
662 // is generated. 677 // is generated.
663 FrameScope scope(masm_, StackFrame::MANUAL); 678 FrameScope scope(masm_, StackFrame::MANUAL);
664 679
665 // Actually emit code to start a new stack frame. 680 // Actually emit code to start a new stack frame.
666 // Push arguments 681 // Push arguments
667 // Save callee-save registers. 682 // Save callee-save registers.
668 // Start new stack frame. 683 // Start new stack frame.
669 // Store link register in existing stack-cell. 684 // Store link register in existing stack-cell.
670 // Order here should correspond to order of offset constants in header file. 685 // Order here should correspond to order of offset constants in header file.
671 RegList registers_to_retain = r4.bit() | r5.bit() | r6.bit() | 686 // WARNING: should change the value of kReturnAddress (depend on the number
672 r7.bit() | r8.bit() | r9.bit() | r10.bit() | fp.bit(); 687 // of saved registers.
673 RegList argument_registers = r0.bit() | r1.bit() | r2.bit() | r3.bit(); 688 RegList registers_to_retain = kCalleeSaved;
674 __ stm(db_w, sp, argument_registers | registers_to_retain | lr.bit()); 689 RegList argument_registers = r4.bit() | r5.bit() | r6.bit() | r7.bit();
690 __ push(pr);
691 __ pushm(registers_to_retain);
692 __ pushm(argument_registers);
675 // Set frame pointer in space for it if this is not a direct call 693 // Set frame pointer in space for it if this is not a direct call
676 // from generated code. 694 // from generated code.
677 __ add(frame_pointer(), sp, Operand(4 * kPointerSize)); 695 __ add(frame_pointer(), sp, Operand(4 * kPointerSize));
678 __ mov(r0, Operand(0, RelocInfo::NONE)); 696 __ mov(r0, Operand(0, RelocInfo::NONE));
679 __ push(r0); // Make room for success counter and initialize it to 0. 697 __ push(r0); // Make room for success counter and initialize it to 0.
680 __ push(r0); // Make room for "position - 1" constant (value is irrelevant). 698 __ push(r0); // Make room for "position - 1" constant (value is irrelevant).
681 // Check if we have space on the stack for registers. 699 // Check if we have space on the stack for registers.
682 Label stack_limit_hit; 700 Label stack_limit_hit;
683 Label stack_ok; 701 Label stack_ok;
684 702
685 ExternalReference stack_limit = 703 ExternalReference stack_limit =
686 ExternalReference::address_of_stack_limit(masm_->isolate()); 704 ExternalReference::address_of_stack_limit(masm_->isolate());
687 __ mov(r0, Operand(stack_limit)); 705 __ mov(r0, Operand(stack_limit));
688 __ ldr(r0, MemOperand(r0)); 706 __ ldr(r0, MemOperand(r0));
689 __ sub(r0, sp, r0, SetCC);
690 // Handle it if the stack pointer is already below the stack limit. 707 // Handle it if the stack pointer is already below the stack limit.
691 __ b(ls, &stack_limit_hit); 708 __ cmphi(sp, r0);
709 __ sub(r0, sp, r0);
710 __ b(ne, &stack_limit_hit);
692 // Check if there is room for the variable number of registers above 711 // Check if there is room for the variable number of registers above
693 // the stack limit. 712 // the stack limit.
694 __ cmp(r0, Operand(num_registers_ * kPointerSize)); 713 __ cmphs(r0, Operand(num_registers_ * kPointerSize));
695 __ b(hs, &stack_ok); 714 __ b(eq, &stack_ok, Label::kNear);
696 // Exit with OutOfMemory exception. There is not enough space on the stack 715 // Exit with OutOfMemory exception. There is not enough space on the stack
697 // for our working registers. 716 // for our working registers.
698 __ mov(r0, Operand(EXCEPTION)); 717 __ mov(r0, Operand(EXCEPTION));
699 __ jmp(&return_r0); 718 __ jmp(&return_r0);
700 719
701 __ bind(&stack_limit_hit); 720 __ bind(&stack_limit_hit);
702 CallCheckStackGuardState(r0); 721 CallCheckStackGuardState(r0);
703 __ cmp(r0, Operand(0, RelocInfo::NONE)); 722 __ cmp(r0, Operand(0, RelocInfo::NONE));
704 // If returned value is non-zero, we exit with the returned value as result. 723 // If returned value is non-zero, we exit with the returned value as result.
705 __ b(ne, &return_r0); 724 __ b(ne, &return_r0);
706 725
707 __ bind(&stack_ok); 726 __ bind(&stack_ok);
708 727
709 // Allocate space on stack for registers. 728 // Allocate space on stack for registers.
710 __ sub(sp, sp, Operand(num_registers_ * kPointerSize)); 729 __ sub(sp, sp, Operand(num_registers_ * kPointerSize));
711 // Load string end. 730 // Load string end.
712 __ ldr(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 731 __ ldr(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
713 // Load input start. 732 // Load input start.
714 __ ldr(r0, MemOperand(frame_pointer(), kInputStart)); 733 __ ldr(r0, MemOperand(frame_pointer(), kInputStart));
715 // Find negative length (offset of start relative to end). 734 // Find negative length (offset of start relative to end).
716 __ sub(current_input_offset(), r0, end_of_input_address()); 735 __ sub(current_input_offset(), r0, end_of_input_address());
717 // Set r0 to address of char before start of the input string 736 // Set r0 to address of char before start of the input string
718 // (effectively string position -1). 737 // (effectively string position -1).
719 __ ldr(r1, MemOperand(frame_pointer(), kStartIndex)); 738 __ ldr(r1, MemOperand(frame_pointer(), kStartIndex));
720 __ sub(r0, current_input_offset(), Operand(char_size())); 739 __ sub(r0, current_input_offset(), Operand(char_size()));
721 __ sub(r0, r0, Operand(r1, LSL, (mode_ == UC16) ? 1 : 0)); 740 __ lsl(ip, r1, Operand((mode_ == UC16) ? 1 : 0));
741 __ sub(r0, r0, ip);
722 // Store this value in a local variable, for use when clearing 742 // Store this value in a local variable, for use when clearing
723 // position registers. 743 // position registers.
724 __ str(r0, MemOperand(frame_pointer(), kInputStartMinusOne)); 744 __ str(r0, MemOperand(frame_pointer(), kInputStartMinusOne));
725 745
726 // Initialize code pointer register 746 // Initialize code pointer register
727 __ mov(code_pointer(), Operand(masm_->CodeObject())); 747 __ mov(code_pointer(), Operand(masm_->CodeObject()));
728 748
729 Label load_char_start_regexp, start_regexp; 749 Label load_char_start_regexp, start_regexp;
730 // Load newline if index is at start, previous character otherwise. 750 // Load newline if index is at start, previous character otherwise.
731 __ cmp(r1, Operand(0, RelocInfo::NONE)); 751 __ cmp(r1, Operand(0, RelocInfo::NONE));
732 __ b(ne, &load_char_start_regexp); 752 __ b(ne, &load_char_start_regexp);
733 __ mov(current_character(), Operand('\n'), LeaveCC, eq); 753 __ mov(current_character(), Operand('\n'), eq);
734 __ jmp(&start_regexp); 754 __ jmp(&start_regexp);
735 755
736 // Global regexp restarts matching here. 756 // Global regexp restarts matching here.
737 __ bind(&load_char_start_regexp); 757 __ bind(&load_char_start_regexp);
738 // Load previous char as initial value of current character register. 758 // Load previous char as initial value of current character register.
739 LoadCurrentCharacterUnchecked(-1, 1); 759 LoadCurrentCharacterUnchecked(-1, 1);
740 __ bind(&start_regexp); 760 __ bind(&start_regexp);
741 761
742 // Initialize on-stack registers. 762 // Initialize on-stack registers.
743 if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. 763 if (num_saved_registers_ > 0) { // Always is, if generated from a regexp.
744 // Fill saved registers with initial value = start offset - 1 764 // Fill saved registers with initial value = start offset - 1
745 if (num_saved_registers_ > 8) { 765 if (num_saved_registers_ > 8) {
746 // Address of register 0. 766 // Address of register 0.
747 __ add(r1, frame_pointer(), Operand(kRegisterZero)); 767 __ add(r1, frame_pointer(), Operand(kRegisterZero));
748 __ mov(r2, Operand(num_saved_registers_)); 768 __ mov(r2, Operand(num_saved_registers_));
749 Label init_loop; 769 Label init_loop;
750 __ bind(&init_loop); 770 __ bind(&init_loop);
751 __ str(r0, MemOperand(r1, kPointerSize, NegPostIndex)); 771 __ str(r0, MemOperand(r1, kPointerSize));
752 __ sub(r2, r2, Operand(1), SetCC); 772 __ add(r1, r1, Operand(-kPointerSize));
773 __ dt(r2);
753 __ b(ne, &init_loop); 774 __ b(ne, &init_loop);
754 } else { 775 } else {
755 for (int i = 0; i < num_saved_registers_; i++) { 776 for (int i = 0; i < num_saved_registers_; i++) {
756 __ str(r0, register_location(i)); 777 __ str(r0, register_location(i));
757 } 778 }
758 } 779 }
759 } 780 }
760 781
761 // Initialize backtrack stack pointer. 782 // Initialize backtrack stack pointer.
762 __ ldr(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd)); 783 __ ldr(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd));
763 784
764 __ jmp(&start_label_); 785 __ jmp(&start_label_);
765 786
766 // Exit code: 787 // Exit code:
767 if (success_label_.is_linked()) { 788 if (success_label_.is_linked()) {
768 // Save captures when successful. 789 // Save captures when successful.
769 __ bind(&success_label_); 790 __ bind(&success_label_);
770 if (num_saved_registers_ > 0) { 791 if (num_saved_registers_ > 0) {
771 // copy captures to output 792 // copy captures to output
772 __ ldr(r1, MemOperand(frame_pointer(), kInputStart)); 793 __ ldr(r1, MemOperand(frame_pointer(), kInputStart));
773 __ ldr(r0, MemOperand(frame_pointer(), kRegisterOutput)); 794 __ ldr(r0, MemOperand(frame_pointer(), kRegisterOutput));
774 __ ldr(r2, MemOperand(frame_pointer(), kStartIndex)); 795 __ ldr(r2, MemOperand(frame_pointer(), kStartIndex));
775 __ sub(r1, end_of_input_address(), r1); 796 __ sub(r1, end_of_input_address(), r1);
776 // r1 is length of input in bytes. 797 // r1 is length of input in bytes.
777 if (mode_ == UC16) { 798 if (mode_ == UC16) {
778 __ mov(r1, Operand(r1, LSR, 1)); 799 __ lsr(r1, r1, Operand(1));
779 } 800 }
780 // r1 is length of input in characters. 801 // r1 is length of input in characters.
781 __ add(r1, r1, Operand(r2)); 802 __ add(r1, r1, r2);
782 // r1 is length of string in characters. 803 // r1 is length of string in characters.
783 804
784 ASSERT_EQ(0, num_saved_registers_ % 2); 805 ASSERT_EQ(0, num_saved_registers_ % 2);
785 // Always an even number of capture registers. This allows us to 806 // Always an even number of capture registers. This allows us to
786 // unroll the loop once to add an operation between a load of a register 807 // unroll the loop once to add an operation between a load of a register
787 // and the following use of that register. 808 // and the following use of that register.
788 for (int i = 0; i < num_saved_registers_; i += 2) { 809 for (int i = 0; i < num_saved_registers_; i += 2) {
789 __ ldr(r2, register_location(i)); 810 __ ldr(r2, register_location(i));
790 __ ldr(r3, register_location(i + 1)); 811 __ ldr(r3, register_location(i + 1));
791 if (i == 0 && global_with_zero_length_check()) { 812 if (i == 0 && global_with_zero_length_check()) {
792 // Keep capture start in r4 for the zero-length check later. 813 // Keep capture start in r4 for the zero-length check later.
793 __ mov(r4, r2); 814 __ mov(r4, r2);
794 } 815 }
795 if (mode_ == UC16) { 816 if (mode_ == UC16) {
796 __ add(r2, r1, Operand(r2, ASR, 1)); 817 __ asr(r2, r2, Operand(1));
797 __ add(r3, r1, Operand(r3, ASR, 1)); 818 __ add(r2, r1, r2);
819 __ asr(r3, r3, Operand(1));
820 __ add(r3, r1, r3);
798 } else { 821 } else {
799 __ add(r2, r1, Operand(r2)); 822 __ add(r2, r1, r2);
800 __ add(r3, r1, Operand(r3)); 823 __ add(r3, r1, r3);
801 } 824 }
802 __ str(r2, MemOperand(r0, kPointerSize, PostIndex)); 825 __ str(r2, MemOperand(r0, kPointerSize, PostIndex));
803 __ str(r3, MemOperand(r0, kPointerSize, PostIndex)); 826 __ str(r3, MemOperand(r0, kPointerSize, PostIndex));
804 } 827 }
805 } 828 }
806 829
807 if (global()) { 830 if (global()) {
808 // Restart matching if the regular expression is flagged as global. 831 // Restart matching if the regular expression is flagged as global.
809 __ ldr(r0, MemOperand(frame_pointer(), kSuccessfulCaptures)); 832 __ ldr(r0, MemOperand(frame_pointer(), kSuccessfulCaptures));
810 __ ldr(r1, MemOperand(frame_pointer(), kNumOutputRegisters)); 833 __ ldr(r1, MemOperand(frame_pointer(), kNumOutputRegisters));
811 __ ldr(r2, MemOperand(frame_pointer(), kRegisterOutput)); 834 __ ldr(r2, MemOperand(frame_pointer(), kRegisterOutput));
812 // Increment success counter. 835 // Increment success counter.
813 __ add(r0, r0, Operand(1)); 836 __ add(r0, r0, Operand(1));
814 __ str(r0, MemOperand(frame_pointer(), kSuccessfulCaptures)); 837 __ str(r0, MemOperand(frame_pointer(), kSuccessfulCaptures));
815 // Capture results have been stored, so the number of remaining global 838 // Capture results have been stored, so the number of remaining global
816 // output registers is reduced by the number of stored captures. 839 // output registers is reduced by the number of stored captures.
817 __ sub(r1, r1, Operand(num_saved_registers_)); 840 __ sub(r1, r1, Operand(num_saved_registers_));
818 // Check whether we have enough room for another set of capture results. 841 // Check whether we have enough room for another set of capture results.
819 __ cmp(r1, Operand(num_saved_registers_)); 842 __ cmpge(r1, Operand(num_saved_registers_));
820 __ b(lt, &return_r0); 843 __ bf(&return_r0);
821 844
822 __ str(r1, MemOperand(frame_pointer(), kNumOutputRegisters)); 845 __ str(r1, MemOperand(frame_pointer(), kNumOutputRegisters));
823 // Advance the location for output. 846 // Advance the location for output.
824 __ add(r2, r2, Operand(num_saved_registers_ * kPointerSize)); 847 __ add(r2, r2, Operand(num_saved_registers_ * kPointerSize));
825 __ str(r2, MemOperand(frame_pointer(), kRegisterOutput)); 848 __ str(r2, MemOperand(frame_pointer(), kRegisterOutput));
826 849
827 // Prepare r0 to initialize registers with its value in the next run. 850 // Prepare r0 to initialize registers with its value in the next run.
828 __ ldr(r0, MemOperand(frame_pointer(), kInputStartMinusOne)); 851 __ ldr(r0, MemOperand(frame_pointer(), kInputStartMinusOne));
829 852
830 if (global_with_zero_length_check()) { 853 if (global_with_zero_length_check()) {
(...skipping 20 matching lines...) Expand all
851 // Exit and return r0 874 // Exit and return r0
852 __ bind(&exit_label_); 875 __ bind(&exit_label_);
853 if (global()) { 876 if (global()) {
854 __ ldr(r0, MemOperand(frame_pointer(), kSuccessfulCaptures)); 877 __ ldr(r0, MemOperand(frame_pointer(), kSuccessfulCaptures));
855 } 878 }
856 879
857 __ bind(&return_r0); 880 __ bind(&return_r0);
858 // Skip sp past regexp registers and local variables.. 881 // Skip sp past regexp registers and local variables..
859 __ mov(sp, frame_pointer()); 882 __ mov(sp, frame_pointer());
860 // Restore registers r4..r11 and return (restoring lr to pc). 883 // Restore registers r4..r11 and return (restoring lr to pc).
861 __ ldm(ia_w, sp, registers_to_retain | pc.bit()); 884 __ popm(registers_to_retain);
885 __ pop(pr);
886 __ rts();
862 887
863 // Backtrack code (branch target for conditional backtracks). 888 // Backtrack code (branch target for conditional backtracks).
864 if (backtrack_label_.is_linked()) { 889 if (backtrack_label_.is_linked()) {
865 __ bind(&backtrack_label_); 890 __ bind(&backtrack_label_);
866 Backtrack(); 891 Backtrack();
867 } 892 }
868 893
869 Label exit_with_exception; 894 Label exit_with_exception;
870 895
871 // Preempt-code 896 // Preempt-code
(...skipping 11 matching lines...) Expand all
883 SafeReturn(); 908 SafeReturn();
884 } 909 }
885 910
886 // Backtrack stack overflow code. 911 // Backtrack stack overflow code.
887 if (stack_overflow_label_.is_linked()) { 912 if (stack_overflow_label_.is_linked()) {
888 SafeCallTarget(&stack_overflow_label_); 913 SafeCallTarget(&stack_overflow_label_);
889 // Reached if the backtrack-stack limit has been hit. 914 // Reached if the backtrack-stack limit has been hit.
890 Label grow_failed; 915 Label grow_failed;
891 916
892 // Call GrowStack(backtrack_stackpointer(), &stack_base) 917 // Call GrowStack(backtrack_stackpointer(), &stack_base)
918 __ Push(r4, r5, r6, r7);
893 static const int num_arguments = 3; 919 static const int num_arguments = 3;
920 __ mov(r4, backtrack_stackpointer());
921 __ add(r5, frame_pointer(), Operand(kStackHighEnd));
922 __ mov(r6, Operand(ExternalReference::isolate_address()));
894 __ PrepareCallCFunction(num_arguments, r0); 923 __ PrepareCallCFunction(num_arguments, r0);
895 __ mov(r0, backtrack_stackpointer());
896 __ add(r1, frame_pointer(), Operand(kStackHighEnd));
897 __ mov(r2, Operand(ExternalReference::isolate_address()));
898 ExternalReference grow_stack = 924 ExternalReference grow_stack =
899 ExternalReference::re_grow_stack(masm_->isolate()); 925 ExternalReference::re_grow_stack(masm_->isolate());
900 __ CallCFunction(grow_stack, num_arguments); 926 __ CallCFunction(grow_stack, num_arguments);
901 // If return NULL, we have failed to grow the stack, and 927 // If return NULL, we have failed to grow the stack, and
902 // must exit with a stack-overflow exception. 928 // must exit with a stack-overflow exception.
929 __ Pop(r4, r5, r6, r7);
903 __ cmp(r0, Operand(0, RelocInfo::NONE)); 930 __ cmp(r0, Operand(0, RelocInfo::NONE));
904 __ b(eq, &exit_with_exception); 931 __ b(eq, &exit_with_exception);
905 // Otherwise use return value as new stack pointer. 932 // Otherwise use return value as new stack pointer.
906 __ mov(backtrack_stackpointer(), r0); 933 __ mov(backtrack_stackpointer(), r0);
907 // Restore saved registers and continue. 934 // Restore saved registers and continue.
908 SafeReturn(); 935 SafeReturn();
909 } 936 }
910 937
911 if (exit_with_exception.is_linked()) { 938 if (exit_with_exception.is_linked()) {
912 // If any of the code above needed to exit with an exception. 939 // If any of the code above needed to exit with an exception.
913 __ bind(&exit_with_exception); 940 __ bind(&exit_with_exception);
914 // Exit with Result EXCEPTION(-1) to signal thrown exception. 941 // Exit with Result EXCEPTION(-1) to signal thrown exception.
915 __ mov(r0, Operand(EXCEPTION)); 942 __ mov(r0, Operand(EXCEPTION));
916 __ jmp(&return_r0); 943 __ jmp(&return_r0);
917 } 944 }
918 945
919 CodeDesc code_desc; 946 CodeDesc code_desc;
920 masm_->GetCode(&code_desc); 947 masm_->GetCode(&code_desc);
921 Handle<Code> code = FACTORY->NewCode(code_desc, 948 Handle<Code> code = FACTORY->NewCode(code_desc,
922 Code::ComputeFlags(Code::REGEXP), 949 Code::ComputeFlags(Code::REGEXP),
923 masm_->CodeObject()); 950 masm_->CodeObject());
924 PROFILE(Isolate::Current(), RegExpCodeCreateEvent(*code, *source)); 951 PROFILE(Isolate::Current(), RegExpCodeCreateEvent(*code, *source));
925 return Handle<HeapObject>::cast(code); 952 return Handle<HeapObject>::cast(code);
926 } 953 }
927 954
928 955
929 void RegExpMacroAssemblerARM::GoTo(Label* to) { 956 void RegExpMacroAssemblerSH4::GoTo(Label* to) {
930 BranchOrBacktrack(al, to); 957 BranchOrBacktrack(al, to);
931 } 958 }
932 959
933 960
934 void RegExpMacroAssemblerARM::IfRegisterGE(int reg, 961 void RegExpMacroAssemblerSH4::IfRegisterGE(int reg,
935 int comparand, 962 int comparand,
936 Label* if_ge) { 963 Label* if_ge) {
937 __ ldr(r0, register_location(reg)); 964 __ ldr(r0, register_location(reg));
938 __ cmp(r0, Operand(comparand)); 965 __ cmpge(r0, Operand(comparand));
939 BranchOrBacktrack(ge, if_ge); 966 BranchOrBacktrack(eq, if_ge);
940 } 967 }
941 968
942 969
943 void RegExpMacroAssemblerARM::IfRegisterLT(int reg, 970 void RegExpMacroAssemblerSH4::IfRegisterLT(int reg,
944 int comparand, 971 int comparand,
945 Label* if_lt) { 972 Label* if_lt) {
946 __ ldr(r0, register_location(reg)); 973 __ ldr(r0, register_location(reg));
947 __ cmp(r0, Operand(comparand)); 974 __ cmpge(r0, Operand(comparand));
948 BranchOrBacktrack(lt, if_lt); 975 BranchOrBacktrack(ne, if_lt);
949 } 976 }
950 977
951 978
952 void RegExpMacroAssemblerARM::IfRegisterEqPos(int reg, 979 void RegExpMacroAssemblerSH4::IfRegisterEqPos(int reg,
953 Label* if_eq) { 980 Label* if_eq) {
954 __ ldr(r0, register_location(reg)); 981 __ ldr(r0, register_location(reg));
955 __ cmp(r0, Operand(current_input_offset())); 982 __ cmp(r0, current_input_offset());
956 BranchOrBacktrack(eq, if_eq); 983 BranchOrBacktrack(eq, if_eq);
957 } 984 }
958 985
959 986
960 RegExpMacroAssembler::IrregexpImplementation 987 RegExpMacroAssembler::IrregexpImplementation
961 RegExpMacroAssemblerARM::Implementation() { 988 RegExpMacroAssemblerSH4::Implementation() {
962 return kARMImplementation; 989 return kSH4Implementation;
963 } 990 }
964 991
965 992
966 void RegExpMacroAssemblerARM::LoadCurrentCharacter(int cp_offset, 993 void RegExpMacroAssemblerSH4::LoadCurrentCharacter(int cp_offset,
967 Label* on_end_of_input, 994 Label* on_end_of_input,
968 bool check_bounds, 995 bool check_bounds,
969 int characters) { 996 int characters) {
970 ASSERT(cp_offset >= -1); // ^ and \b can look behind one character. 997 ASSERT(cp_offset >= -1); // ^ and \b can look behind one character.
971 ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) 998 ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works)
972 if (check_bounds) { 999 if (check_bounds) {
973 CheckPosition(cp_offset + characters - 1, on_end_of_input); 1000 CheckPosition(cp_offset + characters - 1, on_end_of_input);
974 } 1001 }
975 LoadCurrentCharacterUnchecked(cp_offset, characters); 1002 LoadCurrentCharacterUnchecked(cp_offset, characters);
976 } 1003 }
977 1004
978 1005
979 void RegExpMacroAssemblerARM::PopCurrentPosition() { 1006 void RegExpMacroAssemblerSH4::PopCurrentPosition() {
980 Pop(current_input_offset()); 1007 Pop(current_input_offset());
981 } 1008 }
982 1009
983 1010
984 void RegExpMacroAssemblerARM::PopRegister(int register_index) { 1011 void RegExpMacroAssemblerSH4::PopRegister(int register_index) {
985 Pop(r0); 1012 Pop(r0);
986 __ str(r0, register_location(register_index)); 1013 __ str(r0, register_location(register_index));
987 } 1014 }
988 1015
989 1016
990 static bool is_valid_memory_offset(int value) { 1017 void RegExpMacroAssemblerSH4::PushBacktrack(Label* label) {
991 if (value < 0) value = -value;
992 return value < (1<<12);
993 }
994
995
996 void RegExpMacroAssemblerARM::PushBacktrack(Label* label) {
997 if (label->is_bound()) { 1018 if (label->is_bound()) {
998 int target = label->pos(); 1019 int target = label->pos();
999 __ mov(r0, Operand(target + Code::kHeaderSize - kHeapObjectTag)); 1020 __ mov(r0, Operand(target + Code::kHeaderSize - kHeapObjectTag));
1000 } else { 1021 } else {
1001 int constant_offset = GetBacktrackConstantPoolEntry(); 1022 masm_->load_label(label);
1002 masm_->label_at_put(label, constant_offset);
1003 // Reading pc-relative is based on the address 8 bytes ahead of
1004 // the current opcode.
1005 unsigned int offset_of_pc_register_read =
1006 masm_->pc_offset() + Assembler::kPcLoadDelta;
1007 int pc_offset_of_constant =
1008 constant_offset - offset_of_pc_register_read;
1009 ASSERT(pc_offset_of_constant < 0);
1010 if (is_valid_memory_offset(pc_offset_of_constant)) {
1011 Assembler::BlockConstPoolScope block_const_pool(masm_);
1012 __ ldr(r0, MemOperand(pc, pc_offset_of_constant));
1013 } else {
1014 // Not a 12-bit offset, so it needs to be loaded from the constant
1015 // pool.
1016 Assembler::BlockConstPoolScope block_const_pool(masm_);
1017 __ mov(r0, Operand(pc_offset_of_constant + Assembler::kInstrSize));
1018 __ ldr(r0, MemOperand(pc, r0));
1019 }
1020 } 1023 }
1021 Push(r0); 1024 Push(r0);
1022 CheckStackLimit(); 1025 CheckStackLimit();
1023 } 1026 }
1024 1027
1025 1028
1026 void RegExpMacroAssemblerARM::PushCurrentPosition() { 1029 void RegExpMacroAssemblerSH4::PushCurrentPosition() {
1027 Push(current_input_offset()); 1030 Push(current_input_offset());
1028 } 1031 }
1029 1032
1030 1033
1031 void RegExpMacroAssemblerARM::PushRegister(int register_index, 1034 void RegExpMacroAssemblerSH4::PushRegister(int register_index,
1032 StackCheckFlag check_stack_limit) { 1035 StackCheckFlag check_stack_limit) {
1033 __ ldr(r0, register_location(register_index)); 1036 __ ldr(r0, register_location(register_index));
1034 Push(r0); 1037 Push(r0);
1035 if (check_stack_limit) CheckStackLimit(); 1038 if (check_stack_limit) CheckStackLimit();
1036 } 1039 }
1037 1040
1038 1041
1039 void RegExpMacroAssemblerARM::ReadCurrentPositionFromRegister(int reg) { 1042 void RegExpMacroAssemblerSH4::ReadCurrentPositionFromRegister(int reg) {
1040 __ ldr(current_input_offset(), register_location(reg)); 1043 __ ldr(current_input_offset(), register_location(reg));
1041 } 1044 }
1042 1045
1043 1046
1044 void RegExpMacroAssemblerARM::ReadStackPointerFromRegister(int reg) { 1047 void RegExpMacroAssemblerSH4::ReadStackPointerFromRegister(int reg) {
1045 __ ldr(backtrack_stackpointer(), register_location(reg)); 1048 __ ldr(backtrack_stackpointer(), register_location(reg));
1046 __ ldr(r0, MemOperand(frame_pointer(), kStackHighEnd)); 1049 __ ldr(r0, MemOperand(frame_pointer(), kStackHighEnd));
1047 __ add(backtrack_stackpointer(), backtrack_stackpointer(), Operand(r0)); 1050 __ add(backtrack_stackpointer(), backtrack_stackpointer(), r0);
1048 } 1051 }
1049 1052
1050 1053
1051 void RegExpMacroAssemblerARM::SetCurrentPositionFromEnd(int by) { 1054 void RegExpMacroAssemblerSH4::SetCurrentPositionFromEnd(int by) {
1052 Label after_position; 1055 Label after_position;
1053 __ cmp(current_input_offset(), Operand(-by * char_size())); 1056 __ cmpge(current_input_offset(), Operand(-by * char_size()));
1054 __ b(ge, &after_position); 1057 __ b(eq, &after_position);
1055 __ mov(current_input_offset(), Operand(-by * char_size())); 1058 __ mov(current_input_offset(), Operand(-by * char_size()));
1056 // On RegExp code entry (where this operation is used), the character before 1059 // On RegExp code entry (where this operation is used), the character before
1057 // the current position is expected to be already loaded. 1060 // the current position is expected to be already loaded.
1058 // We have advanced the position, so it's safe to read backwards. 1061 // We have advanced the position, so it's safe to read backwards.
1059 LoadCurrentCharacterUnchecked(-1, 1); 1062 LoadCurrentCharacterUnchecked(-1, 1);
1060 __ bind(&after_position); 1063 __ bind(&after_position);
1061 } 1064 }
1062 1065
1063 1066
1064 void RegExpMacroAssemblerARM::SetRegister(int register_index, int to) { 1067 void RegExpMacroAssemblerSH4::SetRegister(int register_index, int to) {
1065 ASSERT(register_index >= num_saved_registers_); // Reserved for positions! 1068 ASSERT(register_index >= num_saved_registers_); // Reserved for positions!
1066 __ mov(r0, Operand(to)); 1069 __ mov(r0, Operand(to));
1067 __ str(r0, register_location(register_index)); 1070 __ str(r0, register_location(register_index));
1068 } 1071 }
1069 1072
1070 1073
1071 bool RegExpMacroAssemblerARM::Succeed() { 1074 bool RegExpMacroAssemblerSH4::Succeed() {
1072 __ jmp(&success_label_); 1075 __ jmp(&success_label_);
1073 return global(); 1076 return global();
1074 } 1077 }
1075 1078
1076 1079
1077 void RegExpMacroAssemblerARM::WriteCurrentPositionToRegister(int reg, 1080 void RegExpMacroAssemblerSH4::WriteCurrentPositionToRegister(int reg,
1078 int cp_offset) { 1081 int cp_offset) {
1079 if (cp_offset == 0) { 1082 if (cp_offset == 0) {
1080 __ str(current_input_offset(), register_location(reg)); 1083 __ str(current_input_offset(), register_location(reg));
1081 } else { 1084 } else {
1082 __ add(r0, current_input_offset(), Operand(cp_offset * char_size())); 1085 __ add(r0, current_input_offset(), Operand(cp_offset * char_size()));
1083 __ str(r0, register_location(reg)); 1086 __ str(r0, register_location(reg));
1084 } 1087 }
1085 } 1088 }
1086 1089
1087 1090
1088 void RegExpMacroAssemblerARM::ClearRegisters(int reg_from, int reg_to) { 1091 void RegExpMacroAssemblerSH4::ClearRegisters(int reg_from, int reg_to) {
1089 ASSERT(reg_from <= reg_to); 1092 ASSERT(reg_from <= reg_to);
1090 __ ldr(r0, MemOperand(frame_pointer(), kInputStartMinusOne)); 1093 __ ldr(r0, MemOperand(frame_pointer(), kInputStartMinusOne));
1091 for (int reg = reg_from; reg <= reg_to; reg++) { 1094 for (int reg = reg_from; reg <= reg_to; reg++) {
1092 __ str(r0, register_location(reg)); 1095 __ str(r0, register_location(reg));
1093 } 1096 }
1094 } 1097 }
1095 1098
1096 1099
1097 void RegExpMacroAssemblerARM::WriteStackPointerToRegister(int reg) { 1100 void RegExpMacroAssemblerSH4::WriteStackPointerToRegister(int reg) {
1098 __ ldr(r1, MemOperand(frame_pointer(), kStackHighEnd)); 1101 __ ldr(r1, MemOperand(frame_pointer(), kStackHighEnd));
1099 __ sub(r0, backtrack_stackpointer(), r1); 1102 __ sub(r0, backtrack_stackpointer(), r1);
1100 __ str(r0, register_location(reg)); 1103 __ str(r0, register_location(reg));
1101 } 1104 }
1102 1105
1103 1106
1104 // Private methods: 1107 // Private methods:
1105 1108
1106 void RegExpMacroAssemblerARM::CallCheckStackGuardState(Register scratch) { 1109 void RegExpMacroAssemblerSH4::CallCheckStackGuardState(Register scratch) {
1107 static const int num_arguments = 3; 1110 static const int num_arguments = 3;
1111 // We do not have to save r5 as this value is then putted back by
1112 // CallCFunctionUsingStub (from the CodeObject)
1113 __ Push(r4, r6, r7);
1108 __ PrepareCallCFunction(num_arguments, scratch); 1114 __ PrepareCallCFunction(num_arguments, scratch);
1109 // RegExp code frame pointer. 1115 // RegExp code frame pointer.
1110 __ mov(r2, frame_pointer()); 1116 __ mov(r6, frame_pointer());
1111 // Code* of self. 1117 // Code* of self.
1112 __ mov(r1, Operand(masm_->CodeObject())); 1118 __ mov(r5, Operand(masm_->CodeObject()));
1113 // r0 becomes return address pointer. 1119 // r0 becomes return address pointer.
1114 ExternalReference stack_guard_check = 1120 ExternalReference stack_guard_check =
1115 ExternalReference::re_check_stack_guard_state(masm_->isolate()); 1121 ExternalReference::re_check_stack_guard_state(masm_->isolate());
1116 CallCFunctionUsingStub(stack_guard_check, num_arguments); 1122 CallCFunctionUsingStub(stack_guard_check, num_arguments);
1123 __ Pop(r4, r6, r7);
1117 } 1124 }
1118 1125
1119 1126
1120 // Helper function for reading a value out of a stack frame. 1127 // Helper function for reading a value out of a stack frame.
1121 template <typename T> 1128 template <typename T>
1122 static T& frame_entry(Address re_frame, int frame_offset) { 1129 static T& frame_entry(Address re_frame, int frame_offset) {
1123 return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset)); 1130 return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset));
1124 } 1131 }
1125 1132
1126 1133
1127 int RegExpMacroAssemblerARM::CheckStackGuardState(Address* return_address, 1134 int RegExpMacroAssemblerSH4::CheckStackGuardState(Address* return_address,
1128 Code* re_code, 1135 Code* re_code,
1129 Address re_frame) { 1136 Address re_frame) {
1130 Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate); 1137 Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
1131 ASSERT(isolate == Isolate::Current()); 1138 ASSERT(isolate == Isolate::Current());
1132 if (isolate->stack_guard()->IsStackOverflow()) { 1139 if (isolate->stack_guard()->IsStackOverflow()) {
1133 isolate->StackOverflow(); 1140 isolate->StackOverflow();
1134 return EXCEPTION; 1141 return EXCEPTION;
1135 } 1142 }
1136 1143
1137 // If not real stack overflow the stack guard was used to interrupt 1144 // If not real stack overflow the stack guard was used to interrupt
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1216 // Subject string might have been a ConsString that underwent 1223 // Subject string might have been a ConsString that underwent
1217 // short-circuiting during GC. That will not change start_address but 1224 // short-circuiting during GC. That will not change start_address but
1218 // will change pointer inside the subject handle. 1225 // will change pointer inside the subject handle.
1219 frame_entry<const String*>(re_frame, kInputString) = *subject; 1226 frame_entry<const String*>(re_frame, kInputString) = *subject;
1220 } 1227 }
1221 1228
1222 return 0; 1229 return 0;
1223 } 1230 }
1224 1231
1225 1232
1226 MemOperand RegExpMacroAssemblerARM::register_location(int register_index) { 1233 MemOperand RegExpMacroAssemblerSH4::register_location(int register_index) {
1227 ASSERT(register_index < (1<<30)); 1234 ASSERT(register_index < (1<<30));
1228 if (num_registers_ <= register_index) { 1235 if (num_registers_ <= register_index) {
1229 num_registers_ = register_index + 1; 1236 num_registers_ = register_index + 1;
1230 } 1237 }
1231 return MemOperand(frame_pointer(), 1238 return MemOperand(frame_pointer(),
1232 kRegisterZero - register_index * kPointerSize); 1239 kRegisterZero - register_index * kPointerSize);
1233 } 1240 }
1234 1241
1235 1242
1236 void RegExpMacroAssemblerARM::CheckPosition(int cp_offset, 1243 void RegExpMacroAssemblerSH4::CheckPosition(int cp_offset,
1237 Label* on_outside_input) { 1244 Label* on_outside_input) {
1238 __ cmp(current_input_offset(), Operand(-cp_offset * char_size())); 1245 __ cmpge(current_input_offset(), Operand(-cp_offset * char_size()));
1239 BranchOrBacktrack(ge, on_outside_input); 1246 BranchOrBacktrack(eq, on_outside_input);
1240 } 1247 }
1241 1248
1242 1249
1243 void RegExpMacroAssemblerARM::BranchOrBacktrack(Condition condition, 1250 void RegExpMacroAssemblerSH4::BranchOrBacktrack(Condition condition,
1244 Label* to) { 1251 Label* to) {
1245 if (condition == al) { // Unconditional. 1252 if (condition == al) { // Unconditional.
1246 if (to == NULL) { 1253 if (to == NULL) {
1247 Backtrack(); 1254 Backtrack();
1248 return; 1255 return;
1249 } 1256 }
1250 __ jmp(to); 1257 __ jmp(to);
1251 return; 1258 return;
1252 } 1259 }
1253 if (to == NULL) { 1260 if (to == NULL) {
1254 __ b(condition, &backtrack_label_); 1261 __ b(condition, &backtrack_label_);
1255 return; 1262 return;
1256 } 1263 }
1257 __ b(condition, to); 1264 __ b(condition, to);
1258 } 1265 }
1259 1266
1260 1267
1261 void RegExpMacroAssemblerARM::SafeCall(Label* to, Condition cond) { 1268 void RegExpMacroAssemblerSH4::SafeCall(Label* to, Condition cond) {
1262 __ bl(to, cond); 1269 Label skip;
1270 ASSERT(cond == eq || cond == ne);
1271 __ b(NegateCondition(cond), &skip, Label::kNear);
1272 __ jsr(to);
1273 __ bind(&skip);
1263 } 1274 }
1264 1275
1265 1276
1266 void RegExpMacroAssemblerARM::SafeReturn() { 1277 void RegExpMacroAssemblerSH4::SafeReturn() {
1267 __ pop(lr); 1278 __ pop(ip);
1268 __ add(pc, lr, Operand(masm_->CodeObject())); 1279 __ add(ip, ip, Operand(masm_->CodeObject()));
1280 __ mov(pr, ip);
1281 __ rts();
1269 } 1282 }
1270 1283
1271 1284
1272 void RegExpMacroAssemblerARM::SafeCallTarget(Label* name) { 1285 void RegExpMacroAssemblerSH4::SafeCallTarget(Label* name) {
1273 __ bind(name); 1286 __ bind(name);
1274 __ sub(lr, lr, Operand(masm_->CodeObject())); 1287 __ mov(ip, pr);
1288 __ sub(ip, ip, Operand(masm_->CodeObject()));
1289 __ mov(pr, ip);
1275 __ push(lr); 1290 __ push(lr);
1276 } 1291 }
1277 1292
1278 1293
1279 void RegExpMacroAssemblerARM::Push(Register source) { 1294 void RegExpMacroAssemblerSH4::Push(Register source) {
1280 ASSERT(!source.is(backtrack_stackpointer())); 1295 ASSERT(!source.is(backtrack_stackpointer()));
1281 __ str(source, 1296 __ add(backtrack_stackpointer(), backtrack_stackpointer(),
1282 MemOperand(backtrack_stackpointer(), kPointerSize, NegPreIndex)); 1297 Operand(-kPointerSize));
1298 __ str(source, MemOperand(backtrack_stackpointer()));
1283 } 1299 }
1284 1300
1285 1301
1286 void RegExpMacroAssemblerARM::Pop(Register target) { 1302 void RegExpMacroAssemblerSH4::Pop(Register target) {
1287 ASSERT(!target.is(backtrack_stackpointer())); 1303 ASSERT(!target.is(backtrack_stackpointer()));
1288 __ ldr(target, 1304 __ ldr(target,
1289 MemOperand(backtrack_stackpointer(), kPointerSize, PostIndex)); 1305 MemOperand(backtrack_stackpointer(), kPointerSize, PostIndex));
1290 } 1306 }
1291 1307
1292 1308
1293 void RegExpMacroAssemblerARM::CheckPreemption() { 1309 void RegExpMacroAssemblerSH4::CheckPreemption() {
1294 // Check for preemption. 1310 // Check for preemption.
1295 ExternalReference stack_limit = 1311 ExternalReference stack_limit =
1296 ExternalReference::address_of_stack_limit(masm_->isolate()); 1312 ExternalReference::address_of_stack_limit(masm_->isolate());
1297 __ mov(r0, Operand(stack_limit)); 1313 __ mov(r0, Operand(stack_limit));
1298 __ ldr(r0, MemOperand(r0)); 1314 __ ldr(r0, MemOperand(r0));
1299 __ cmp(sp, r0); 1315 __ cmphi(sp, r0);
1300 SafeCall(&check_preempt_label_, ls); 1316 SafeCall(&check_preempt_label_, ne);
1301 } 1317 }
1302 1318
1303 1319
1304 void RegExpMacroAssemblerARM::CheckStackLimit() { 1320 void RegExpMacroAssemblerSH4::CheckStackLimit() {
1305 ExternalReference stack_limit = 1321 ExternalReference stack_limit =
1306 ExternalReference::address_of_regexp_stack_limit(masm_->isolate()); 1322 ExternalReference::address_of_regexp_stack_limit(masm_->isolate());
1307 __ mov(r0, Operand(stack_limit)); 1323 __ mov(r0, Operand(stack_limit));
1308 __ ldr(r0, MemOperand(r0)); 1324 __ ldr(r0, MemOperand(r0));
1309 __ cmp(backtrack_stackpointer(), Operand(r0)); 1325 __ cmphi(backtrack_stackpointer(), r0);
1310 SafeCall(&stack_overflow_label_, ls); 1326 SafeCall(&stack_overflow_label_, ne);
1311 } 1327 }
1312 1328
1313 1329
1314 void RegExpMacroAssemblerARM::EmitBacktrackConstantPool() { 1330 void RegExpMacroAssemblerSH4::CallCFunctionUsingStub(
1315 __ CheckConstPool(false, false);
1316 Assembler::BlockConstPoolScope block_const_pool(masm_);
1317 backtrack_constant_pool_offset_ = masm_->pc_offset();
1318 for (int i = 0; i < kBacktrackConstantPoolSize; i++) {
1319 __ emit(0);
1320 }
1321
1322 backtrack_constant_pool_capacity_ = kBacktrackConstantPoolSize;
1323 }
1324
1325
1326 int RegExpMacroAssemblerARM::GetBacktrackConstantPoolEntry() {
1327 while (backtrack_constant_pool_capacity_ > 0) {
1328 int offset = backtrack_constant_pool_offset_;
1329 backtrack_constant_pool_offset_ += kPointerSize;
1330 backtrack_constant_pool_capacity_--;
1331 if (masm_->pc_offset() - offset < 2 * KB) {
1332 return offset;
1333 }
1334 }
1335 Label new_pool_skip;
1336 __ jmp(&new_pool_skip);
1337 EmitBacktrackConstantPool();
1338 __ bind(&new_pool_skip);
1339 int offset = backtrack_constant_pool_offset_;
1340 backtrack_constant_pool_offset_ += kPointerSize;
1341 backtrack_constant_pool_capacity_--;
1342 return offset;
1343 }
1344
1345
1346 void RegExpMacroAssemblerARM::CallCFunctionUsingStub(
1347 ExternalReference function, 1331 ExternalReference function,
1348 int num_arguments) { 1332 int num_arguments) {
1349 // Must pass all arguments in registers. The stub pushes on the stack. 1333 // Must pass all arguments in registers. The stub pushes on the stack.
1350 ASSERT(num_arguments <= 4); 1334 ASSERT(num_arguments <= 4);
1351 __ mov(code_pointer(), Operand(function)); 1335 __ mov(r1, Operand(function));
1352 RegExpCEntryStub stub; 1336 RegExpCEntryStub stub;
1353 __ CallStub(&stub); 1337 __ CallStub(&stub);
1354 if (OS::ActivationFrameAlignment() != 0) {
1355 __ ldr(sp, MemOperand(sp, 0));
1356 }
1357 __ mov(code_pointer(), Operand(masm_->CodeObject())); 1338 __ mov(code_pointer(), Operand(masm_->CodeObject()));
1358 } 1339 }
1359 1340
1360 1341
1361 bool RegExpMacroAssemblerARM::CanReadUnaligned() { 1342 void RegExpMacroAssemblerSH4::LoadCurrentCharacterUnchecked(int cp_offset,
1362 return CpuFeatures::IsSupported(UNALIGNED_ACCESSES) && !slow_safe();
1363 }
1364
1365
1366 void RegExpMacroAssemblerARM::LoadCurrentCharacterUnchecked(int cp_offset,
1367 int characters) { 1343 int characters) {
1368 Register offset = current_input_offset(); 1344 Register offset = current_input_offset();
1369 if (cp_offset != 0) { 1345 if (cp_offset != 0) {
1370 // r4 is not being used to store the capture start index at this point. 1346 // r4 is not being used to store the capture start index at this point.
1371 __ add(r4, current_input_offset(), Operand(cp_offset * char_size())); 1347 __ add(r4, current_input_offset(), Operand(cp_offset * char_size()));
1372 offset = r4; 1348 offset = r4;
1373 } 1349 }
1374 // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU 1350 // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU
1375 // and the operating system running on the target allow it. 1351 // and the operating system running on the target allow it.
1376 // If unaligned load/stores are not supported then this function must only 1352 // If unaligned load/stores are not supported then this function must only
1377 // be used to load a single character at a time. 1353 // be used to load a single character at a time.
1378 if (!CanReadUnaligned()) { 1354 #if !V8_TARGET_CAN_READ_UNALIGNED
1379 ASSERT(characters == 1); 1355 ASSERT(characters == 1);
1380 } 1356 #endif
1381 1357
1382 if (mode_ == ASCII) { 1358 if (mode_ == ASCII) {
1383 if (characters == 4) { 1359 if (characters == 4) {
1384 __ ldr(current_character(), MemOperand(end_of_input_address(), offset)); 1360 __ ldr(current_character(), MemOperand(end_of_input_address(), offset));
1385 } else if (characters == 2) { 1361 } else if (characters == 2) {
1386 __ ldrh(current_character(), MemOperand(end_of_input_address(), offset)); 1362 __ ldrh(current_character(), MemOperand(end_of_input_address(), offset));
1387 } else { 1363 } else {
1388 ASSERT(characters == 1); 1364 ASSERT(characters == 1);
1389 __ ldrb(current_character(), MemOperand(end_of_input_address(), offset)); 1365 __ ldrb(current_character(), MemOperand(end_of_input_address(), offset));
1390 } 1366 }
1391 } else { 1367 } else {
1392 ASSERT(mode_ == UC16); 1368 ASSERT(mode_ == UC16);
1393 if (characters == 2) { 1369 if (characters == 2) {
1394 __ ldr(current_character(), MemOperand(end_of_input_address(), offset)); 1370 __ ldr(current_character(), MemOperand(end_of_input_address(), offset));
1395 } else { 1371 } else {
1396 ASSERT(characters == 1); 1372 ASSERT(characters == 1);
1397 __ ldrh(current_character(), MemOperand(end_of_input_address(), offset)); 1373 __ ldrh(current_character(), MemOperand(end_of_input_address(), offset));
1398 } 1374 }
1399 } 1375 }
1400 } 1376 }
1401 1377
1402 1378
1403 void RegExpCEntryStub::Generate(MacroAssembler* masm_) { 1379 void RegExpCEntryStub::Generate(MacroAssembler* masm_) {
1404 int stack_alignment = OS::ActivationFrameAlignment(); 1380 // TODO(STM): do we have to align the stack arguments ?
1405 if (stack_alignment < kPointerSize) stack_alignment = kPointerSize; 1381 // // Decrement it by kPointerSize to make room for pushing and poping pr
1406 // Stack is already aligned for call, so decrement by alignment 1382 // int stack_alignment = OS::ActivationFrameAlignment() - kPointerSize;
1407 // to make room for storing the link register. 1383 // // Stack is already aligned for call, so decrement by alignment
1408 __ str(lr, MemOperand(sp, stack_alignment, NegPreIndex)); 1384 // // to make room for storing the link register.
1409 __ mov(r0, sp); 1385 __ push(pr);
1410 __ Call(r5); 1386 // The first argument should be sp
1411 __ ldr(pc, MemOperand(sp, stack_alignment, PostIndex)); 1387 __ mov(r4, sp);
1388 __ jsr(r1);
1389 __ pop(pr);
1390 __ rts();
1412 } 1391 }
1413 1392
1414 #undef __ 1393 #undef __
1415 1394
1416 #endif // V8_INTERPRETED_REGEXP 1395 #endif // V8_INTERPRETED_REGEXP
1417 1396
1418 }} // namespace v8::internal 1397 }} // namespace v8::internal
1419 1398
1420 #endif // V8_TARGET_ARCH_ARM 1399 #endif // V8_TARGET_ARCH_SH4
OLDNEW
« no previous file with comments | « src/sh4/regexp-macro-assembler-sh4.h ('k') | src/sh4/simulator-sh4.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698