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