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