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