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