11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/init/v8.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_S390 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h" 101cb0ef41Sopenharmony_ci#include "src/codegen/s390/assembler-s390-inl.h" 111cb0ef41Sopenharmony_ci#include "src/heap/factory.h" 121cb0ef41Sopenharmony_ci#include "src/logging/log.h" 131cb0ef41Sopenharmony_ci#include "src/objects/code-inl.h" 141cb0ef41Sopenharmony_ci#include "src/regexp/regexp-stack.h" 151cb0ef41Sopenharmony_ci#include "src/regexp/s390/regexp-macro-assembler-s390.h" 161cb0ef41Sopenharmony_ci#include "src/snapshot/embedded/embedded-data-inl.h" 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_cinamespace v8 { 191cb0ef41Sopenharmony_cinamespace internal { 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci/* 221cb0ef41Sopenharmony_ci * This assembler uses the following register assignment convention 231cb0ef41Sopenharmony_ci * - r6: Temporarily stores the index of capture start after a matching pass 241cb0ef41Sopenharmony_ci * for a global regexp. 251cb0ef41Sopenharmony_ci * - r7: Pointer to current Code object including heap object tag. 261cb0ef41Sopenharmony_ci * - r8: Current position in input, as negative offset from end of string. 271cb0ef41Sopenharmony_ci * Please notice that this is the byte offset, not the character offset! 281cb0ef41Sopenharmony_ci * - r9: Currently loaded character. Must be loaded using 291cb0ef41Sopenharmony_ci * LoadCurrentCharacter before using any of the dispatch methods. 301cb0ef41Sopenharmony_ci * - r13: Points to tip of backtrack stack 311cb0ef41Sopenharmony_ci * - r10: End of input (points to byte after last character in input). 321cb0ef41Sopenharmony_ci * - r11: Frame pointer. Used to access arguments, local variables and 331cb0ef41Sopenharmony_ci * RegExp registers. 341cb0ef41Sopenharmony_ci * - r12: IP register, used by assembler. Very volatile. 351cb0ef41Sopenharmony_ci * - r15/sp : Points to tip of C stack. 361cb0ef41Sopenharmony_ci * 371cb0ef41Sopenharmony_ci * The remaining registers are free for computations. 381cb0ef41Sopenharmony_ci * Each call to a public method should retain this convention. 391cb0ef41Sopenharmony_ci * 401cb0ef41Sopenharmony_ci * The stack will have the following structure 411cb0ef41Sopenharmony_ci * - fp[112] Address regexp (address of the JSRegExp object; unused in 421cb0ef41Sopenharmony_ci * native code, passed to match signature of 431cb0ef41Sopenharmony_ci * the interpreter) 441cb0ef41Sopenharmony_ci * - fp[108] Isolate* isolate (address of the current isolate) 451cb0ef41Sopenharmony_ci * - fp[104] direct_call (if 1, direct call from JavaScript code, 461cb0ef41Sopenharmony_ci * if 0, call through the runtime system). 471cb0ef41Sopenharmony_ci * - fp[100] stack_area_base (high end of the memory area to use as 481cb0ef41Sopenharmony_ci * backtracking stack). 491cb0ef41Sopenharmony_ci * - fp[96] capture array size (may fit multiple sets of matches) 501cb0ef41Sopenharmony_ci * - fp[0..96] zLinux ABI register saving area 511cb0ef41Sopenharmony_ci * --- sp when called --- 521cb0ef41Sopenharmony_ci * --- frame pointer ---- 531cb0ef41Sopenharmony_ci * - fp[-4] direct_call (if 1, direct call from JavaScript code, 541cb0ef41Sopenharmony_ci * if 0, call through the runtime system). 551cb0ef41Sopenharmony_ci * - fp[-8] stack_area_base (high end of the memory area to use as 561cb0ef41Sopenharmony_ci * backtracking stack). 571cb0ef41Sopenharmony_ci * - fp[-12] capture array size (may fit multiple sets of matches) 581cb0ef41Sopenharmony_ci * - fp[-16] int* capture_array (int[num_saved_registers_], for output). 591cb0ef41Sopenharmony_ci * - fp[-20] end of input (address of end of string). 601cb0ef41Sopenharmony_ci * - fp[-24] start of input (address of first character in string). 611cb0ef41Sopenharmony_ci * - fp[-28] start index (character index of start). 621cb0ef41Sopenharmony_ci * - fp[-32] void* input_string (location of a handle containing the string). 631cb0ef41Sopenharmony_ci * - fp[-36] success counter (only for global regexps to count matches). 641cb0ef41Sopenharmony_ci * - fp[-40] Offset of location before start of input (effectively character 651cb0ef41Sopenharmony_ci * string start - 1). Used to initialize capture registers to a 661cb0ef41Sopenharmony_ci * non-position. 671cb0ef41Sopenharmony_ci * - fp[-44] At start (if 1, we are starting at the start of the 681cb0ef41Sopenharmony_ci * string, otherwise 0) 691cb0ef41Sopenharmony_ci * - fp[-48] register 0 (Only positions must be stored in the first 701cb0ef41Sopenharmony_ci * - register 1 num_saved_registers_ registers) 711cb0ef41Sopenharmony_ci * - ... 721cb0ef41Sopenharmony_ci * - register num_registers-1 731cb0ef41Sopenharmony_ci * --- sp --- 741cb0ef41Sopenharmony_ci * 751cb0ef41Sopenharmony_ci * The first num_saved_registers_ registers are initialized to point to 761cb0ef41Sopenharmony_ci * "character -1" in the string (i.e., char_size() bytes before the first 771cb0ef41Sopenharmony_ci * character of the string). The remaining registers start out as garbage. 781cb0ef41Sopenharmony_ci * 791cb0ef41Sopenharmony_ci * The data up to the return address must be placed there by the calling 801cb0ef41Sopenharmony_ci * code and the remaining arguments are passed in registers, e.g. by calling the 811cb0ef41Sopenharmony_ci * code entry as cast to a function with the signature: 821cb0ef41Sopenharmony_ci * int (*match)(String input_string, 831cb0ef41Sopenharmony_ci * int start_index, 841cb0ef41Sopenharmony_ci * Address start, 851cb0ef41Sopenharmony_ci * Address end, 861cb0ef41Sopenharmony_ci * int* capture_output_array, 871cb0ef41Sopenharmony_ci * int num_capture_registers, 881cb0ef41Sopenharmony_ci * byte* stack_area_base, 891cb0ef41Sopenharmony_ci * bool direct_call = false, 901cb0ef41Sopenharmony_ci * Isolate* isolate, 911cb0ef41Sopenharmony_ci * Address regexp); 921cb0ef41Sopenharmony_ci * The call is performed by NativeRegExpMacroAssembler::Execute() 931cb0ef41Sopenharmony_ci * (in regexp-macro-assembler.cc) via the GeneratedCode wrapper. 941cb0ef41Sopenharmony_ci */ 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci#define __ ACCESS_MASM(masm_) 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ciconst int RegExpMacroAssemblerS390::kRegExpCodeSize; 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ciRegExpMacroAssemblerS390::RegExpMacroAssemblerS390(Isolate* isolate, Zone* zone, 1011cb0ef41Sopenharmony_ci Mode mode, 1021cb0ef41Sopenharmony_ci int registers_to_save) 1031cb0ef41Sopenharmony_ci : NativeRegExpMacroAssembler(isolate, zone), 1041cb0ef41Sopenharmony_ci masm_(std::make_unique<MacroAssembler>( 1051cb0ef41Sopenharmony_ci isolate, CodeObjectRequired::kYes, 1061cb0ef41Sopenharmony_ci NewAssemblerBuffer(kRegExpCodeSize))), 1071cb0ef41Sopenharmony_ci no_root_array_scope_(masm_.get()), 1081cb0ef41Sopenharmony_ci mode_(mode), 1091cb0ef41Sopenharmony_ci num_registers_(registers_to_save), 1101cb0ef41Sopenharmony_ci num_saved_registers_(registers_to_save), 1111cb0ef41Sopenharmony_ci entry_label_(), 1121cb0ef41Sopenharmony_ci start_label_(), 1131cb0ef41Sopenharmony_ci success_label_(), 1141cb0ef41Sopenharmony_ci backtrack_label_(), 1151cb0ef41Sopenharmony_ci exit_label_(), 1161cb0ef41Sopenharmony_ci internal_failure_label_() { 1171cb0ef41Sopenharmony_ci DCHECK_EQ(0, registers_to_save % 2); 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci __ b(&entry_label_); // We'll write the entry code later. 1201cb0ef41Sopenharmony_ci // If the code gets too big or corrupted, an internal exception will be 1211cb0ef41Sopenharmony_ci // raised, and we will exit right away. 1221cb0ef41Sopenharmony_ci __ bind(&internal_failure_label_); 1231cb0ef41Sopenharmony_ci __ mov(r2, Operand(FAILURE)); 1241cb0ef41Sopenharmony_ci __ Ret(); 1251cb0ef41Sopenharmony_ci __ bind(&start_label_); // And then continue from here. 1261cb0ef41Sopenharmony_ci} 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ciRegExpMacroAssemblerS390::~RegExpMacroAssemblerS390() { 1291cb0ef41Sopenharmony_ci // Unuse labels in case we throw away the assembler without calling GetCode. 1301cb0ef41Sopenharmony_ci entry_label_.Unuse(); 1311cb0ef41Sopenharmony_ci start_label_.Unuse(); 1321cb0ef41Sopenharmony_ci success_label_.Unuse(); 1331cb0ef41Sopenharmony_ci backtrack_label_.Unuse(); 1341cb0ef41Sopenharmony_ci exit_label_.Unuse(); 1351cb0ef41Sopenharmony_ci check_preempt_label_.Unuse(); 1361cb0ef41Sopenharmony_ci stack_overflow_label_.Unuse(); 1371cb0ef41Sopenharmony_ci internal_failure_label_.Unuse(); 1381cb0ef41Sopenharmony_ci fallback_label_.Unuse(); 1391cb0ef41Sopenharmony_ci} 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ciint RegExpMacroAssemblerS390::stack_limit_slack() { 1421cb0ef41Sopenharmony_ci return RegExpStack::kStackLimitSlack; 1431cb0ef41Sopenharmony_ci} 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::AdvanceCurrentPosition(int by) { 1461cb0ef41Sopenharmony_ci if (by != 0) { 1471cb0ef41Sopenharmony_ci __ AddS64(current_input_offset(), Operand(by * char_size())); 1481cb0ef41Sopenharmony_ci } 1491cb0ef41Sopenharmony_ci} 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::AdvanceRegister(int reg, int by) { 1521cb0ef41Sopenharmony_ci DCHECK_LE(0, reg); 1531cb0ef41Sopenharmony_ci DCHECK_GT(num_registers_, reg); 1541cb0ef41Sopenharmony_ci if (by != 0) { 1551cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(GENERAL_INSTR_EXT) && is_int8(by)) { 1561cb0ef41Sopenharmony_ci __ agsi(register_location(reg), Operand(by)); 1571cb0ef41Sopenharmony_ci } else { 1581cb0ef41Sopenharmony_ci __ LoadU64(r2, register_location(reg), r0); 1591cb0ef41Sopenharmony_ci __ mov(r0, Operand(by)); 1601cb0ef41Sopenharmony_ci __ agr(r2, r0); 1611cb0ef41Sopenharmony_ci __ StoreU64(r2, register_location(reg)); 1621cb0ef41Sopenharmony_ci } 1631cb0ef41Sopenharmony_ci } 1641cb0ef41Sopenharmony_ci} 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::Backtrack() { 1671cb0ef41Sopenharmony_ci CheckPreemption(); 1681cb0ef41Sopenharmony_ci if (has_backtrack_limit()) { 1691cb0ef41Sopenharmony_ci Label next; 1701cb0ef41Sopenharmony_ci __ LoadU64(r2, MemOperand(frame_pointer(), kBacktrackCount), r0); 1711cb0ef41Sopenharmony_ci __ AddS64(r2, r2, Operand(1)); 1721cb0ef41Sopenharmony_ci __ StoreU64(r2, MemOperand(frame_pointer(), kBacktrackCount), r0); 1731cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand(backtrack_limit())); 1741cb0ef41Sopenharmony_ci __ bne(&next); 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci // Backtrack limit exceeded. 1771cb0ef41Sopenharmony_ci if (can_fallback()) { 1781cb0ef41Sopenharmony_ci __ jmp(&fallback_label_); 1791cb0ef41Sopenharmony_ci } else { 1801cb0ef41Sopenharmony_ci // Can't fallback, so we treat it as a failed match. 1811cb0ef41Sopenharmony_ci Fail(); 1821cb0ef41Sopenharmony_ci } 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ci __ bind(&next); 1851cb0ef41Sopenharmony_ci } 1861cb0ef41Sopenharmony_ci // Pop Code offset from backtrack stack, add Code and jump to location. 1871cb0ef41Sopenharmony_ci Pop(r2); 1881cb0ef41Sopenharmony_ci __ AddS64(r2, code_pointer()); 1891cb0ef41Sopenharmony_ci __ b(r2); 1901cb0ef41Sopenharmony_ci} 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::Bind(Label* label) { __ bind(label); } 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckCharacter(uint32_t c, Label* on_equal) { 1951cb0ef41Sopenharmony_ci __ CmpU64(current_character(), Operand(c)); 1961cb0ef41Sopenharmony_ci BranchOrBacktrack(eq, on_equal); 1971cb0ef41Sopenharmony_ci} 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckCharacterGT(base::uc16 limit, 2001cb0ef41Sopenharmony_ci Label* on_greater) { 2011cb0ef41Sopenharmony_ci __ CmpU64(current_character(), Operand(limit)); 2021cb0ef41Sopenharmony_ci BranchOrBacktrack(gt, on_greater); 2031cb0ef41Sopenharmony_ci} 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckAtStart(int cp_offset, Label* on_at_start) { 2061cb0ef41Sopenharmony_ci __ LoadU64(r3, MemOperand(frame_pointer(), kStringStartMinusOne)); 2071cb0ef41Sopenharmony_ci __ AddS64(r2, current_input_offset(), 2081cb0ef41Sopenharmony_ci Operand(-char_size() + cp_offset * char_size())); 2091cb0ef41Sopenharmony_ci __ CmpS64(r2, r3); 2101cb0ef41Sopenharmony_ci BranchOrBacktrack(eq, on_at_start); 2111cb0ef41Sopenharmony_ci} 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckNotAtStart(int cp_offset, 2141cb0ef41Sopenharmony_ci Label* on_not_at_start) { 2151cb0ef41Sopenharmony_ci __ LoadU64(r3, MemOperand(frame_pointer(), kStringStartMinusOne)); 2161cb0ef41Sopenharmony_ci __ AddS64(r2, current_input_offset(), 2171cb0ef41Sopenharmony_ci Operand(-char_size() + cp_offset * char_size())); 2181cb0ef41Sopenharmony_ci __ CmpS64(r2, r3); 2191cb0ef41Sopenharmony_ci BranchOrBacktrack(ne, on_not_at_start); 2201cb0ef41Sopenharmony_ci} 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckCharacterLT(base::uc16 limit, 2231cb0ef41Sopenharmony_ci Label* on_less) { 2241cb0ef41Sopenharmony_ci __ CmpU64(current_character(), Operand(limit)); 2251cb0ef41Sopenharmony_ci BranchOrBacktrack(lt, on_less); 2261cb0ef41Sopenharmony_ci} 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckGreedyLoop(Label* on_equal) { 2291cb0ef41Sopenharmony_ci Label backtrack_non_equal; 2301cb0ef41Sopenharmony_ci __ CmpS64(current_input_offset(), MemOperand(backtrack_stackpointer(), 0)); 2311cb0ef41Sopenharmony_ci __ bne(&backtrack_non_equal); 2321cb0ef41Sopenharmony_ci __ AddS64(backtrack_stackpointer(), Operand(kSystemPointerSize)); 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_ci BranchOrBacktrack(al, on_equal); 2351cb0ef41Sopenharmony_ci __ bind(&backtrack_non_equal); 2361cb0ef41Sopenharmony_ci} 2371cb0ef41Sopenharmony_ci 2381cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckNotBackReferenceIgnoreCase( 2391cb0ef41Sopenharmony_ci int start_reg, bool read_backward, bool unicode, Label* on_no_match) { 2401cb0ef41Sopenharmony_ci Label fallthrough; 2411cb0ef41Sopenharmony_ci __ LoadU64(r2, register_location(start_reg)); // Index of start of 2421cb0ef41Sopenharmony_ci // capture 2431cb0ef41Sopenharmony_ci __ LoadU64(r3, register_location(start_reg + 1)); // Index of end 2441cb0ef41Sopenharmony_ci __ SubS64(r3, r3, r2); 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci // At this point, the capture registers are either both set or both cleared. 2471cb0ef41Sopenharmony_ci // If the capture length is zero, then the capture is either empty or cleared. 2481cb0ef41Sopenharmony_ci // Fall through in both cases. 2491cb0ef41Sopenharmony_ci __ beq(&fallthrough); 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_ci // Check that there are enough characters left in the input. 2521cb0ef41Sopenharmony_ci if (read_backward) { 2531cb0ef41Sopenharmony_ci __ LoadU64(r5, MemOperand(frame_pointer(), kStringStartMinusOne)); 2541cb0ef41Sopenharmony_ci __ AddS64(r5, r5, r3); 2551cb0ef41Sopenharmony_ci __ CmpS64(current_input_offset(), r5); 2561cb0ef41Sopenharmony_ci BranchOrBacktrack(le, on_no_match); 2571cb0ef41Sopenharmony_ci } else { 2581cb0ef41Sopenharmony_ci __ AddS64(r0, r3, current_input_offset()); 2591cb0ef41Sopenharmony_ci BranchOrBacktrack(gt, on_no_match); 2601cb0ef41Sopenharmony_ci } 2611cb0ef41Sopenharmony_ci 2621cb0ef41Sopenharmony_ci if (mode_ == LATIN1) { 2631cb0ef41Sopenharmony_ci Label success; 2641cb0ef41Sopenharmony_ci Label fail; 2651cb0ef41Sopenharmony_ci Label loop_check; 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci // r2 - offset of start of capture 2681cb0ef41Sopenharmony_ci // r3 - length of capture 2691cb0ef41Sopenharmony_ci __ AddS64(r2, end_of_input_address()); 2701cb0ef41Sopenharmony_ci __ AddS64(r4, current_input_offset(), end_of_input_address()); 2711cb0ef41Sopenharmony_ci if (read_backward) { 2721cb0ef41Sopenharmony_ci __ SubS64(r4, r4, r3); // Offset by length when matching backwards. 2731cb0ef41Sopenharmony_ci } 2741cb0ef41Sopenharmony_ci __ mov(r1, Operand::Zero()); 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_ci // r1 - Loop index 2771cb0ef41Sopenharmony_ci // r2 - Address of start of capture. 2781cb0ef41Sopenharmony_ci // r4 - Address of current input position. 2791cb0ef41Sopenharmony_ci 2801cb0ef41Sopenharmony_ci Label loop; 2811cb0ef41Sopenharmony_ci __ bind(&loop); 2821cb0ef41Sopenharmony_ci __ LoadU8(r5, MemOperand(r2, r1)); 2831cb0ef41Sopenharmony_ci __ LoadU8(r6, MemOperand(r4, r1)); 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci __ CmpS64(r6, r5); 2861cb0ef41Sopenharmony_ci __ beq(&loop_check); 2871cb0ef41Sopenharmony_ci 2881cb0ef41Sopenharmony_ci // Mismatch, try case-insensitive match (converting letters to lower-case). 2891cb0ef41Sopenharmony_ci __ Or(r5, Operand(0x20)); // Convert capture character to lower-case. 2901cb0ef41Sopenharmony_ci __ Or(r6, Operand(0x20)); // Also convert input character. 2911cb0ef41Sopenharmony_ci __ CmpS64(r6, r5); 2921cb0ef41Sopenharmony_ci __ bne(&fail); 2931cb0ef41Sopenharmony_ci __ SubS64(r5, Operand('a')); 2941cb0ef41Sopenharmony_ci __ CmpU64(r5, Operand('z' - 'a')); // Is r5 a lowercase letter? 2951cb0ef41Sopenharmony_ci __ ble(&loop_check); // In range 'a'-'z'. 2961cb0ef41Sopenharmony_ci // Latin-1: Check for values in range [224,254] but not 247. 2971cb0ef41Sopenharmony_ci __ SubS64(r5, Operand(224 - 'a')); 2981cb0ef41Sopenharmony_ci __ CmpU64(r5, Operand(254 - 224)); 2991cb0ef41Sopenharmony_ci __ bgt(&fail); // Weren't Latin-1 letters. 3001cb0ef41Sopenharmony_ci __ CmpU64(r5, Operand(247 - 224)); // Check for 247. 3011cb0ef41Sopenharmony_ci __ beq(&fail); 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_ci __ bind(&loop_check); 3041cb0ef41Sopenharmony_ci __ la(r1, MemOperand(r1, char_size())); 3051cb0ef41Sopenharmony_ci __ CmpS64(r1, r3); 3061cb0ef41Sopenharmony_ci __ blt(&loop); 3071cb0ef41Sopenharmony_ci __ b(&success); 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ci __ bind(&fail); 3101cb0ef41Sopenharmony_ci BranchOrBacktrack(al, on_no_match); 3111cb0ef41Sopenharmony_ci 3121cb0ef41Sopenharmony_ci __ bind(&success); 3131cb0ef41Sopenharmony_ci // Compute new value of character position after the matched part. 3141cb0ef41Sopenharmony_ci __ SubS64(current_input_offset(), r4, end_of_input_address()); 3151cb0ef41Sopenharmony_ci if (read_backward) { 3161cb0ef41Sopenharmony_ci __ LoadU64(r2, 3171cb0ef41Sopenharmony_ci register_location(start_reg)); // Index of start of capture 3181cb0ef41Sopenharmony_ci __ LoadU64(r3, 3191cb0ef41Sopenharmony_ci register_location(start_reg + 1)); // Index of end of capture 3201cb0ef41Sopenharmony_ci __ AddS64(current_input_offset(), current_input_offset(), r2); 3211cb0ef41Sopenharmony_ci __ SubS64(current_input_offset(), current_input_offset(), r3); 3221cb0ef41Sopenharmony_ci } 3231cb0ef41Sopenharmony_ci __ AddS64(current_input_offset(), r1); 3241cb0ef41Sopenharmony_ci } else { 3251cb0ef41Sopenharmony_ci DCHECK(mode_ == UC16); 3261cb0ef41Sopenharmony_ci int argument_count = 4; 3271cb0ef41Sopenharmony_ci __ PrepareCallCFunction(argument_count, r4); 3281cb0ef41Sopenharmony_ci 3291cb0ef41Sopenharmony_ci // r2 - offset of start of capture 3301cb0ef41Sopenharmony_ci // r3 - length of capture 3311cb0ef41Sopenharmony_ci 3321cb0ef41Sopenharmony_ci // Put arguments into arguments registers. 3331cb0ef41Sopenharmony_ci // Parameters are 3341cb0ef41Sopenharmony_ci // r2: Address byte_offset1 - Address captured substring's start. 3351cb0ef41Sopenharmony_ci // r3: Address byte_offset2 - Address of current character position. 3361cb0ef41Sopenharmony_ci // r4: size_t byte_length - length of capture in bytes(!) 3371cb0ef41Sopenharmony_ci // r5: Isolate* isolate. 3381cb0ef41Sopenharmony_ci 3391cb0ef41Sopenharmony_ci // Address of start of capture. 3401cb0ef41Sopenharmony_ci __ AddS64(r2, end_of_input_address()); 3411cb0ef41Sopenharmony_ci // Length of capture. 3421cb0ef41Sopenharmony_ci __ mov(r4, r3); 3431cb0ef41Sopenharmony_ci // Save length in callee-save register for use on return. 3441cb0ef41Sopenharmony_ci __ mov(r6, r3); 3451cb0ef41Sopenharmony_ci // Address of current input position. 3461cb0ef41Sopenharmony_ci __ AddS64(r3, current_input_offset(), end_of_input_address()); 3471cb0ef41Sopenharmony_ci if (read_backward) { 3481cb0ef41Sopenharmony_ci __ SubS64(r3, r3, r6); 3491cb0ef41Sopenharmony_ci } 3501cb0ef41Sopenharmony_ci// Isolate. 3511cb0ef41Sopenharmony_ci __ mov(r5, Operand(ExternalReference::isolate_address(isolate()))); 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci { 3541cb0ef41Sopenharmony_ci AllowExternalCallThatCantCauseGC scope(masm_.get()); 3551cb0ef41Sopenharmony_ci ExternalReference function = 3561cb0ef41Sopenharmony_ci unicode 3571cb0ef41Sopenharmony_ci ? ExternalReference::re_case_insensitive_compare_unicode() 3581cb0ef41Sopenharmony_ci : ExternalReference::re_case_insensitive_compare_non_unicode(); 3591cb0ef41Sopenharmony_ci __ CallCFunction(function, argument_count); 3601cb0ef41Sopenharmony_ci } 3611cb0ef41Sopenharmony_ci 3621cb0ef41Sopenharmony_ci // Check if function returned non-zero for success or zero for failure. 3631cb0ef41Sopenharmony_ci __ CmpS64(r2, Operand::Zero()); 3641cb0ef41Sopenharmony_ci BranchOrBacktrack(eq, on_no_match); 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_ci // On success, advance position by length of capture. 3671cb0ef41Sopenharmony_ci if (read_backward) { 3681cb0ef41Sopenharmony_ci __ SubS64(current_input_offset(), current_input_offset(), r6); 3691cb0ef41Sopenharmony_ci } else { 3701cb0ef41Sopenharmony_ci __ AddS64(current_input_offset(), current_input_offset(), r6); 3711cb0ef41Sopenharmony_ci } 3721cb0ef41Sopenharmony_ci } 3731cb0ef41Sopenharmony_ci 3741cb0ef41Sopenharmony_ci __ bind(&fallthrough); 3751cb0ef41Sopenharmony_ci} 3761cb0ef41Sopenharmony_ci 3771cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckNotBackReference(int start_reg, 3781cb0ef41Sopenharmony_ci bool read_backward, 3791cb0ef41Sopenharmony_ci Label* on_no_match) { 3801cb0ef41Sopenharmony_ci Label fallthrough; 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_ci // Find length of back-referenced capture. 3831cb0ef41Sopenharmony_ci __ LoadU64(r2, register_location(start_reg)); 3841cb0ef41Sopenharmony_ci __ LoadU64(r3, register_location(start_reg + 1)); 3851cb0ef41Sopenharmony_ci __ SubS64(r3, r3, r2); // Length to check. 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_ci // At this point, the capture registers are either both set or both cleared. 3881cb0ef41Sopenharmony_ci // If the capture length is zero, then the capture is either empty or cleared. 3891cb0ef41Sopenharmony_ci // Fall through in both cases. 3901cb0ef41Sopenharmony_ci __ beq(&fallthrough); 3911cb0ef41Sopenharmony_ci 3921cb0ef41Sopenharmony_ci // Check that there are enough characters left in the input. 3931cb0ef41Sopenharmony_ci if (read_backward) { 3941cb0ef41Sopenharmony_ci __ LoadU64(r5, MemOperand(frame_pointer(), kStringStartMinusOne)); 3951cb0ef41Sopenharmony_ci __ AddS64(r5, r5, r3); 3961cb0ef41Sopenharmony_ci __ CmpS64(current_input_offset(), r5); 3971cb0ef41Sopenharmony_ci BranchOrBacktrack(le, on_no_match); 3981cb0ef41Sopenharmony_ci } else { 3991cb0ef41Sopenharmony_ci __ AddS64(r0, r3, current_input_offset()); 4001cb0ef41Sopenharmony_ci BranchOrBacktrack(gt, on_no_match, cr0); 4011cb0ef41Sopenharmony_ci } 4021cb0ef41Sopenharmony_ci 4031cb0ef41Sopenharmony_ci // r2 - offset of start of capture 4041cb0ef41Sopenharmony_ci // r3 - length of capture 4051cb0ef41Sopenharmony_ci __ la(r2, MemOperand(r2, end_of_input_address())); 4061cb0ef41Sopenharmony_ci __ la(r4, MemOperand(current_input_offset(), end_of_input_address())); 4071cb0ef41Sopenharmony_ci if (read_backward) { 4081cb0ef41Sopenharmony_ci __ SubS64(r4, r4, r3); // Offset by length when matching backwards. 4091cb0ef41Sopenharmony_ci } 4101cb0ef41Sopenharmony_ci __ mov(r1, Operand::Zero()); 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_ci Label loop; 4131cb0ef41Sopenharmony_ci __ bind(&loop); 4141cb0ef41Sopenharmony_ci if (mode_ == LATIN1) { 4151cb0ef41Sopenharmony_ci __ LoadU8(r5, MemOperand(r2, r1)); 4161cb0ef41Sopenharmony_ci __ LoadU8(r6, MemOperand(r4, r1)); 4171cb0ef41Sopenharmony_ci } else { 4181cb0ef41Sopenharmony_ci DCHECK(mode_ == UC16); 4191cb0ef41Sopenharmony_ci __ LoadU16(r5, MemOperand(r2, r1)); 4201cb0ef41Sopenharmony_ci __ LoadU16(r6, MemOperand(r4, r1)); 4211cb0ef41Sopenharmony_ci } 4221cb0ef41Sopenharmony_ci __ la(r1, MemOperand(r1, char_size())); 4231cb0ef41Sopenharmony_ci __ CmpS64(r5, r6); 4241cb0ef41Sopenharmony_ci BranchOrBacktrack(ne, on_no_match); 4251cb0ef41Sopenharmony_ci __ CmpS64(r1, r3); 4261cb0ef41Sopenharmony_ci __ blt(&loop); 4271cb0ef41Sopenharmony_ci 4281cb0ef41Sopenharmony_ci // Move current character position to position after match. 4291cb0ef41Sopenharmony_ci __ SubS64(current_input_offset(), r4, end_of_input_address()); 4301cb0ef41Sopenharmony_ci if (read_backward) { 4311cb0ef41Sopenharmony_ci __ LoadU64(r2, register_location(start_reg)); // Index of start of capture 4321cb0ef41Sopenharmony_ci __ LoadU64(r3, 4331cb0ef41Sopenharmony_ci register_location(start_reg + 1)); // Index of end of capture 4341cb0ef41Sopenharmony_ci __ AddS64(current_input_offset(), current_input_offset(), r2); 4351cb0ef41Sopenharmony_ci __ SubS64(current_input_offset(), current_input_offset(), r3); 4361cb0ef41Sopenharmony_ci } 4371cb0ef41Sopenharmony_ci __ AddS64(current_input_offset(), r1); 4381cb0ef41Sopenharmony_ci 4391cb0ef41Sopenharmony_ci __ bind(&fallthrough); 4401cb0ef41Sopenharmony_ci} 4411cb0ef41Sopenharmony_ci 4421cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckNotCharacter(unsigned c, 4431cb0ef41Sopenharmony_ci Label* on_not_equal) { 4441cb0ef41Sopenharmony_ci __ CmpU64(current_character(), Operand(c)); 4451cb0ef41Sopenharmony_ci BranchOrBacktrack(ne, on_not_equal); 4461cb0ef41Sopenharmony_ci} 4471cb0ef41Sopenharmony_ci 4481cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckCharacterAfterAnd(uint32_t c, uint32_t mask, 4491cb0ef41Sopenharmony_ci Label* on_equal) { 4501cb0ef41Sopenharmony_ci __ AndP(r2, current_character(), Operand(mask)); 4511cb0ef41Sopenharmony_ci if (c != 0) { 4521cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand(c)); 4531cb0ef41Sopenharmony_ci } 4541cb0ef41Sopenharmony_ci BranchOrBacktrack(eq, on_equal); 4551cb0ef41Sopenharmony_ci} 4561cb0ef41Sopenharmony_ci 4571cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckNotCharacterAfterAnd(unsigned c, 4581cb0ef41Sopenharmony_ci unsigned mask, 4591cb0ef41Sopenharmony_ci Label* on_not_equal) { 4601cb0ef41Sopenharmony_ci __ AndP(r2, current_character(), Operand(mask)); 4611cb0ef41Sopenharmony_ci if (c != 0) { 4621cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand(c)); 4631cb0ef41Sopenharmony_ci } 4641cb0ef41Sopenharmony_ci BranchOrBacktrack(ne, on_not_equal); 4651cb0ef41Sopenharmony_ci} 4661cb0ef41Sopenharmony_ci 4671cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckNotCharacterAfterMinusAnd( 4681cb0ef41Sopenharmony_ci base::uc16 c, base::uc16 minus, base::uc16 mask, Label* on_not_equal) { 4691cb0ef41Sopenharmony_ci DCHECK_GT(String::kMaxUtf16CodeUnit, minus); 4701cb0ef41Sopenharmony_ci __ lay(r2, MemOperand(current_character(), -minus)); 4711cb0ef41Sopenharmony_ci __ And(r2, Operand(mask)); 4721cb0ef41Sopenharmony_ci if (c != 0) { 4731cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand(c)); 4741cb0ef41Sopenharmony_ci } 4751cb0ef41Sopenharmony_ci BranchOrBacktrack(ne, on_not_equal); 4761cb0ef41Sopenharmony_ci} 4771cb0ef41Sopenharmony_ci 4781cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckCharacterInRange(base::uc16 from, 4791cb0ef41Sopenharmony_ci base::uc16 to, 4801cb0ef41Sopenharmony_ci Label* on_in_range) { 4811cb0ef41Sopenharmony_ci __ lay(r2, MemOperand(current_character(), -from)); 4821cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand(to - from)); 4831cb0ef41Sopenharmony_ci BranchOrBacktrack(le, on_in_range); // Unsigned lower-or-same condition. 4841cb0ef41Sopenharmony_ci} 4851cb0ef41Sopenharmony_ci 4861cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckCharacterNotInRange( 4871cb0ef41Sopenharmony_ci base::uc16 from, base::uc16 to, Label* on_not_in_range) { 4881cb0ef41Sopenharmony_ci __ lay(r2, MemOperand(current_character(), -from)); 4891cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand(to - from)); 4901cb0ef41Sopenharmony_ci BranchOrBacktrack(gt, on_not_in_range); // Unsigned higher condition. 4911cb0ef41Sopenharmony_ci} 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CallIsCharacterInRangeArray( 4941cb0ef41Sopenharmony_ci const ZoneList<CharacterRange>* ranges) { 4951cb0ef41Sopenharmony_ci static const int kNumArguments = 3; 4961cb0ef41Sopenharmony_ci __ PrepareCallCFunction(kNumArguments, r0); 4971cb0ef41Sopenharmony_ci 4981cb0ef41Sopenharmony_ci __ mov(r2, current_character()); 4991cb0ef41Sopenharmony_ci __ mov(r3, Operand(GetOrAddRangeArray(ranges))); 5001cb0ef41Sopenharmony_ci __ mov(r4, Operand(ExternalReference::isolate_address(isolate()))); 5011cb0ef41Sopenharmony_ci 5021cb0ef41Sopenharmony_ci { 5031cb0ef41Sopenharmony_ci // We have a frame (set up in GetCode), but the assembler doesn't know. 5041cb0ef41Sopenharmony_ci FrameScope scope(masm_.get(), StackFrame::MANUAL); 5051cb0ef41Sopenharmony_ci __ CallCFunction(ExternalReference::re_is_character_in_range_array(), 5061cb0ef41Sopenharmony_ci kNumArguments); 5071cb0ef41Sopenharmony_ci } 5081cb0ef41Sopenharmony_ci 5091cb0ef41Sopenharmony_ci __ mov(code_pointer(), Operand(masm_->CodeObject())); 5101cb0ef41Sopenharmony_ci} 5111cb0ef41Sopenharmony_ci 5121cb0ef41Sopenharmony_cibool RegExpMacroAssemblerS390::CheckCharacterInRangeArray( 5131cb0ef41Sopenharmony_ci const ZoneList<CharacterRange>* ranges, Label* on_in_range) { 5141cb0ef41Sopenharmony_ci CallIsCharacterInRangeArray(ranges); 5151cb0ef41Sopenharmony_ci __ CmpS64(r2, Operand::Zero()); 5161cb0ef41Sopenharmony_ci BranchOrBacktrack(ne, on_in_range); 5171cb0ef41Sopenharmony_ci return true; 5181cb0ef41Sopenharmony_ci} 5191cb0ef41Sopenharmony_ci 5201cb0ef41Sopenharmony_cibool RegExpMacroAssemblerS390::CheckCharacterNotInRangeArray( 5211cb0ef41Sopenharmony_ci const ZoneList<CharacterRange>* ranges, Label* on_not_in_range) { 5221cb0ef41Sopenharmony_ci CallIsCharacterInRangeArray(ranges); 5231cb0ef41Sopenharmony_ci __ CmpS64(r2, Operand::Zero()); 5241cb0ef41Sopenharmony_ci BranchOrBacktrack(eq, on_not_in_range); 5251cb0ef41Sopenharmony_ci return true; 5261cb0ef41Sopenharmony_ci} 5271cb0ef41Sopenharmony_ci 5281cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckBitInTable(Handle<ByteArray> table, 5291cb0ef41Sopenharmony_ci Label* on_bit_set) { 5301cb0ef41Sopenharmony_ci __ mov(r2, Operand(table)); 5311cb0ef41Sopenharmony_ci Register index = current_character(); 5321cb0ef41Sopenharmony_ci if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) { 5331cb0ef41Sopenharmony_ci __ AndP(r3, current_character(), Operand(kTableSize - 1)); 5341cb0ef41Sopenharmony_ci index = r3; 5351cb0ef41Sopenharmony_ci } 5361cb0ef41Sopenharmony_ci __ LoadU8(r2, 5371cb0ef41Sopenharmony_ci MemOperand(r2, index, (ByteArray::kHeaderSize - kHeapObjectTag))); 5381cb0ef41Sopenharmony_ci __ CmpS64(r2, Operand::Zero()); 5391cb0ef41Sopenharmony_ci BranchOrBacktrack(ne, on_bit_set); 5401cb0ef41Sopenharmony_ci} 5411cb0ef41Sopenharmony_ci 5421cb0ef41Sopenharmony_cibool RegExpMacroAssemblerS390::CheckSpecialCharacterClass( 5431cb0ef41Sopenharmony_ci StandardCharacterSet type, Label* on_no_match) { 5441cb0ef41Sopenharmony_ci // Range checks (c in min..max) are generally implemented by an unsigned 5451cb0ef41Sopenharmony_ci // (c - min) <= (max - min) check 5461cb0ef41Sopenharmony_ci // TODO(jgruber): No custom implementation (yet): s(UC16), S(UC16). 5471cb0ef41Sopenharmony_ci switch (type) { 5481cb0ef41Sopenharmony_ci case StandardCharacterSet::kWhitespace: 5491cb0ef41Sopenharmony_ci // Match space-characters. 5501cb0ef41Sopenharmony_ci if (mode_ == LATIN1) { 5511cb0ef41Sopenharmony_ci // One byte space characters are '\t'..'\r', ' ' and \u00a0. 5521cb0ef41Sopenharmony_ci Label success; 5531cb0ef41Sopenharmony_ci __ CmpS64(current_character(), Operand(' ')); 5541cb0ef41Sopenharmony_ci __ beq(&success); 5551cb0ef41Sopenharmony_ci // Check range 0x09..0x0D. 5561cb0ef41Sopenharmony_ci __ SubS64(r2, current_character(), Operand('\t')); 5571cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand('\r' - '\t')); 5581cb0ef41Sopenharmony_ci __ ble(&success); 5591cb0ef41Sopenharmony_ci // \u00a0 (NBSP). 5601cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand(0x00A0 - '\t')); 5611cb0ef41Sopenharmony_ci BranchOrBacktrack(ne, on_no_match); 5621cb0ef41Sopenharmony_ci __ bind(&success); 5631cb0ef41Sopenharmony_ci return true; 5641cb0ef41Sopenharmony_ci } 5651cb0ef41Sopenharmony_ci return false; 5661cb0ef41Sopenharmony_ci case StandardCharacterSet::kNotWhitespace: 5671cb0ef41Sopenharmony_ci // The emitted code for generic character classes is good enough. 5681cb0ef41Sopenharmony_ci return false; 5691cb0ef41Sopenharmony_ci case StandardCharacterSet::kDigit: 5701cb0ef41Sopenharmony_ci // Match ASCII digits ('0'..'9') 5711cb0ef41Sopenharmony_ci __ SubS64(r2, current_character(), Operand('0')); 5721cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand('9' - '0')); 5731cb0ef41Sopenharmony_ci BranchOrBacktrack(gt, on_no_match); 5741cb0ef41Sopenharmony_ci return true; 5751cb0ef41Sopenharmony_ci case StandardCharacterSet::kNotDigit: 5761cb0ef41Sopenharmony_ci // Match non ASCII-digits 5771cb0ef41Sopenharmony_ci __ SubS64(r2, current_character(), Operand('0')); 5781cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand('9' - '0')); 5791cb0ef41Sopenharmony_ci BranchOrBacktrack(le, on_no_match); 5801cb0ef41Sopenharmony_ci return true; 5811cb0ef41Sopenharmony_ci case StandardCharacterSet::kNotLineTerminator: { 5821cb0ef41Sopenharmony_ci // Match non-newlines (not 0x0A('\n'), 0x0D('\r'), 0x2028 and 0x2029) 5831cb0ef41Sopenharmony_ci __ XorP(r2, current_character(), Operand(0x01)); 5841cb0ef41Sopenharmony_ci // See if current character is '\n'^1 or '\r'^1, i.e., 0x0B or 0x0C 5851cb0ef41Sopenharmony_ci __ SubS64(r2, Operand(0x0B)); 5861cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand(0x0C - 0x0B)); 5871cb0ef41Sopenharmony_ci BranchOrBacktrack(le, on_no_match); 5881cb0ef41Sopenharmony_ci if (mode_ == UC16) { 5891cb0ef41Sopenharmony_ci // Compare original value to 0x2028 and 0x2029, using the already 5901cb0ef41Sopenharmony_ci // computed (current_char ^ 0x01 - 0x0B). I.e., check for 5911cb0ef41Sopenharmony_ci // 0x201D (0x2028 - 0x0B) or 0x201E. 5921cb0ef41Sopenharmony_ci __ SubS64(r2, Operand(0x2028 - 0x0B)); 5931cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand(1)); 5941cb0ef41Sopenharmony_ci BranchOrBacktrack(le, on_no_match); 5951cb0ef41Sopenharmony_ci } 5961cb0ef41Sopenharmony_ci return true; 5971cb0ef41Sopenharmony_ci } 5981cb0ef41Sopenharmony_ci case StandardCharacterSet::kLineTerminator: { 5991cb0ef41Sopenharmony_ci // Match newlines (0x0A('\n'), 0x0D('\r'), 0x2028 and 0x2029) 6001cb0ef41Sopenharmony_ci __ XorP(r2, current_character(), Operand(0x01)); 6011cb0ef41Sopenharmony_ci // See if current character is '\n'^1 or '\r'^1, i.e., 0x0B or 0x0C 6021cb0ef41Sopenharmony_ci __ SubS64(r2, Operand(0x0B)); 6031cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand(0x0C - 0x0B)); 6041cb0ef41Sopenharmony_ci if (mode_ == LATIN1) { 6051cb0ef41Sopenharmony_ci BranchOrBacktrack(gt, on_no_match); 6061cb0ef41Sopenharmony_ci } else { 6071cb0ef41Sopenharmony_ci Label done; 6081cb0ef41Sopenharmony_ci __ ble(&done); 6091cb0ef41Sopenharmony_ci // Compare original value to 0x2028 and 0x2029, using the already 6101cb0ef41Sopenharmony_ci // computed (current_char ^ 0x01 - 0x0B). I.e., check for 6111cb0ef41Sopenharmony_ci // 0x201D (0x2028 - 0x0B) or 0x201E. 6121cb0ef41Sopenharmony_ci __ SubS64(r2, Operand(0x2028 - 0x0B)); 6131cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand(1)); 6141cb0ef41Sopenharmony_ci BranchOrBacktrack(gt, on_no_match); 6151cb0ef41Sopenharmony_ci __ bind(&done); 6161cb0ef41Sopenharmony_ci } 6171cb0ef41Sopenharmony_ci return true; 6181cb0ef41Sopenharmony_ci } 6191cb0ef41Sopenharmony_ci case StandardCharacterSet::kWord: { 6201cb0ef41Sopenharmony_ci if (mode_ != LATIN1) { 6211cb0ef41Sopenharmony_ci // Table is 1256 entries, so all LATIN1 characters can be tested. 6221cb0ef41Sopenharmony_ci __ CmpS64(current_character(), Operand('z')); 6231cb0ef41Sopenharmony_ci BranchOrBacktrack(gt, on_no_match); 6241cb0ef41Sopenharmony_ci } 6251cb0ef41Sopenharmony_ci ExternalReference map = ExternalReference::re_word_character_map(); 6261cb0ef41Sopenharmony_ci __ mov(r2, Operand(map)); 6271cb0ef41Sopenharmony_ci __ LoadU8(r2, MemOperand(r2, current_character())); 6281cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand::Zero()); 6291cb0ef41Sopenharmony_ci BranchOrBacktrack(eq, on_no_match); 6301cb0ef41Sopenharmony_ci return true; 6311cb0ef41Sopenharmony_ci } 6321cb0ef41Sopenharmony_ci case StandardCharacterSet::kNotWord: { 6331cb0ef41Sopenharmony_ci Label done; 6341cb0ef41Sopenharmony_ci if (mode_ != LATIN1) { 6351cb0ef41Sopenharmony_ci // Table is 256 entries, so all LATIN characters can be tested. 6361cb0ef41Sopenharmony_ci __ CmpU64(current_character(), Operand('z')); 6371cb0ef41Sopenharmony_ci __ bgt(&done); 6381cb0ef41Sopenharmony_ci } 6391cb0ef41Sopenharmony_ci ExternalReference map = ExternalReference::re_word_character_map(); 6401cb0ef41Sopenharmony_ci __ mov(r2, Operand(map)); 6411cb0ef41Sopenharmony_ci __ LoadU8(r2, MemOperand(r2, current_character())); 6421cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand::Zero()); 6431cb0ef41Sopenharmony_ci BranchOrBacktrack(ne, on_no_match); 6441cb0ef41Sopenharmony_ci if (mode_ != LATIN1) { 6451cb0ef41Sopenharmony_ci __ bind(&done); 6461cb0ef41Sopenharmony_ci } 6471cb0ef41Sopenharmony_ci return true; 6481cb0ef41Sopenharmony_ci } 6491cb0ef41Sopenharmony_ci case StandardCharacterSet::kEverything: 6501cb0ef41Sopenharmony_ci // Match any character. 6511cb0ef41Sopenharmony_ci return true; 6521cb0ef41Sopenharmony_ci } 6531cb0ef41Sopenharmony_ci} 6541cb0ef41Sopenharmony_ci 6551cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::Fail() { 6561cb0ef41Sopenharmony_ci __ mov(r2, Operand(FAILURE)); 6571cb0ef41Sopenharmony_ci __ b(&exit_label_); 6581cb0ef41Sopenharmony_ci} 6591cb0ef41Sopenharmony_ci 6601cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::LoadRegExpStackPointerFromMemory(Register dst) { 6611cb0ef41Sopenharmony_ci ExternalReference ref = 6621cb0ef41Sopenharmony_ci ExternalReference::address_of_regexp_stack_stack_pointer(isolate()); 6631cb0ef41Sopenharmony_ci __ mov(dst, Operand(ref)); 6641cb0ef41Sopenharmony_ci __ LoadU64(dst, MemOperand(dst)); 6651cb0ef41Sopenharmony_ci} 6661cb0ef41Sopenharmony_ci 6671cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::StoreRegExpStackPointerToMemory( 6681cb0ef41Sopenharmony_ci Register src, Register scratch) { 6691cb0ef41Sopenharmony_ci ExternalReference ref = 6701cb0ef41Sopenharmony_ci ExternalReference::address_of_regexp_stack_stack_pointer(isolate()); 6711cb0ef41Sopenharmony_ci __ mov(scratch, Operand(ref)); 6721cb0ef41Sopenharmony_ci __ StoreU64(src, MemOperand(scratch)); 6731cb0ef41Sopenharmony_ci} 6741cb0ef41Sopenharmony_ci 6751cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::PushRegExpBasePointer(Register stack_pointer, 6761cb0ef41Sopenharmony_ci Register scratch) { 6771cb0ef41Sopenharmony_ci ExternalReference ref = 6781cb0ef41Sopenharmony_ci ExternalReference::address_of_regexp_stack_memory_top_address(isolate()); 6791cb0ef41Sopenharmony_ci __ mov(scratch, Operand(ref)); 6801cb0ef41Sopenharmony_ci __ LoadU64(scratch, MemOperand(scratch)); 6811cb0ef41Sopenharmony_ci __ SubS64(scratch, stack_pointer, scratch); 6821cb0ef41Sopenharmony_ci __ StoreU64(scratch, MemOperand(frame_pointer(), kRegExpStackBasePointer)); 6831cb0ef41Sopenharmony_ci} 6841cb0ef41Sopenharmony_ci 6851cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::PopRegExpBasePointer(Register stack_pointer_out, 6861cb0ef41Sopenharmony_ci Register scratch) { 6871cb0ef41Sopenharmony_ci ExternalReference ref = 6881cb0ef41Sopenharmony_ci ExternalReference::address_of_regexp_stack_memory_top_address(isolate()); 6891cb0ef41Sopenharmony_ci __ LoadU64(stack_pointer_out, 6901cb0ef41Sopenharmony_ci MemOperand(frame_pointer(), kRegExpStackBasePointer)); 6911cb0ef41Sopenharmony_ci __ mov(scratch, Operand(ref)); 6921cb0ef41Sopenharmony_ci __ LoadU64(scratch, MemOperand(scratch)); 6931cb0ef41Sopenharmony_ci __ AddS64(stack_pointer_out, stack_pointer_out, scratch); 6941cb0ef41Sopenharmony_ci StoreRegExpStackPointerToMemory(stack_pointer_out, scratch); 6951cb0ef41Sopenharmony_ci} 6961cb0ef41Sopenharmony_ci 6971cb0ef41Sopenharmony_ciHandle<HeapObject> RegExpMacroAssemblerS390::GetCode(Handle<String> source) { 6981cb0ef41Sopenharmony_ci Label return_r2; 6991cb0ef41Sopenharmony_ci 7001cb0ef41Sopenharmony_ci // Finalize code - write the entry point code now we know how many 7011cb0ef41Sopenharmony_ci // registers we need. 7021cb0ef41Sopenharmony_ci 7031cb0ef41Sopenharmony_ci // Entry code: 7041cb0ef41Sopenharmony_ci __ bind(&entry_label_); 7051cb0ef41Sopenharmony_ci 7061cb0ef41Sopenharmony_ci // Tell the system that we have a stack frame. Because the type 7071cb0ef41Sopenharmony_ci // is MANUAL, no is generated. 7081cb0ef41Sopenharmony_ci FrameScope scope(masm_.get(), StackFrame::MANUAL); 7091cb0ef41Sopenharmony_ci 7101cb0ef41Sopenharmony_ci // Ensure register assigments are consistent with callee save mask 7111cb0ef41Sopenharmony_ci DCHECK(kRegExpCalleeSaved.has(r6)); 7121cb0ef41Sopenharmony_ci DCHECK(kRegExpCalleeSaved.has(code_pointer())); 7131cb0ef41Sopenharmony_ci DCHECK(kRegExpCalleeSaved.has(current_input_offset())); 7141cb0ef41Sopenharmony_ci DCHECK(kRegExpCalleeSaved.has(current_character())); 7151cb0ef41Sopenharmony_ci DCHECK(kRegExpCalleeSaved.has(backtrack_stackpointer())); 7161cb0ef41Sopenharmony_ci DCHECK(kRegExpCalleeSaved.has(end_of_input_address())); 7171cb0ef41Sopenharmony_ci DCHECK(kRegExpCalleeSaved.has(frame_pointer())); 7181cb0ef41Sopenharmony_ci 7191cb0ef41Sopenharmony_ci // zLinux ABI 7201cb0ef41Sopenharmony_ci // Incoming parameters: 7211cb0ef41Sopenharmony_ci // r2: input_string 7221cb0ef41Sopenharmony_ci // r3: start_index 7231cb0ef41Sopenharmony_ci // r4: start addr 7241cb0ef41Sopenharmony_ci // r5: end addr 7251cb0ef41Sopenharmony_ci // r6: capture output arrray 7261cb0ef41Sopenharmony_ci // Requires us to save the callee-preserved registers r6-r13 7271cb0ef41Sopenharmony_ci // General convention is to also save r14 (return addr) and 7281cb0ef41Sopenharmony_ci // sp/r15 as well in a single STM/STMG 7291cb0ef41Sopenharmony_ci __ StoreMultipleP(r6, sp, MemOperand(sp, 6 * kSystemPointerSize)); 7301cb0ef41Sopenharmony_ci 7311cb0ef41Sopenharmony_ci // Load stack parameters from caller stack frame 7321cb0ef41Sopenharmony_ci __ LoadMultipleP( 7331cb0ef41Sopenharmony_ci r7, r9, MemOperand(sp, kStackFrameExtraParamSlot * kSystemPointerSize)); 7341cb0ef41Sopenharmony_ci // r7 = capture array size 7351cb0ef41Sopenharmony_ci // r8 = stack area base 7361cb0ef41Sopenharmony_ci // r9 = direct call 7371cb0ef41Sopenharmony_ci 7381cb0ef41Sopenharmony_ci // Actually emit code to start a new stack frame. 7391cb0ef41Sopenharmony_ci // Push arguments 7401cb0ef41Sopenharmony_ci // Save callee-save registers. 7411cb0ef41Sopenharmony_ci // Start new stack frame. 7421cb0ef41Sopenharmony_ci // Store link register in existing stack-cell. 7431cb0ef41Sopenharmony_ci // Order here should correspond to order of offset constants in header file. 7441cb0ef41Sopenharmony_ci // 7451cb0ef41Sopenharmony_ci // Set frame pointer in space for it if this is not a direct call 7461cb0ef41Sopenharmony_ci // from generated code. 7471cb0ef41Sopenharmony_ci __ mov(frame_pointer(), sp); 7481cb0ef41Sopenharmony_ci __ lay(sp, MemOperand(sp, -10 * kSystemPointerSize)); 7491cb0ef41Sopenharmony_ci STATIC_ASSERT(kSuccessfulCaptures == kInputString - kSystemPointerSize); 7501cb0ef41Sopenharmony_ci __ mov(r1, Operand::Zero()); // success counter 7511cb0ef41Sopenharmony_ci STATIC_ASSERT(kStringStartMinusOne == 7521cb0ef41Sopenharmony_ci kSuccessfulCaptures - kSystemPointerSize); 7531cb0ef41Sopenharmony_ci __ mov(r0, r1); // offset of location 7541cb0ef41Sopenharmony_ci __ StoreMultipleP(r0, r9, MemOperand(sp, 0)); 7551cb0ef41Sopenharmony_ci STATIC_ASSERT(kBacktrackCount == kStringStartMinusOne - kSystemPointerSize); 7561cb0ef41Sopenharmony_ci __ Push(r1); // The backtrack counter. 7571cb0ef41Sopenharmony_ci STATIC_ASSERT(kRegExpStackBasePointer == 7581cb0ef41Sopenharmony_ci kBacktrackCount - kSystemPointerSize); 7591cb0ef41Sopenharmony_ci __ push(r1); // The regexp stack base ptr. 7601cb0ef41Sopenharmony_ci 7611cb0ef41Sopenharmony_ci // Initialize backtrack stack pointer. It must not be clobbered from here on. 7621cb0ef41Sopenharmony_ci // Note the backtrack_stackpointer is callee-saved. 7631cb0ef41Sopenharmony_ci STATIC_ASSERT(backtrack_stackpointer() == r13); 7641cb0ef41Sopenharmony_ci LoadRegExpStackPointerFromMemory(backtrack_stackpointer()); 7651cb0ef41Sopenharmony_ci 7661cb0ef41Sopenharmony_ci // Store the regexp base pointer - we'll later restore it / write it to 7671cb0ef41Sopenharmony_ci // memory when returning from this irregexp code object. 7681cb0ef41Sopenharmony_ci PushRegExpBasePointer(backtrack_stackpointer(), r3); 7691cb0ef41Sopenharmony_ci 7701cb0ef41Sopenharmony_ci { 7711cb0ef41Sopenharmony_ci // Check if we have space on the stack for registers. 7721cb0ef41Sopenharmony_ci Label stack_limit_hit, stack_ok; 7731cb0ef41Sopenharmony_ci 7741cb0ef41Sopenharmony_ci ExternalReference stack_limit = 7751cb0ef41Sopenharmony_ci ExternalReference::address_of_jslimit(isolate()); 7761cb0ef41Sopenharmony_ci __ mov(r2, Operand(stack_limit)); 7771cb0ef41Sopenharmony_ci __ LoadU64(r2, MemOperand(r2)); 7781cb0ef41Sopenharmony_ci __ SubS64(r2, sp, r2); 7791cb0ef41Sopenharmony_ci // Handle it if the stack pointer is already below the stack limit. 7801cb0ef41Sopenharmony_ci __ ble(&stack_limit_hit); 7811cb0ef41Sopenharmony_ci // Check if there is room for the variable number of registers above 7821cb0ef41Sopenharmony_ci // the stack limit. 7831cb0ef41Sopenharmony_ci __ CmpU64(r2, Operand(num_registers_ * kSystemPointerSize)); 7841cb0ef41Sopenharmony_ci __ bge(&stack_ok); 7851cb0ef41Sopenharmony_ci // Exit with OutOfMemory exception. There is not enough space on the stack 7861cb0ef41Sopenharmony_ci // for our working registers. 7871cb0ef41Sopenharmony_ci __ mov(r2, Operand(EXCEPTION)); 7881cb0ef41Sopenharmony_ci __ b(&return_r2); 7891cb0ef41Sopenharmony_ci 7901cb0ef41Sopenharmony_ci __ bind(&stack_limit_hit); 7911cb0ef41Sopenharmony_ci CallCheckStackGuardState(r2); 7921cb0ef41Sopenharmony_ci __ CmpS64(r2, Operand::Zero()); 7931cb0ef41Sopenharmony_ci // If returned value is non-zero, we exit with the returned value as result. 7941cb0ef41Sopenharmony_ci __ bne(&return_r2); 7951cb0ef41Sopenharmony_ci 7961cb0ef41Sopenharmony_ci __ bind(&stack_ok); 7971cb0ef41Sopenharmony_ci } 7981cb0ef41Sopenharmony_ci 7991cb0ef41Sopenharmony_ci // Allocate space on stack for registers. 8001cb0ef41Sopenharmony_ci __ lay(sp, MemOperand(sp, (-num_registers_ * kSystemPointerSize))); 8011cb0ef41Sopenharmony_ci // Load string end. 8021cb0ef41Sopenharmony_ci __ LoadU64(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 8031cb0ef41Sopenharmony_ci // Load input start. 8041cb0ef41Sopenharmony_ci __ LoadU64(r4, MemOperand(frame_pointer(), kInputStart)); 8051cb0ef41Sopenharmony_ci // Find negative length (offset of start relative to end). 8061cb0ef41Sopenharmony_ci __ SubS64(current_input_offset(), r4, end_of_input_address()); 8071cb0ef41Sopenharmony_ci __ LoadU64(r3, MemOperand(frame_pointer(), kStartIndex)); 8081cb0ef41Sopenharmony_ci // Set r1 to address of char before start of the input string 8091cb0ef41Sopenharmony_ci // (effectively string position -1). 8101cb0ef41Sopenharmony_ci __ mov(r1, r4); 8111cb0ef41Sopenharmony_ci __ SubS64(r1, current_input_offset(), Operand(char_size())); 8121cb0ef41Sopenharmony_ci if (mode_ == UC16) { 8131cb0ef41Sopenharmony_ci __ ShiftLeftU64(r0, r3, Operand(1)); 8141cb0ef41Sopenharmony_ci __ SubS64(r1, r1, r0); 8151cb0ef41Sopenharmony_ci } else { 8161cb0ef41Sopenharmony_ci __ SubS64(r1, r1, r3); 8171cb0ef41Sopenharmony_ci } 8181cb0ef41Sopenharmony_ci // Store this value in a local variable, for use when clearing 8191cb0ef41Sopenharmony_ci // position registers. 8201cb0ef41Sopenharmony_ci __ StoreU64(r1, MemOperand(frame_pointer(), kStringStartMinusOne)); 8211cb0ef41Sopenharmony_ci 8221cb0ef41Sopenharmony_ci // Initialize code pointer register 8231cb0ef41Sopenharmony_ci __ mov(code_pointer(), Operand(masm_->CodeObject())); 8241cb0ef41Sopenharmony_ci 8251cb0ef41Sopenharmony_ci Label load_char_start_regexp; 8261cb0ef41Sopenharmony_ci { 8271cb0ef41Sopenharmony_ci Label start_regexp; 8281cb0ef41Sopenharmony_ci // Load newline if index is at start, previous character otherwise. 8291cb0ef41Sopenharmony_ci __ CmpS64(r3, Operand::Zero()); 8301cb0ef41Sopenharmony_ci __ bne(&load_char_start_regexp); 8311cb0ef41Sopenharmony_ci __ mov(current_character(), Operand('\n')); 8321cb0ef41Sopenharmony_ci __ b(&start_regexp); 8331cb0ef41Sopenharmony_ci 8341cb0ef41Sopenharmony_ci // Global regexp restarts matching here. 8351cb0ef41Sopenharmony_ci __ bind(&load_char_start_regexp); 8361cb0ef41Sopenharmony_ci // Load previous char as initial value of current character register. 8371cb0ef41Sopenharmony_ci LoadCurrentCharacterUnchecked(-1, 1); 8381cb0ef41Sopenharmony_ci __ bind(&start_regexp); 8391cb0ef41Sopenharmony_ci } 8401cb0ef41Sopenharmony_ci 8411cb0ef41Sopenharmony_ci // Initialize on-stack registers. 8421cb0ef41Sopenharmony_ci if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. 8431cb0ef41Sopenharmony_ci // Fill saved registers with initial value = start offset - 1 8441cb0ef41Sopenharmony_ci if (num_saved_registers_ > 8) { 8451cb0ef41Sopenharmony_ci // One slot beyond address of register 0. 8461cb0ef41Sopenharmony_ci __ lay(r3, 8471cb0ef41Sopenharmony_ci MemOperand(frame_pointer(), kRegisterZero + kSystemPointerSize)); 8481cb0ef41Sopenharmony_ci __ mov(r4, Operand(num_saved_registers_)); 8491cb0ef41Sopenharmony_ci Label init_loop; 8501cb0ef41Sopenharmony_ci __ bind(&init_loop); 8511cb0ef41Sopenharmony_ci __ StoreU64(r1, MemOperand(r3, -kSystemPointerSize)); 8521cb0ef41Sopenharmony_ci __ lay(r3, MemOperand(r3, -kSystemPointerSize)); 8531cb0ef41Sopenharmony_ci __ BranchOnCount(r4, &init_loop); 8541cb0ef41Sopenharmony_ci } else { 8551cb0ef41Sopenharmony_ci for (int i = 0; i < num_saved_registers_; i++) { 8561cb0ef41Sopenharmony_ci __ StoreU64(r1, register_location(i)); 8571cb0ef41Sopenharmony_ci } 8581cb0ef41Sopenharmony_ci } 8591cb0ef41Sopenharmony_ci } 8601cb0ef41Sopenharmony_ci 8611cb0ef41Sopenharmony_ci __ b(&start_label_); 8621cb0ef41Sopenharmony_ci 8631cb0ef41Sopenharmony_ci // Exit code: 8641cb0ef41Sopenharmony_ci if (success_label_.is_linked()) { 8651cb0ef41Sopenharmony_ci // Save captures when successful. 8661cb0ef41Sopenharmony_ci __ bind(&success_label_); 8671cb0ef41Sopenharmony_ci if (num_saved_registers_ > 0) { 8681cb0ef41Sopenharmony_ci // copy captures to output 8691cb0ef41Sopenharmony_ci __ LoadU64(r0, MemOperand(frame_pointer(), kInputStart)); 8701cb0ef41Sopenharmony_ci __ LoadU64(r2, MemOperand(frame_pointer(), kRegisterOutput)); 8711cb0ef41Sopenharmony_ci __ LoadU64(r4, MemOperand(frame_pointer(), kStartIndex)); 8721cb0ef41Sopenharmony_ci __ SubS64(r0, end_of_input_address(), r0); 8731cb0ef41Sopenharmony_ci // r0 is length of input in bytes. 8741cb0ef41Sopenharmony_ci if (mode_ == UC16) { 8751cb0ef41Sopenharmony_ci __ ShiftRightU64(r0, r0, Operand(1)); 8761cb0ef41Sopenharmony_ci } 8771cb0ef41Sopenharmony_ci // r0 is length of input in characters. 8781cb0ef41Sopenharmony_ci __ AddS64(r0, r4); 8791cb0ef41Sopenharmony_ci // r0 is length of string in characters. 8801cb0ef41Sopenharmony_ci 8811cb0ef41Sopenharmony_ci DCHECK_EQ(0, num_saved_registers_ % 2); 8821cb0ef41Sopenharmony_ci // Always an even number of capture registers. This allows us to 8831cb0ef41Sopenharmony_ci // unroll the loop once to add an operation between a load of a register 8841cb0ef41Sopenharmony_ci // and the following use of that register. 8851cb0ef41Sopenharmony_ci __ lay(r2, MemOperand(r2, num_saved_registers_ * kIntSize)); 8861cb0ef41Sopenharmony_ci for (int i = 0; i < num_saved_registers_;) { 8871cb0ef41Sopenharmony_ci if ((false) && i < num_saved_registers_ - 4) { 8881cb0ef41Sopenharmony_ci // TODO(john.yan): Can be optimized by SIMD instructions 8891cb0ef41Sopenharmony_ci __ LoadMultipleP(r3, r6, register_location(i + 3)); 8901cb0ef41Sopenharmony_ci if (mode_ == UC16) { 8911cb0ef41Sopenharmony_ci __ ShiftRightS64(r3, r3, Operand(1)); 8921cb0ef41Sopenharmony_ci __ ShiftRightS64(r4, r4, Operand(1)); 8931cb0ef41Sopenharmony_ci __ ShiftRightS64(r5, r5, Operand(1)); 8941cb0ef41Sopenharmony_ci __ ShiftRightS64(r6, r6, Operand(1)); 8951cb0ef41Sopenharmony_ci } 8961cb0ef41Sopenharmony_ci __ AddS64(r3, r0); 8971cb0ef41Sopenharmony_ci __ AddS64(r4, r0); 8981cb0ef41Sopenharmony_ci __ AddS64(r5, r0); 8991cb0ef41Sopenharmony_ci __ AddS64(r6, r0); 9001cb0ef41Sopenharmony_ci __ StoreU32( 9011cb0ef41Sopenharmony_ci r3, MemOperand(r2, -(num_saved_registers_ - i - 3) * kIntSize)); 9021cb0ef41Sopenharmony_ci __ StoreU32( 9031cb0ef41Sopenharmony_ci r4, MemOperand(r2, -(num_saved_registers_ - i - 2) * kIntSize)); 9041cb0ef41Sopenharmony_ci __ StoreU32( 9051cb0ef41Sopenharmony_ci r5, MemOperand(r2, -(num_saved_registers_ - i - 1) * kIntSize)); 9061cb0ef41Sopenharmony_ci __ StoreU32(r6, 9071cb0ef41Sopenharmony_ci MemOperand(r2, -(num_saved_registers_ - i) * kIntSize)); 9081cb0ef41Sopenharmony_ci i += 4; 9091cb0ef41Sopenharmony_ci } else { 9101cb0ef41Sopenharmony_ci __ LoadMultipleP(r3, r4, register_location(i + 1)); 9111cb0ef41Sopenharmony_ci if (mode_ == UC16) { 9121cb0ef41Sopenharmony_ci __ ShiftRightS64(r3, r3, Operand(1)); 9131cb0ef41Sopenharmony_ci __ ShiftRightS64(r4, r4, Operand(1)); 9141cb0ef41Sopenharmony_ci } 9151cb0ef41Sopenharmony_ci __ AddS64(r3, r0); 9161cb0ef41Sopenharmony_ci __ AddS64(r4, r0); 9171cb0ef41Sopenharmony_ci __ StoreU32( 9181cb0ef41Sopenharmony_ci r3, MemOperand(r2, -(num_saved_registers_ - i - 1) * kIntSize)); 9191cb0ef41Sopenharmony_ci __ StoreU32(r4, 9201cb0ef41Sopenharmony_ci MemOperand(r2, -(num_saved_registers_ - i) * kIntSize)); 9211cb0ef41Sopenharmony_ci i += 2; 9221cb0ef41Sopenharmony_ci } 9231cb0ef41Sopenharmony_ci } 9241cb0ef41Sopenharmony_ci if (global_with_zero_length_check()) { 9251cb0ef41Sopenharmony_ci // Keep capture start in r6 for the zero-length check later. 9261cb0ef41Sopenharmony_ci __ LoadU64(r6, register_location(0)); 9271cb0ef41Sopenharmony_ci } 9281cb0ef41Sopenharmony_ci } 9291cb0ef41Sopenharmony_ci 9301cb0ef41Sopenharmony_ci if (global()) { 9311cb0ef41Sopenharmony_ci // Restart matching if the regular expression is flagged as global. 9321cb0ef41Sopenharmony_ci __ LoadU64(r2, MemOperand(frame_pointer(), kSuccessfulCaptures)); 9331cb0ef41Sopenharmony_ci __ LoadU64(r3, MemOperand(frame_pointer(), kNumOutputRegisters)); 9341cb0ef41Sopenharmony_ci __ LoadU64(r4, MemOperand(frame_pointer(), kRegisterOutput)); 9351cb0ef41Sopenharmony_ci // Increment success counter. 9361cb0ef41Sopenharmony_ci __ AddS64(r2, Operand(1)); 9371cb0ef41Sopenharmony_ci __ StoreU64(r2, MemOperand(frame_pointer(), kSuccessfulCaptures)); 9381cb0ef41Sopenharmony_ci // Capture results have been stored, so the number of remaining global 9391cb0ef41Sopenharmony_ci // output registers is reduced by the number of stored captures. 9401cb0ef41Sopenharmony_ci __ SubS64(r3, Operand(num_saved_registers_)); 9411cb0ef41Sopenharmony_ci // Check whether we have enough room for another set of capture results. 9421cb0ef41Sopenharmony_ci __ CmpS64(r3, Operand(num_saved_registers_)); 9431cb0ef41Sopenharmony_ci __ blt(&return_r2); 9441cb0ef41Sopenharmony_ci 9451cb0ef41Sopenharmony_ci __ StoreU64(r3, MemOperand(frame_pointer(), kNumOutputRegisters)); 9461cb0ef41Sopenharmony_ci // Advance the location for output. 9471cb0ef41Sopenharmony_ci __ AddS64(r4, Operand(num_saved_registers_ * kIntSize)); 9481cb0ef41Sopenharmony_ci __ StoreU64(r4, MemOperand(frame_pointer(), kRegisterOutput)); 9491cb0ef41Sopenharmony_ci 9501cb0ef41Sopenharmony_ci // Prepare r2 to initialize registers with its value in the next run. 9511cb0ef41Sopenharmony_ci __ LoadU64(r2, MemOperand(frame_pointer(), kStringStartMinusOne)); 9521cb0ef41Sopenharmony_ci 9531cb0ef41Sopenharmony_ci // Restore the original regexp stack pointer value (effectively, pop the 9541cb0ef41Sopenharmony_ci // stored base pointer). 9551cb0ef41Sopenharmony_ci PopRegExpBasePointer(backtrack_stackpointer(), r4); 9561cb0ef41Sopenharmony_ci 9571cb0ef41Sopenharmony_ci if (global_with_zero_length_check()) { 9581cb0ef41Sopenharmony_ci // Special case for zero-length matches. 9591cb0ef41Sopenharmony_ci // r6: capture start index 9601cb0ef41Sopenharmony_ci __ CmpS64(current_input_offset(), r6); 9611cb0ef41Sopenharmony_ci // Not a zero-length match, restart. 9621cb0ef41Sopenharmony_ci __ bne(&load_char_start_regexp); 9631cb0ef41Sopenharmony_ci // Offset from the end is zero if we already reached the end. 9641cb0ef41Sopenharmony_ci __ CmpS64(current_input_offset(), Operand::Zero()); 9651cb0ef41Sopenharmony_ci __ beq(&exit_label_); 9661cb0ef41Sopenharmony_ci // Advance current position after a zero-length match. 9671cb0ef41Sopenharmony_ci Label advance; 9681cb0ef41Sopenharmony_ci __ bind(&advance); 9691cb0ef41Sopenharmony_ci __ AddS64(current_input_offset(), Operand((mode_ == UC16) ? 2 : 1)); 9701cb0ef41Sopenharmony_ci if (global_unicode()) CheckNotInSurrogatePair(0, &advance); 9711cb0ef41Sopenharmony_ci } 9721cb0ef41Sopenharmony_ci 9731cb0ef41Sopenharmony_ci __ b(&load_char_start_regexp); 9741cb0ef41Sopenharmony_ci } else { 9751cb0ef41Sopenharmony_ci __ mov(r2, Operand(SUCCESS)); 9761cb0ef41Sopenharmony_ci } 9771cb0ef41Sopenharmony_ci } 9781cb0ef41Sopenharmony_ci 9791cb0ef41Sopenharmony_ci // Exit and return r2 9801cb0ef41Sopenharmony_ci __ bind(&exit_label_); 9811cb0ef41Sopenharmony_ci if (global()) { 9821cb0ef41Sopenharmony_ci __ LoadU64(r2, MemOperand(frame_pointer(), kSuccessfulCaptures)); 9831cb0ef41Sopenharmony_ci } 9841cb0ef41Sopenharmony_ci 9851cb0ef41Sopenharmony_ci __ bind(&return_r2); 9861cb0ef41Sopenharmony_ci // Restore the original regexp stack pointer value (effectively, pop the 9871cb0ef41Sopenharmony_ci // stored base pointer). 9881cb0ef41Sopenharmony_ci PopRegExpBasePointer(backtrack_stackpointer(), r4); 9891cb0ef41Sopenharmony_ci 9901cb0ef41Sopenharmony_ci // Skip sp past regexp registers and local variables.. 9911cb0ef41Sopenharmony_ci __ mov(sp, frame_pointer()); 9921cb0ef41Sopenharmony_ci // Restore registers r6..r15. 9931cb0ef41Sopenharmony_ci __ LoadMultipleP(r6, sp, MemOperand(sp, 6 * kSystemPointerSize)); 9941cb0ef41Sopenharmony_ci 9951cb0ef41Sopenharmony_ci __ b(r14); 9961cb0ef41Sopenharmony_ci 9971cb0ef41Sopenharmony_ci // Backtrack code (branch target for conditional backtracks). 9981cb0ef41Sopenharmony_ci if (backtrack_label_.is_linked()) { 9991cb0ef41Sopenharmony_ci __ bind(&backtrack_label_); 10001cb0ef41Sopenharmony_ci Backtrack(); 10011cb0ef41Sopenharmony_ci } 10021cb0ef41Sopenharmony_ci 10031cb0ef41Sopenharmony_ci Label exit_with_exception; 10041cb0ef41Sopenharmony_ci 10051cb0ef41Sopenharmony_ci // Preempt-code 10061cb0ef41Sopenharmony_ci if (check_preempt_label_.is_linked()) { 10071cb0ef41Sopenharmony_ci SafeCallTarget(&check_preempt_label_); 10081cb0ef41Sopenharmony_ci 10091cb0ef41Sopenharmony_ci StoreRegExpStackPointerToMemory(backtrack_stackpointer(), r3); 10101cb0ef41Sopenharmony_ci 10111cb0ef41Sopenharmony_ci CallCheckStackGuardState(r2); 10121cb0ef41Sopenharmony_ci __ CmpS64(r2, Operand::Zero()); 10131cb0ef41Sopenharmony_ci // If returning non-zero, we should end execution with the given 10141cb0ef41Sopenharmony_ci // result as return value. 10151cb0ef41Sopenharmony_ci __ bne(&return_r2); 10161cb0ef41Sopenharmony_ci 10171cb0ef41Sopenharmony_ci LoadRegExpStackPointerFromMemory(backtrack_stackpointer()); 10181cb0ef41Sopenharmony_ci 10191cb0ef41Sopenharmony_ci // String might have moved: Reload end of string from frame. 10201cb0ef41Sopenharmony_ci __ LoadU64(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 10211cb0ef41Sopenharmony_ci SafeReturn(); 10221cb0ef41Sopenharmony_ci } 10231cb0ef41Sopenharmony_ci 10241cb0ef41Sopenharmony_ci // Backtrack stack overflow code. 10251cb0ef41Sopenharmony_ci if (stack_overflow_label_.is_linked()) { 10261cb0ef41Sopenharmony_ci SafeCallTarget(&stack_overflow_label_); 10271cb0ef41Sopenharmony_ci // Reached if the backtrack-stack limit has been hit. 10281cb0ef41Sopenharmony_ci 10291cb0ef41Sopenharmony_ci // Call GrowStack(isolate). 10301cb0ef41Sopenharmony_ci 10311cb0ef41Sopenharmony_ci StoreRegExpStackPointerToMemory(backtrack_stackpointer(), r3); 10321cb0ef41Sopenharmony_ci 10331cb0ef41Sopenharmony_ci static constexpr int kNumArguments = 1; 10341cb0ef41Sopenharmony_ci __ PrepareCallCFunction(kNumArguments, r2); 10351cb0ef41Sopenharmony_ci __ mov(r2, Operand(ExternalReference::isolate_address(isolate()))); 10361cb0ef41Sopenharmony_ci ExternalReference grow_stack = ExternalReference::re_grow_stack(); 10371cb0ef41Sopenharmony_ci __ CallCFunction(grow_stack, kNumArguments); 10381cb0ef41Sopenharmony_ci // If nullptr is returned, we have failed to grow the stack, and must exit 10391cb0ef41Sopenharmony_ci // with a stack-overflow exception. 10401cb0ef41Sopenharmony_ci __ CmpS64(r2, Operand::Zero()); 10411cb0ef41Sopenharmony_ci __ beq(&exit_with_exception); 10421cb0ef41Sopenharmony_ci // Otherwise use return value as new stack pointer. 10431cb0ef41Sopenharmony_ci __ mov(backtrack_stackpointer(), r2); 10441cb0ef41Sopenharmony_ci // Restore saved registers and continue. 10451cb0ef41Sopenharmony_ci SafeReturn(); 10461cb0ef41Sopenharmony_ci } 10471cb0ef41Sopenharmony_ci 10481cb0ef41Sopenharmony_ci if (exit_with_exception.is_linked()) { 10491cb0ef41Sopenharmony_ci // If any of the code above needed to exit with an exception. 10501cb0ef41Sopenharmony_ci __ bind(&exit_with_exception); 10511cb0ef41Sopenharmony_ci // Exit with Result EXCEPTION(-1) to signal thrown exception. 10521cb0ef41Sopenharmony_ci __ mov(r2, Operand(EXCEPTION)); 10531cb0ef41Sopenharmony_ci __ b(&return_r2); 10541cb0ef41Sopenharmony_ci } 10551cb0ef41Sopenharmony_ci 10561cb0ef41Sopenharmony_ci if (fallback_label_.is_linked()) { 10571cb0ef41Sopenharmony_ci __ bind(&fallback_label_); 10581cb0ef41Sopenharmony_ci __ mov(r2, Operand(FALLBACK_TO_EXPERIMENTAL)); 10591cb0ef41Sopenharmony_ci __ b(&return_r2); 10601cb0ef41Sopenharmony_ci } 10611cb0ef41Sopenharmony_ci 10621cb0ef41Sopenharmony_ci CodeDesc code_desc; 10631cb0ef41Sopenharmony_ci masm_->GetCode(isolate(), &code_desc); 10641cb0ef41Sopenharmony_ci Handle<Code> code = 10651cb0ef41Sopenharmony_ci Factory::CodeBuilder(isolate(), code_desc, CodeKind::REGEXP) 10661cb0ef41Sopenharmony_ci .set_self_reference(masm_->CodeObject()) 10671cb0ef41Sopenharmony_ci .Build(); 10681cb0ef41Sopenharmony_ci PROFILE(masm_->isolate(), 10691cb0ef41Sopenharmony_ci RegExpCodeCreateEvent(Handle<AbstractCode>::cast(code), source)); 10701cb0ef41Sopenharmony_ci return Handle<HeapObject>::cast(code); 10711cb0ef41Sopenharmony_ci} 10721cb0ef41Sopenharmony_ci 10731cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::GoTo(Label* to) { BranchOrBacktrack(al, to); } 10741cb0ef41Sopenharmony_ci 10751cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::IfRegisterGE(int reg, int comparand, 10761cb0ef41Sopenharmony_ci Label* if_ge) { 10771cb0ef41Sopenharmony_ci __ LoadU64(r2, register_location(reg), r0); 10781cb0ef41Sopenharmony_ci __ CmpS64(r2, Operand(comparand)); 10791cb0ef41Sopenharmony_ci BranchOrBacktrack(ge, if_ge); 10801cb0ef41Sopenharmony_ci} 10811cb0ef41Sopenharmony_ci 10821cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::IfRegisterLT(int reg, int comparand, 10831cb0ef41Sopenharmony_ci Label* if_lt) { 10841cb0ef41Sopenharmony_ci __ LoadU64(r2, register_location(reg), r0); 10851cb0ef41Sopenharmony_ci __ CmpS64(r2, Operand(comparand)); 10861cb0ef41Sopenharmony_ci BranchOrBacktrack(lt, if_lt); 10871cb0ef41Sopenharmony_ci} 10881cb0ef41Sopenharmony_ci 10891cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::IfRegisterEqPos(int reg, Label* if_eq) { 10901cb0ef41Sopenharmony_ci __ LoadU64(r2, register_location(reg), r0); 10911cb0ef41Sopenharmony_ci __ CmpS64(r2, current_input_offset()); 10921cb0ef41Sopenharmony_ci BranchOrBacktrack(eq, if_eq); 10931cb0ef41Sopenharmony_ci} 10941cb0ef41Sopenharmony_ci 10951cb0ef41Sopenharmony_ciRegExpMacroAssembler::IrregexpImplementation 10961cb0ef41Sopenharmony_ciRegExpMacroAssemblerS390::Implementation() { 10971cb0ef41Sopenharmony_ci return kS390Implementation; 10981cb0ef41Sopenharmony_ci} 10991cb0ef41Sopenharmony_ci 11001cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::PopCurrentPosition() { 11011cb0ef41Sopenharmony_ci Pop(current_input_offset()); 11021cb0ef41Sopenharmony_ci} 11031cb0ef41Sopenharmony_ci 11041cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::PopRegister(int register_index) { 11051cb0ef41Sopenharmony_ci Pop(r2); 11061cb0ef41Sopenharmony_ci __ StoreU64(r2, register_location(register_index)); 11071cb0ef41Sopenharmony_ci} 11081cb0ef41Sopenharmony_ci 11091cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::PushBacktrack(Label* label) { 11101cb0ef41Sopenharmony_ci if (label->is_bound()) { 11111cb0ef41Sopenharmony_ci int target = label->pos(); 11121cb0ef41Sopenharmony_ci __ mov(r2, Operand(target + Code::kHeaderSize - kHeapObjectTag)); 11131cb0ef41Sopenharmony_ci } else { 11141cb0ef41Sopenharmony_ci masm_->load_label_offset(r2, label); 11151cb0ef41Sopenharmony_ci } 11161cb0ef41Sopenharmony_ci Push(r2); 11171cb0ef41Sopenharmony_ci CheckStackLimit(); 11181cb0ef41Sopenharmony_ci} 11191cb0ef41Sopenharmony_ci 11201cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::PushCurrentPosition() { 11211cb0ef41Sopenharmony_ci Push(current_input_offset()); 11221cb0ef41Sopenharmony_ci} 11231cb0ef41Sopenharmony_ci 11241cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::PushRegister(int register_index, 11251cb0ef41Sopenharmony_ci StackCheckFlag check_stack_limit) { 11261cb0ef41Sopenharmony_ci __ LoadU64(r2, register_location(register_index), r0); 11271cb0ef41Sopenharmony_ci Push(r2); 11281cb0ef41Sopenharmony_ci if (check_stack_limit) CheckStackLimit(); 11291cb0ef41Sopenharmony_ci} 11301cb0ef41Sopenharmony_ci 11311cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::ReadCurrentPositionFromRegister(int reg) { 11321cb0ef41Sopenharmony_ci __ LoadU64(current_input_offset(), register_location(reg), r0); 11331cb0ef41Sopenharmony_ci} 11341cb0ef41Sopenharmony_ci 11351cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::WriteStackPointerToRegister(int reg) { 11361cb0ef41Sopenharmony_ci ExternalReference ref = 11371cb0ef41Sopenharmony_ci ExternalReference::address_of_regexp_stack_memory_top_address(isolate()); 11381cb0ef41Sopenharmony_ci __ mov(r3, Operand(ref)); 11391cb0ef41Sopenharmony_ci __ LoadU64(r3, MemOperand(r3)); 11401cb0ef41Sopenharmony_ci __ SubS64(r2, backtrack_stackpointer(), r3); 11411cb0ef41Sopenharmony_ci __ StoreU64(r2, register_location(reg)); 11421cb0ef41Sopenharmony_ci} 11431cb0ef41Sopenharmony_ci 11441cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::ReadStackPointerFromRegister(int reg) { 11451cb0ef41Sopenharmony_ci ExternalReference ref = 11461cb0ef41Sopenharmony_ci ExternalReference::address_of_regexp_stack_memory_top_address(isolate()); 11471cb0ef41Sopenharmony_ci __ mov(r2, Operand(ref)); 11481cb0ef41Sopenharmony_ci __ LoadU64(r2, MemOperand(r2)); 11491cb0ef41Sopenharmony_ci __ LoadU64(backtrack_stackpointer(), register_location(reg)); 11501cb0ef41Sopenharmony_ci __ AddS64(backtrack_stackpointer(), backtrack_stackpointer(), r2); 11511cb0ef41Sopenharmony_ci} 11521cb0ef41Sopenharmony_ci 11531cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::SetCurrentPositionFromEnd(int by) { 11541cb0ef41Sopenharmony_ci Label after_position; 11551cb0ef41Sopenharmony_ci __ CmpS64(current_input_offset(), Operand(-by * char_size())); 11561cb0ef41Sopenharmony_ci __ bge(&after_position); 11571cb0ef41Sopenharmony_ci __ mov(current_input_offset(), Operand(-by * char_size())); 11581cb0ef41Sopenharmony_ci // On RegExp code entry (where this operation is used), the character before 11591cb0ef41Sopenharmony_ci // the current position is expected to be already loaded. 11601cb0ef41Sopenharmony_ci // We have advanced the position, so it's safe to read backwards. 11611cb0ef41Sopenharmony_ci LoadCurrentCharacterUnchecked(-1, 1); 11621cb0ef41Sopenharmony_ci __ bind(&after_position); 11631cb0ef41Sopenharmony_ci} 11641cb0ef41Sopenharmony_ci 11651cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::SetRegister(int register_index, int to) { 11661cb0ef41Sopenharmony_ci DCHECK(register_index >= num_saved_registers_); // Reserved for positions! 11671cb0ef41Sopenharmony_ci __ mov(r2, Operand(to)); 11681cb0ef41Sopenharmony_ci __ StoreU64(r2, register_location(register_index)); 11691cb0ef41Sopenharmony_ci} 11701cb0ef41Sopenharmony_ci 11711cb0ef41Sopenharmony_cibool RegExpMacroAssemblerS390::Succeed() { 11721cb0ef41Sopenharmony_ci __ b(&success_label_); 11731cb0ef41Sopenharmony_ci return global(); 11741cb0ef41Sopenharmony_ci} 11751cb0ef41Sopenharmony_ci 11761cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::WriteCurrentPositionToRegister(int reg, 11771cb0ef41Sopenharmony_ci int cp_offset) { 11781cb0ef41Sopenharmony_ci if (cp_offset == 0) { 11791cb0ef41Sopenharmony_ci __ StoreU64(current_input_offset(), register_location(reg)); 11801cb0ef41Sopenharmony_ci } else { 11811cb0ef41Sopenharmony_ci __ AddS64(r2, current_input_offset(), Operand(cp_offset * char_size())); 11821cb0ef41Sopenharmony_ci __ StoreU64(r2, register_location(reg)); 11831cb0ef41Sopenharmony_ci } 11841cb0ef41Sopenharmony_ci} 11851cb0ef41Sopenharmony_ci 11861cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::ClearRegisters(int reg_from, int reg_to) { 11871cb0ef41Sopenharmony_ci DCHECK(reg_from <= reg_to); 11881cb0ef41Sopenharmony_ci __ LoadU64(r2, MemOperand(frame_pointer(), kStringStartMinusOne)); 11891cb0ef41Sopenharmony_ci for (int reg = reg_from; reg <= reg_to; reg++) { 11901cb0ef41Sopenharmony_ci __ StoreU64(r2, register_location(reg)); 11911cb0ef41Sopenharmony_ci } 11921cb0ef41Sopenharmony_ci} 11931cb0ef41Sopenharmony_ci 11941cb0ef41Sopenharmony_ci// Private methods: 11951cb0ef41Sopenharmony_ci 11961cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CallCheckStackGuardState(Register scratch) { 11971cb0ef41Sopenharmony_ci DCHECK(!isolate()->IsGeneratingEmbeddedBuiltins()); 11981cb0ef41Sopenharmony_ci DCHECK(!masm_->options().isolate_independent_code); 11991cb0ef41Sopenharmony_ci 12001cb0ef41Sopenharmony_ci static constexpr int num_arguments = 3; 12011cb0ef41Sopenharmony_ci __ PrepareCallCFunction(num_arguments, scratch); 12021cb0ef41Sopenharmony_ci // RegExp code frame pointer. 12031cb0ef41Sopenharmony_ci __ mov(r4, frame_pointer()); 12041cb0ef41Sopenharmony_ci // Code of self. 12051cb0ef41Sopenharmony_ci __ mov(r3, Operand(masm_->CodeObject())); 12061cb0ef41Sopenharmony_ci // r2 becomes return address pointer. 12071cb0ef41Sopenharmony_ci __ lay(r2, MemOperand(sp, kStackFrameRASlot * kSystemPointerSize)); 12081cb0ef41Sopenharmony_ci ExternalReference stack_guard_check = 12091cb0ef41Sopenharmony_ci ExternalReference::re_check_stack_guard_state(); 12101cb0ef41Sopenharmony_ci 12111cb0ef41Sopenharmony_ci __ mov(ip, Operand(stack_guard_check)); 12121cb0ef41Sopenharmony_ci __ StoreReturnAddressAndCall(ip); 12131cb0ef41Sopenharmony_ci 12141cb0ef41Sopenharmony_ci if (base::OS::ActivationFrameAlignment() > kSystemPointerSize) { 12151cb0ef41Sopenharmony_ci __ LoadU64( 12161cb0ef41Sopenharmony_ci sp, MemOperand(sp, (kNumRequiredStackFrameSlots * kSystemPointerSize))); 12171cb0ef41Sopenharmony_ci } else { 12181cb0ef41Sopenharmony_ci __ la(sp, 12191cb0ef41Sopenharmony_ci MemOperand(sp, (kNumRequiredStackFrameSlots * kSystemPointerSize))); 12201cb0ef41Sopenharmony_ci } 12211cb0ef41Sopenharmony_ci 12221cb0ef41Sopenharmony_ci __ mov(code_pointer(), Operand(masm_->CodeObject())); 12231cb0ef41Sopenharmony_ci} 12241cb0ef41Sopenharmony_ci 12251cb0ef41Sopenharmony_ci// Helper function for reading a value out of a stack frame. 12261cb0ef41Sopenharmony_citemplate <typename T> 12271cb0ef41Sopenharmony_cistatic T& frame_entry(Address re_frame, int frame_offset) { 12281cb0ef41Sopenharmony_ci DCHECK_EQ(kSystemPointerSize, sizeof(T)); 12291cb0ef41Sopenharmony_ci#ifdef V8_TARGET_ARCH_S390X 12301cb0ef41Sopenharmony_ci return reinterpret_cast<T&>(Memory<uint64_t>(re_frame + frame_offset)); 12311cb0ef41Sopenharmony_ci#else 12321cb0ef41Sopenharmony_ci return reinterpret_cast<T&>(Memory<uint32_t>(re_frame + frame_offset)); 12331cb0ef41Sopenharmony_ci#endif 12341cb0ef41Sopenharmony_ci} 12351cb0ef41Sopenharmony_ci 12361cb0ef41Sopenharmony_citemplate <typename T> 12371cb0ef41Sopenharmony_cistatic T* frame_entry_address(Address re_frame, int frame_offset) { 12381cb0ef41Sopenharmony_ci return reinterpret_cast<T*>(re_frame + frame_offset); 12391cb0ef41Sopenharmony_ci} 12401cb0ef41Sopenharmony_ci 12411cb0ef41Sopenharmony_ciint RegExpMacroAssemblerS390::CheckStackGuardState(Address* return_address, 12421cb0ef41Sopenharmony_ci Address raw_code, 12431cb0ef41Sopenharmony_ci Address re_frame) { 12441cb0ef41Sopenharmony_ci Code re_code = Code::cast(Object(raw_code)); 12451cb0ef41Sopenharmony_ci return NativeRegExpMacroAssembler::CheckStackGuardState( 12461cb0ef41Sopenharmony_ci frame_entry<Isolate*>(re_frame, kIsolate), 12471cb0ef41Sopenharmony_ci frame_entry<intptr_t>(re_frame, kStartIndex), 12481cb0ef41Sopenharmony_ci static_cast<RegExp::CallOrigin>( 12491cb0ef41Sopenharmony_ci frame_entry<intptr_t>(re_frame, kDirectCall)), 12501cb0ef41Sopenharmony_ci return_address, re_code, 12511cb0ef41Sopenharmony_ci frame_entry_address<Address>(re_frame, kInputString), 12521cb0ef41Sopenharmony_ci frame_entry_address<const byte*>(re_frame, kInputStart), 12531cb0ef41Sopenharmony_ci frame_entry_address<const byte*>(re_frame, kInputEnd)); 12541cb0ef41Sopenharmony_ci} 12551cb0ef41Sopenharmony_ci 12561cb0ef41Sopenharmony_ciMemOperand RegExpMacroAssemblerS390::register_location(int register_index) { 12571cb0ef41Sopenharmony_ci DCHECK(register_index < (1 << 30)); 12581cb0ef41Sopenharmony_ci if (num_registers_ <= register_index) { 12591cb0ef41Sopenharmony_ci num_registers_ = register_index + 1; 12601cb0ef41Sopenharmony_ci } 12611cb0ef41Sopenharmony_ci return MemOperand(frame_pointer(), 12621cb0ef41Sopenharmony_ci kRegisterZero - register_index * kSystemPointerSize); 12631cb0ef41Sopenharmony_ci} 12641cb0ef41Sopenharmony_ci 12651cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckPosition(int cp_offset, 12661cb0ef41Sopenharmony_ci Label* on_outside_input) { 12671cb0ef41Sopenharmony_ci if (cp_offset >= 0) { 12681cb0ef41Sopenharmony_ci __ CmpS64(current_input_offset(), Operand(-cp_offset * char_size())); 12691cb0ef41Sopenharmony_ci BranchOrBacktrack(ge, on_outside_input); 12701cb0ef41Sopenharmony_ci } else { 12711cb0ef41Sopenharmony_ci __ LoadU64(r3, MemOperand(frame_pointer(), kStringStartMinusOne)); 12721cb0ef41Sopenharmony_ci __ AddS64(r2, current_input_offset(), Operand(cp_offset * char_size())); 12731cb0ef41Sopenharmony_ci __ CmpS64(r2, r3); 12741cb0ef41Sopenharmony_ci BranchOrBacktrack(le, on_outside_input); 12751cb0ef41Sopenharmony_ci } 12761cb0ef41Sopenharmony_ci} 12771cb0ef41Sopenharmony_ci 12781cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::BranchOrBacktrack(Condition condition, Label* to, 12791cb0ef41Sopenharmony_ci CRegister cr) { 12801cb0ef41Sopenharmony_ci if (condition == al) { // Unconditional. 12811cb0ef41Sopenharmony_ci if (to == nullptr) { 12821cb0ef41Sopenharmony_ci Backtrack(); 12831cb0ef41Sopenharmony_ci return; 12841cb0ef41Sopenharmony_ci } 12851cb0ef41Sopenharmony_ci __ b(to); 12861cb0ef41Sopenharmony_ci return; 12871cb0ef41Sopenharmony_ci } 12881cb0ef41Sopenharmony_ci if (to == nullptr) { 12891cb0ef41Sopenharmony_ci __ b(condition, &backtrack_label_); 12901cb0ef41Sopenharmony_ci return; 12911cb0ef41Sopenharmony_ci } 12921cb0ef41Sopenharmony_ci __ b(condition, to); 12931cb0ef41Sopenharmony_ci} 12941cb0ef41Sopenharmony_ci 12951cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::SafeCall(Label* to, Condition cond, 12961cb0ef41Sopenharmony_ci CRegister cr) { 12971cb0ef41Sopenharmony_ci Label skip; 12981cb0ef41Sopenharmony_ci __ b(NegateCondition(cond), &skip); 12991cb0ef41Sopenharmony_ci __ b(r14, to); 13001cb0ef41Sopenharmony_ci __ bind(&skip); 13011cb0ef41Sopenharmony_ci} 13021cb0ef41Sopenharmony_ci 13031cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::SafeReturn() { 13041cb0ef41Sopenharmony_ci __ pop(r14); 13051cb0ef41Sopenharmony_ci __ mov(ip, Operand(masm_->CodeObject())); 13061cb0ef41Sopenharmony_ci __ AddS64(r14, ip); 13071cb0ef41Sopenharmony_ci __ Ret(); 13081cb0ef41Sopenharmony_ci} 13091cb0ef41Sopenharmony_ci 13101cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::SafeCallTarget(Label* name) { 13111cb0ef41Sopenharmony_ci __ bind(name); 13121cb0ef41Sopenharmony_ci __ CleanseP(r14); 13131cb0ef41Sopenharmony_ci __ mov(r0, r14); 13141cb0ef41Sopenharmony_ci __ mov(ip, Operand(masm_->CodeObject())); 13151cb0ef41Sopenharmony_ci __ SubS64(r0, r0, ip); 13161cb0ef41Sopenharmony_ci __ push(r0); 13171cb0ef41Sopenharmony_ci} 13181cb0ef41Sopenharmony_ci 13191cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::Push(Register source) { 13201cb0ef41Sopenharmony_ci DCHECK(source != backtrack_stackpointer()); 13211cb0ef41Sopenharmony_ci __ lay(backtrack_stackpointer(), 13221cb0ef41Sopenharmony_ci MemOperand(backtrack_stackpointer(), -kSystemPointerSize)); 13231cb0ef41Sopenharmony_ci __ StoreU64(source, MemOperand(backtrack_stackpointer())); 13241cb0ef41Sopenharmony_ci} 13251cb0ef41Sopenharmony_ci 13261cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::Pop(Register target) { 13271cb0ef41Sopenharmony_ci DCHECK(target != backtrack_stackpointer()); 13281cb0ef41Sopenharmony_ci __ LoadU64(target, MemOperand(backtrack_stackpointer())); 13291cb0ef41Sopenharmony_ci __ la(backtrack_stackpointer(), 13301cb0ef41Sopenharmony_ci MemOperand(backtrack_stackpointer(), kSystemPointerSize)); 13311cb0ef41Sopenharmony_ci} 13321cb0ef41Sopenharmony_ci 13331cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckPreemption() { 13341cb0ef41Sopenharmony_ci // Check for preemption. 13351cb0ef41Sopenharmony_ci ExternalReference stack_limit = 13361cb0ef41Sopenharmony_ci ExternalReference::address_of_jslimit(isolate()); 13371cb0ef41Sopenharmony_ci __ mov(r2, Operand(stack_limit)); 13381cb0ef41Sopenharmony_ci __ CmpU64(sp, MemOperand(r2)); 13391cb0ef41Sopenharmony_ci SafeCall(&check_preempt_label_, le); 13401cb0ef41Sopenharmony_ci} 13411cb0ef41Sopenharmony_ci 13421cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CheckStackLimit() { 13431cb0ef41Sopenharmony_ci ExternalReference stack_limit = 13441cb0ef41Sopenharmony_ci ExternalReference::address_of_regexp_stack_limit_address(isolate()); 13451cb0ef41Sopenharmony_ci __ mov(r2, Operand(stack_limit)); 13461cb0ef41Sopenharmony_ci __ CmpU64(backtrack_stackpointer(), MemOperand(r2)); 13471cb0ef41Sopenharmony_ci SafeCall(&stack_overflow_label_, le); 13481cb0ef41Sopenharmony_ci} 13491cb0ef41Sopenharmony_ci 13501cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::CallCFunctionUsingStub( 13511cb0ef41Sopenharmony_ci ExternalReference function, int num_arguments) { 13521cb0ef41Sopenharmony_ci // Must pass all arguments in registers. The stub pushes on the stack. 13531cb0ef41Sopenharmony_ci DCHECK_GE(8, num_arguments); 13541cb0ef41Sopenharmony_ci __ mov(code_pointer(), Operand(function)); 13551cb0ef41Sopenharmony_ci Label ret; 13561cb0ef41Sopenharmony_ci __ larl(r14, &ret); 13571cb0ef41Sopenharmony_ci __ StoreU64(r14, MemOperand(sp, kStackFrameRASlot * kSystemPointerSize)); 13581cb0ef41Sopenharmony_ci __ b(code_pointer()); 13591cb0ef41Sopenharmony_ci __ bind(&ret); 13601cb0ef41Sopenharmony_ci if (base::OS::ActivationFrameAlignment() > kSystemPointerSize) { 13611cb0ef41Sopenharmony_ci __ LoadU64( 13621cb0ef41Sopenharmony_ci sp, MemOperand(sp, (kNumRequiredStackFrameSlots * kSystemPointerSize))); 13631cb0ef41Sopenharmony_ci } else { 13641cb0ef41Sopenharmony_ci __ la(sp, 13651cb0ef41Sopenharmony_ci MemOperand(sp, (kNumRequiredStackFrameSlots * kSystemPointerSize))); 13661cb0ef41Sopenharmony_ci } 13671cb0ef41Sopenharmony_ci __ mov(code_pointer(), Operand(masm_->CodeObject())); 13681cb0ef41Sopenharmony_ci} 13691cb0ef41Sopenharmony_ci 13701cb0ef41Sopenharmony_ci 13711cb0ef41Sopenharmony_civoid RegExpMacroAssemblerS390::LoadCurrentCharacterUnchecked(int cp_offset, 13721cb0ef41Sopenharmony_ci int characters) { 13731cb0ef41Sopenharmony_ci if (mode_ == LATIN1) { 13741cb0ef41Sopenharmony_ci // using load reverse for big-endian platforms 13751cb0ef41Sopenharmony_ci if (characters == 4) { 13761cb0ef41Sopenharmony_ci __ LoadU32LE(current_character(), 13771cb0ef41Sopenharmony_ci MemOperand(current_input_offset(), end_of_input_address(), 13781cb0ef41Sopenharmony_ci cp_offset * char_size())); 13791cb0ef41Sopenharmony_ci } else if (characters == 2) { 13801cb0ef41Sopenharmony_ci __ LoadU16LE(current_character(), 13811cb0ef41Sopenharmony_ci MemOperand(current_input_offset(), end_of_input_address(), 13821cb0ef41Sopenharmony_ci cp_offset * char_size())); 13831cb0ef41Sopenharmony_ci } else { 13841cb0ef41Sopenharmony_ci DCHECK_EQ(1, characters); 13851cb0ef41Sopenharmony_ci __ LoadU8(current_character(), 13861cb0ef41Sopenharmony_ci MemOperand(current_input_offset(), end_of_input_address(), 13871cb0ef41Sopenharmony_ci cp_offset * char_size())); 13881cb0ef41Sopenharmony_ci } 13891cb0ef41Sopenharmony_ci } else { 13901cb0ef41Sopenharmony_ci DCHECK(mode_ == UC16); 13911cb0ef41Sopenharmony_ci if (characters == 2) { 13921cb0ef41Sopenharmony_ci __ LoadU32(current_character(), 13931cb0ef41Sopenharmony_ci MemOperand(current_input_offset(), end_of_input_address(), 13941cb0ef41Sopenharmony_ci cp_offset * char_size())); 13951cb0ef41Sopenharmony_ci#if !V8_TARGET_LITTLE_ENDIAN 13961cb0ef41Sopenharmony_ci // need to swap the order of the characters for big-endian platforms 13971cb0ef41Sopenharmony_ci __ rll(current_character(), current_character(), Operand(16)); 13981cb0ef41Sopenharmony_ci#endif 13991cb0ef41Sopenharmony_ci } else { 14001cb0ef41Sopenharmony_ci DCHECK_EQ(1, characters); 14011cb0ef41Sopenharmony_ci __ LoadU16( 14021cb0ef41Sopenharmony_ci current_character(), 14031cb0ef41Sopenharmony_ci MemOperand(current_input_offset(), end_of_input_address(), 14041cb0ef41Sopenharmony_ci cp_offset * char_size())); 14051cb0ef41Sopenharmony_ci } 14061cb0ef41Sopenharmony_ci } 14071cb0ef41Sopenharmony_ci} 14081cb0ef41Sopenharmony_ci 14091cb0ef41Sopenharmony_ci#undef __ 14101cb0ef41Sopenharmony_ci 14111cb0ef41Sopenharmony_ci} // namespace internal 14121cb0ef41Sopenharmony_ci} // namespace v8 14131cb0ef41Sopenharmony_ci 14141cb0ef41Sopenharmony_ci#endif // V8_TARGET_ARCH_S390 1415