1// 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"
13#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
1229
1230void RegExpMacroAssemblerS390::LoadCurrentCharacterUnchecked(int cp_offset,
1231                                                             int characters) {
1232  if (mode_ == LATIN1) {
1233    // using load reverse for big-endian platforms
1234    if (characters == 4) {
1235#if V8_TARGET_LITTLE_ENDIAN
1236      __ LoadlW(current_character(),
1237                MemOperand(current_input_offset(), end_of_input_address(),
1238                           cp_offset * char_size()));
1239#else
1240      __ LoadLogicalReversedWordP(current_character(),
1241                MemOperand(current_input_offset(), end_of_input_address(),
1242                           cp_offset * char_size()));
1243#endif
1244    } else if (characters == 2) {
1245#if V8_TARGET_LITTLE_ENDIAN
1246      __ LoadLogicalHalfWordP(current_character(),
1247                MemOperand(current_input_offset(), end_of_input_address(),
1248                           cp_offset * char_size()));
1249#else
1250      __ LoadLogicalReversedHalfWordP(current_character(),
1251                MemOperand(current_input_offset(), end_of_input_address(),
1252                           cp_offset * char_size()));
1253#endif
1254    } else {
1255      DCHECK(characters == 1);
1256      __ LoadlB(current_character(),
1257                MemOperand(current_input_offset(), end_of_input_address(),
1258                           cp_offset * char_size()));
1259    }
1260  } else {
1261    DCHECK(mode_ == UC16);
1262    if (characters == 2) {
1263      __ LoadlW(current_character(),
1264                MemOperand(current_input_offset(), end_of_input_address(),
1265                           cp_offset * char_size()));
1266#if !V8_TARGET_LITTLE_ENDIAN
1267      // need to swap the order of the characters for big-endian platforms
1268      __ rll(current_character(), current_character(), Operand(16));
1269#endif
1270    } else {
1271      DCHECK(characters == 1);
1272      __ LoadLogicalHalfWordP(
1273          current_character(),
1274                MemOperand(current_input_offset(), end_of_input_address(),
1275                           cp_offset * char_size()));
1276    }
1277  }
1278}
1279
1280#undef __
1281
1282#endif  // V8_INTERPRETED_REGEXP
1283}  // namespace internal
1284}  // namespace v8
1285
1286#endif  // V8_TARGET_ARCH_S390
1287