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