1/* 2 * Copyright (C) 2013 Cisco Systems, Inc. All rights reserved. 3 * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved. 4 * Copyright (C) 2008 Apple Inc. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26*/ 27 28#ifndef MacroAssemblerSH4_h 29#define MacroAssemblerSH4_h 30 31#if ENABLE(ASSEMBLER) && CPU(SH4) 32 33#include "SH4Assembler.h" 34#include "AbstractMacroAssembler.h" 35#include <wtf/Assertions.h> 36 37namespace JSC { 38 39class MacroAssemblerSH4 : public AbstractMacroAssembler<SH4Assembler> { 40public: 41 typedef SH4Assembler::FPRegisterID FPRegisterID; 42 43 static const Scale ScalePtr = TimesFour; 44 static const FPRegisterID fscratch = SH4Registers::dr10; 45 static const RegisterID stackPointerRegister = SH4Registers::sp; 46 static const RegisterID framePointerRegister = SH4Registers::fp; 47 static const RegisterID linkRegister = SH4Registers::pr; 48 static const RegisterID scratchReg3 = SH4Registers::r13; 49 50 static const int MaximumCompactPtrAlignedAddressOffset = 60; 51 52 static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value) 53 { 54 return (value >= 0) && (value <= MaximumCompactPtrAlignedAddressOffset) && (!(value & 3)); 55 } 56 57 enum RelationalCondition { 58 Equal = SH4Assembler::EQ, 59 NotEqual = SH4Assembler::NE, 60 Above = SH4Assembler::HI, 61 AboveOrEqual = SH4Assembler::HS, 62 Below = SH4Assembler::LI, 63 BelowOrEqual = SH4Assembler::LS, 64 GreaterThan = SH4Assembler::GT, 65 GreaterThanOrEqual = SH4Assembler::GE, 66 LessThan = SH4Assembler::LT, 67 LessThanOrEqual = SH4Assembler::LE 68 }; 69 70 enum ResultCondition { 71 Overflow = SH4Assembler::OF, 72 Signed = SH4Assembler::SI, 73 PositiveOrZero = SH4Assembler::NS, 74 Zero = SH4Assembler::EQ, 75 NonZero = SH4Assembler::NE 76 }; 77 78 enum DoubleCondition { 79 // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN. 80 DoubleEqual = SH4Assembler::EQ, 81 DoubleNotEqual = SH4Assembler::NE, 82 DoubleGreaterThan = SH4Assembler::GT, 83 DoubleGreaterThanOrEqual = SH4Assembler::GE, 84 DoubleLessThan = SH4Assembler::LT, 85 DoubleLessThanOrEqual = SH4Assembler::LE, 86 // If either operand is NaN, these conditions always evaluate to true. 87 DoubleEqualOrUnordered = SH4Assembler::EQU, 88 DoubleNotEqualOrUnordered = SH4Assembler::NEU, 89 DoubleGreaterThanOrUnordered = SH4Assembler::GTU, 90 DoubleGreaterThanOrEqualOrUnordered = SH4Assembler::GEU, 91 DoubleLessThanOrUnordered = SH4Assembler::LTU, 92 DoubleLessThanOrEqualOrUnordered = SH4Assembler::LEU, 93 }; 94 95 RegisterID claimScratch() 96 { 97 return m_assembler.claimScratch(); 98 } 99 100 void releaseScratch(RegisterID reg) 101 { 102 m_assembler.releaseScratch(reg); 103 } 104 105 static RelationalCondition invert(RelationalCondition cond) 106 { 107 switch (cond) { 108 case Equal: 109 return NotEqual; 110 case NotEqual: 111 return Equal; 112 case Above: 113 return BelowOrEqual; 114 case AboveOrEqual: 115 return Below; 116 case Below: 117 return AboveOrEqual; 118 case BelowOrEqual: 119 return Above; 120 case GreaterThan: 121 return LessThanOrEqual; 122 case GreaterThanOrEqual: 123 return LessThan; 124 case LessThan: 125 return GreaterThanOrEqual; 126 case LessThanOrEqual: 127 return GreaterThan; 128 default: 129 RELEASE_ASSERT_NOT_REACHED(); 130 } 131 } 132 133 // Integer arithmetic operations 134 135 void add32(RegisterID src, RegisterID dest) 136 { 137 m_assembler.addlRegReg(src, dest); 138 } 139 140 void add32(RegisterID src1, RegisterID src2, RegisterID dest) 141 { 142 if (src1 == dest) 143 add32(src2, dest); 144 else { 145 move(src2, dest); 146 add32(src1, dest); 147 } 148 } 149 150 void add32(TrustedImm32 imm, RegisterID dest) 151 { 152 if (!imm.m_value) 153 return; 154 155 if (m_assembler.isImmediate(imm.m_value)) { 156 m_assembler.addlImm8r(imm.m_value, dest); 157 return; 158 } 159 160 RegisterID scr = claimScratch(); 161 m_assembler.loadConstant(imm.m_value, scr); 162 m_assembler.addlRegReg(scr, dest); 163 releaseScratch(scr); 164 } 165 166 void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) 167 { 168 move(src, dest); 169 add32(imm, dest); 170 } 171 172 void add32(TrustedImm32 imm, Address address) 173 { 174 if (!imm.m_value) 175 return; 176 177 RegisterID scr = claimScratch(); 178 load32(address, scr); 179 add32(imm, scr); 180 store32(scr, address); 181 releaseScratch(scr); 182 } 183 184 void add32(Address src, RegisterID dest) 185 { 186 RegisterID scr = claimScratch(); 187 load32(src, scr); 188 m_assembler.addlRegReg(scr, dest); 189 releaseScratch(scr); 190 } 191 192 void add32(AbsoluteAddress src, RegisterID dest) 193 { 194 RegisterID scr = claimScratch(); 195 load32(src.m_ptr, scr); 196 m_assembler.addlRegReg(scr, dest); 197 releaseScratch(scr); 198 } 199 200 void and32(RegisterID src, RegisterID dest) 201 { 202 m_assembler.andlRegReg(src, dest); 203 } 204 205 void and32(RegisterID src1, RegisterID src2, RegisterID dest) 206 { 207 if (src1 == dest) 208 and32(src2, dest); 209 else { 210 move(src2, dest); 211 and32(src1, dest); 212 } 213 } 214 215 void and32(Address src, RegisterID dest) 216 { 217 RegisterID scr = claimScratch(); 218 load32(src, scr); 219 and32(scr, dest); 220 releaseScratch(scr); 221 } 222 223 void and32(TrustedImm32 imm, RegisterID dest) 224 { 225 if (!imm.m_value) { 226 m_assembler.movImm8(0, dest); 227 return; 228 } 229 230 if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) { 231 m_assembler.andlImm8r(imm.m_value, dest); 232 return; 233 } 234 235 RegisterID scr = claimScratch(); 236 m_assembler.loadConstant(imm.m_value, scr); 237 m_assembler.andlRegReg(scr, dest); 238 releaseScratch(scr); 239 } 240 241 void and32(TrustedImm32 imm, RegisterID src, RegisterID dest) 242 { 243 if (src != dest) { 244 move(imm, dest); 245 and32(src, dest); 246 return; 247 } 248 249 and32(imm, dest); 250 } 251 252 void lshift32(RegisterID shiftamount, RegisterID dest) 253 { 254 RegisterID shiftTmp = claimScratch(); 255 m_assembler.loadConstant(0x1f, shiftTmp); 256 m_assembler.andlRegReg(shiftamount, shiftTmp); 257 m_assembler.shldRegReg(dest, shiftTmp); 258 releaseScratch(shiftTmp); 259 } 260 261 void lshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) 262 { 263 move(src, dest); 264 lshift32(shiftAmount, dest); 265 } 266 267 void lshift32(TrustedImm32 imm, RegisterID dest) 268 { 269 int immMasked = imm.m_value & 0x1f; 270 if (!immMasked) 271 return; 272 273 if ((immMasked == 1) || (immMasked == 2) || (immMasked == 8) || (immMasked == 16)) { 274 m_assembler.shllImm8r(immMasked, dest); 275 return; 276 } 277 278 RegisterID shiftTmp = claimScratch(); 279 m_assembler.loadConstant(immMasked, shiftTmp); 280 m_assembler.shldRegReg(dest, shiftTmp); 281 releaseScratch(shiftTmp); 282 } 283 284 void lshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest) 285 { 286 move(src, dest); 287 lshift32(shiftamount, dest); 288 } 289 290 void mul32(RegisterID src, RegisterID dest) 291 { 292 mul32(src, dest, dest); 293 } 294 295 void mul32(RegisterID src1, RegisterID src2, RegisterID dest) 296 { 297 m_assembler.imullRegReg(src1, src2); 298 m_assembler.stsmacl(dest); 299 } 300 301 void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest) 302 { 303 if (src == dest) { 304 RegisterID immval = claimScratch(); 305 move(imm, immval); 306 mul32(immval, dest); 307 releaseScratch(immval); 308 } else { 309 move(imm, dest); 310 mul32(src, dest); 311 } 312 } 313 314 void or32(RegisterID src, RegisterID dest) 315 { 316 m_assembler.orlRegReg(src, dest); 317 } 318 319 void or32(TrustedImm32 imm, RegisterID dest) 320 { 321 if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) { 322 m_assembler.orlImm8r(imm.m_value, dest); 323 return; 324 } 325 326 RegisterID scr = claimScratch(); 327 m_assembler.loadConstant(imm.m_value, scr); 328 m_assembler.orlRegReg(scr, dest); 329 releaseScratch(scr); 330 } 331 332 void or32(RegisterID op1, RegisterID op2, RegisterID dest) 333 { 334 if (op1 == op2) 335 move(op1, dest); 336 else if (op1 == dest) 337 or32(op2, dest); 338 else { 339 move(op2, dest); 340 or32(op1, dest); 341 } 342 } 343 344 void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) 345 { 346 if (src != dest) { 347 move(imm, dest); 348 or32(src, dest); 349 return; 350 } 351 352 or32(imm, dest); 353 } 354 355 void or32(RegisterID src, AbsoluteAddress address) 356 { 357 RegisterID destptr = claimScratch(); 358 move(TrustedImmPtr(address.m_ptr), destptr); 359 RegisterID destval = claimScratch(); 360 m_assembler.movlMemReg(destptr, destval); 361 m_assembler.orlRegReg(src, destval); 362 m_assembler.movlRegMem(destval, destptr); 363 releaseScratch(destval); 364 releaseScratch(destptr); 365 } 366 367 void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest) 368 { 369 if (src != dest) { 370 move(imm, dest); 371 xor32(src, dest); 372 return; 373 } 374 375 xor32(imm, dest); 376 } 377 378 void rshift32(RegisterID shiftamount, RegisterID dest) 379 { 380 RegisterID shiftTmp = claimScratch(); 381 m_assembler.loadConstant(0x1f, shiftTmp); 382 m_assembler.andlRegReg(shiftamount, shiftTmp); 383 m_assembler.neg(shiftTmp, shiftTmp); 384 m_assembler.shadRegReg(dest, shiftTmp); 385 releaseScratch(shiftTmp); 386 } 387 388 void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) 389 { 390 move(src, dest); 391 rshift32(shiftAmount, dest); 392 } 393 394 void rshift32(TrustedImm32 imm, RegisterID dest) 395 { 396 int immMasked = imm.m_value & 0x1f; 397 if (!immMasked) 398 return; 399 400 if (immMasked == 1) { 401 m_assembler.sharImm8r(immMasked, dest); 402 return; 403 } 404 405 RegisterID shiftTmp = claimScratch(); 406 m_assembler.loadConstant(-immMasked, shiftTmp); 407 m_assembler.shadRegReg(dest, shiftTmp); 408 releaseScratch(shiftTmp); 409 } 410 411 void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) 412 { 413 move(src, dest); 414 rshift32(imm, dest); 415 } 416 417 void sub32(RegisterID src, RegisterID dest) 418 { 419 m_assembler.sublRegReg(src, dest); 420 } 421 422 void sub32(TrustedImm32 imm, AbsoluteAddress address) 423 { 424 if (!imm.m_value) 425 return; 426 427 RegisterID result = claimScratch(); 428 RegisterID scratchReg = claimScratch(); 429 430 move(TrustedImmPtr(address.m_ptr), scratchReg); 431 m_assembler.movlMemReg(scratchReg, result); 432 433 if (m_assembler.isImmediate(-imm.m_value)) 434 m_assembler.addlImm8r(-imm.m_value, result); 435 else { 436 m_assembler.loadConstant(imm.m_value, scratchReg3); 437 m_assembler.sublRegReg(scratchReg3, result); 438 } 439 440 store32(result, scratchReg); 441 releaseScratch(result); 442 releaseScratch(scratchReg); 443 } 444 445 void sub32(TrustedImm32 imm, Address address) 446 { 447 add32(TrustedImm32(-imm.m_value), address); 448 } 449 450 void add32(TrustedImm32 imm, AbsoluteAddress address) 451 { 452 if (!imm.m_value) 453 return; 454 455 RegisterID result = claimScratch(); 456 RegisterID scratchReg = claimScratch(); 457 458 move(TrustedImmPtr(address.m_ptr), scratchReg); 459 m_assembler.movlMemReg(scratchReg, result); 460 461 if (m_assembler.isImmediate(imm.m_value)) 462 m_assembler.addlImm8r(imm.m_value, result); 463 else { 464 m_assembler.loadConstant(imm.m_value, scratchReg3); 465 m_assembler.addlRegReg(scratchReg3, result); 466 } 467 468 store32(result, scratchReg); 469 releaseScratch(result); 470 releaseScratch(scratchReg); 471 } 472 473 void add64(TrustedImm32 imm, AbsoluteAddress address) 474 { 475 RegisterID scr1 = claimScratch(); 476 RegisterID scr2 = claimScratch(); 477 478 // Add 32-bit LSB first. 479 move(TrustedImmPtr(address.m_ptr), scratchReg3); 480 m_assembler.movlMemReg(scratchReg3, scr1); // scr1 = 32-bit LSB of int64 @ address 481 m_assembler.loadConstant(imm.m_value, scr2); 482 m_assembler.clrt(); 483 m_assembler.addclRegReg(scr1, scr2); 484 m_assembler.movlRegMem(scr2, scratchReg3); // Update address with 32-bit LSB result. 485 486 // Then add 32-bit MSB. 487 m_assembler.addlImm8r(4, scratchReg3); 488 m_assembler.movlMemReg(scratchReg3, scr1); // scr1 = 32-bit MSB of int64 @ address 489 m_assembler.movt(scr2); 490 if (imm.m_value < 0) 491 m_assembler.addlImm8r(-1, scr2); // Sign extend imm value if needed. 492 m_assembler.addvlRegReg(scr2, scr1); 493 m_assembler.movlRegMem(scr1, scratchReg3); // Update (address + 4) with 32-bit MSB result. 494 495 releaseScratch(scr2); 496 releaseScratch(scr1); 497 } 498 499 void sub32(TrustedImm32 imm, RegisterID dest) 500 { 501 if (!imm.m_value) 502 return; 503 504 if (m_assembler.isImmediate(-imm.m_value)) { 505 m_assembler.addlImm8r(-imm.m_value, dest); 506 return; 507 } 508 509 RegisterID scr = claimScratch(); 510 m_assembler.loadConstant(imm.m_value, scr); 511 m_assembler.sublRegReg(scr, dest); 512 releaseScratch(scr); 513 } 514 515 void sub32(Address src, RegisterID dest) 516 { 517 RegisterID scr = claimScratch(); 518 load32(src, scr); 519 m_assembler.sublRegReg(scr, dest); 520 releaseScratch(scr); 521 } 522 523 void xor32(RegisterID src, RegisterID dest) 524 { 525 m_assembler.xorlRegReg(src, dest); 526 } 527 528 void xor32(RegisterID src1, RegisterID src2, RegisterID dest) 529 { 530 if (src1 == dest) 531 xor32(src2, dest); 532 else { 533 move(src2, dest); 534 xor32(src1, dest); 535 } 536 } 537 538 void xor32(TrustedImm32 imm, RegisterID srcDest) 539 { 540 if (imm.m_value == -1) { 541 m_assembler.notlReg(srcDest, srcDest); 542 return; 543 } 544 545 if ((srcDest != SH4Registers::r0) || (imm.m_value > 255) || (imm.m_value < 0)) { 546 RegisterID scr = claimScratch(); 547 m_assembler.loadConstant(imm.m_value, scr); 548 m_assembler.xorlRegReg(scr, srcDest); 549 releaseScratch(scr); 550 return; 551 } 552 553 m_assembler.xorlImm8r(imm.m_value, srcDest); 554 } 555 556 void compare32(int imm, RegisterID dst, RelationalCondition cond) 557 { 558 if (((cond == Equal) || (cond == NotEqual)) && (dst == SH4Registers::r0) && m_assembler.isImmediate(imm)) { 559 m_assembler.cmpEqImmR0(imm, dst); 560 return; 561 } 562 563 if (((cond == Equal) || (cond == NotEqual)) && !imm) { 564 m_assembler.testlRegReg(dst, dst); 565 return; 566 } 567 568 RegisterID scr = claimScratch(); 569 m_assembler.loadConstant(imm, scr); 570 m_assembler.cmplRegReg(scr, dst, SH4Condition(cond)); 571 releaseScratch(scr); 572 } 573 574 void compare32(int offset, RegisterID base, RegisterID left, RelationalCondition cond) 575 { 576 RegisterID scr = claimScratch(); 577 if (!offset) { 578 m_assembler.movlMemReg(base, scr); 579 m_assembler.cmplRegReg(scr, left, SH4Condition(cond)); 580 releaseScratch(scr); 581 return; 582 } 583 584 if ((offset < 0) || (offset >= 64)) { 585 m_assembler.loadConstant(offset, scr); 586 m_assembler.addlRegReg(base, scr); 587 m_assembler.movlMemReg(scr, scr); 588 m_assembler.cmplRegReg(scr, left, SH4Condition(cond)); 589 releaseScratch(scr); 590 return; 591 } 592 593 m_assembler.movlMemReg(offset >> 2, base, scr); 594 m_assembler.cmplRegReg(scr, left, SH4Condition(cond)); 595 releaseScratch(scr); 596 } 597 598 void testImm(int imm, int offset, RegisterID base) 599 { 600 RegisterID scr = claimScratch(); 601 load32(base, offset, scr); 602 603 RegisterID scr1 = claimScratch(); 604 move(TrustedImm32(imm), scr1); 605 606 m_assembler.testlRegReg(scr, scr1); 607 releaseScratch(scr); 608 releaseScratch(scr1); 609 } 610 611 void testlImm(int imm, RegisterID dst) 612 { 613 if ((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0)) { 614 m_assembler.testlImm8r(imm, dst); 615 return; 616 } 617 618 RegisterID scr = claimScratch(); 619 m_assembler.loadConstant(imm, scr); 620 m_assembler.testlRegReg(scr, dst); 621 releaseScratch(scr); 622 } 623 624 void compare32(RegisterID right, int offset, RegisterID base, RelationalCondition cond) 625 { 626 if (!offset) { 627 RegisterID scr = claimScratch(); 628 m_assembler.movlMemReg(base, scr); 629 m_assembler.cmplRegReg(right, scr, SH4Condition(cond)); 630 releaseScratch(scr); 631 return; 632 } 633 634 if ((offset < 0) || (offset >= 64)) { 635 RegisterID scr = claimScratch(); 636 m_assembler.loadConstant(offset, scr); 637 m_assembler.addlRegReg(base, scr); 638 m_assembler.movlMemReg(scr, scr); 639 m_assembler.cmplRegReg(right, scr, SH4Condition(cond)); 640 releaseScratch(scr); 641 return; 642 } 643 644 RegisterID scr = claimScratch(); 645 m_assembler.movlMemReg(offset >> 2, base, scr); 646 m_assembler.cmplRegReg(right, scr, SH4Condition(cond)); 647 releaseScratch(scr); 648 } 649 650 void compare32(int imm, int offset, RegisterID base, RelationalCondition cond) 651 { 652 RegisterID scr = claimScratch(); 653 load32(base, offset, scr); 654 655 RegisterID scr1 = claimScratch(); 656 move(TrustedImm32(imm), scr1); 657 658 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond)); 659 660 releaseScratch(scr1); 661 releaseScratch(scr); 662 } 663 664 // Memory access operation 665 666 ALWAYS_INLINE void loadEffectiveAddress(BaseIndex address, RegisterID dest, int extraoffset = 0) 667 { 668 if (dest == address.base) { 669 RegisterID scaledIndex = claimScratch(); 670 move(address.index, scaledIndex); 671 lshift32(TrustedImm32(address.scale), scaledIndex); 672 add32(scaledIndex, dest); 673 releaseScratch(scaledIndex); 674 } else { 675 move(address.index, dest); 676 lshift32(TrustedImm32(address.scale), dest); 677 add32(address.base, dest); 678 } 679 680 add32(TrustedImm32(address.offset + extraoffset), dest); 681 } 682 683 void load32(ImplicitAddress address, RegisterID dest) 684 { 685 load32(address.base, address.offset, dest); 686 } 687 688 void load8(ImplicitAddress address, RegisterID dest) 689 { 690 load8(address.base, address.offset, dest); 691 } 692 693 void load8(BaseIndex address, RegisterID dest) 694 { 695 RegisterID scr = claimScratch(); 696 move(address.index, scr); 697 lshift32(TrustedImm32(address.scale), scr); 698 add32(address.base, scr); 699 load8(scr, address.offset, dest); 700 releaseScratch(scr); 701 } 702 703 void load8(AbsoluteAddress address, RegisterID dest) 704 { 705 move(TrustedImmPtr(address.m_ptr), dest); 706 m_assembler.movbMemReg(dest, dest); 707 m_assembler.extub(dest, dest); 708 } 709 710 void load8(const void* address, RegisterID dest) 711 { 712 load8(AbsoluteAddress(address), dest); 713 } 714 715 void load8PostInc(RegisterID base, RegisterID dest) 716 { 717 m_assembler.movbMemRegIn(base, dest); 718 m_assembler.extub(dest, dest); 719 } 720 721 void load8Signed(BaseIndex address, RegisterID dest) 722 { 723 RegisterID scr = claimScratch(); 724 move(address.index, scr); 725 lshift32(TrustedImm32(address.scale), scr); 726 add32(address.base, scr); 727 load8Signed(scr, address.offset, dest); 728 releaseScratch(scr); 729 } 730 731 void load32(BaseIndex address, RegisterID dest) 732 { 733 RegisterID scr = claimScratch(); 734 move(address.index, scr); 735 lshift32(TrustedImm32(address.scale), scr); 736 add32(address.base, scr); 737 load32(scr, address.offset, dest); 738 releaseScratch(scr); 739 } 740 741 void load32(const void* address, RegisterID dest) 742 { 743 move(TrustedImmPtr(address), dest); 744 m_assembler.movlMemReg(dest, dest); 745 } 746 747 void load32(RegisterID base, int offset, RegisterID dest) 748 { 749 if (!offset) { 750 m_assembler.movlMemReg(base, dest); 751 return; 752 } 753 754 if ((offset >= 0) && (offset < 64)) { 755 m_assembler.movlMemReg(offset >> 2, base, dest); 756 return; 757 } 758 759 RegisterID scr = (dest == base) ? claimScratch() : dest; 760 761 m_assembler.loadConstant(offset, scr); 762 if (base == SH4Registers::r0) 763 m_assembler.movlR0mr(scr, dest); 764 else { 765 m_assembler.addlRegReg(base, scr); 766 m_assembler.movlMemReg(scr, dest); 767 } 768 769 if (dest == base) 770 releaseScratch(scr); 771 } 772 773 void load8Signed(RegisterID base, int offset, RegisterID dest) 774 { 775 if (!offset) { 776 m_assembler.movbMemReg(base, dest); 777 return; 778 } 779 780 if ((offset > 0) && (offset <= 15) && (dest == SH4Registers::r0)) { 781 m_assembler.movbMemReg(offset, base, dest); 782 return; 783 } 784 785 RegisterID scr = (dest == base) ? claimScratch() : dest; 786 787 m_assembler.loadConstant(offset, scr); 788 if (base == SH4Registers::r0) 789 m_assembler.movbR0mr(scr, dest); 790 else { 791 m_assembler.addlRegReg(base, scr); 792 m_assembler.movbMemReg(scr, dest); 793 } 794 795 if (dest == base) 796 releaseScratch(scr); 797 } 798 799 void load8(RegisterID base, int offset, RegisterID dest) 800 { 801 load8Signed(base, offset, dest); 802 m_assembler.extub(dest, dest); 803 } 804 805 void load32(RegisterID src, RegisterID dst) 806 { 807 m_assembler.movlMemReg(src, dst); 808 } 809 810 void load16(ImplicitAddress address, RegisterID dest) 811 { 812 if (!address.offset) { 813 m_assembler.movwMemReg(address.base, dest); 814 m_assembler.extuw(dest, dest); 815 return; 816 } 817 818 if ((address.offset > 0) && (address.offset <= 30) && (dest == SH4Registers::r0)) { 819 m_assembler.movwMemReg(address.offset >> 1, address.base, dest); 820 m_assembler.extuw(dest, dest); 821 return; 822 } 823 824 RegisterID scr = (dest == address.base) ? claimScratch() : dest; 825 826 m_assembler.loadConstant(address.offset, scr); 827 if (address.base == SH4Registers::r0) 828 m_assembler.movwR0mr(scr, dest); 829 else { 830 m_assembler.addlRegReg(address.base, scr); 831 m_assembler.movwMemReg(scr, dest); 832 } 833 m_assembler.extuw(dest, dest); 834 835 if (dest == address.base) 836 releaseScratch(scr); 837 } 838 839 void load16Unaligned(BaseIndex address, RegisterID dest) 840 { 841 RegisterID scr = claimScratch(); 842 843 loadEffectiveAddress(address, scr); 844 845 RegisterID scr1 = claimScratch(); 846 load8PostInc(scr, scr1); 847 load8(scr, dest); 848 m_assembler.shllImm8r(8, dest); 849 or32(scr1, dest); 850 851 releaseScratch(scr); 852 releaseScratch(scr1); 853 } 854 855 void load16(RegisterID src, RegisterID dest) 856 { 857 m_assembler.movwMemReg(src, dest); 858 m_assembler.extuw(dest, dest); 859 } 860 861 void load16Signed(RegisterID src, RegisterID dest) 862 { 863 m_assembler.movwMemReg(src, dest); 864 } 865 866 void load16(BaseIndex address, RegisterID dest) 867 { 868 load16Signed(address, dest); 869 m_assembler.extuw(dest, dest); 870 } 871 872 void load16PostInc(RegisterID base, RegisterID dest) 873 { 874 m_assembler.movwMemRegIn(base, dest); 875 m_assembler.extuw(dest, dest); 876 } 877 878 void load16Signed(BaseIndex address, RegisterID dest) 879 { 880 RegisterID scr = claimScratch(); 881 882 move(address.index, scr); 883 lshift32(TrustedImm32(address.scale), scr); 884 add32(TrustedImm32(address.offset), scr); 885 886 if (address.base == SH4Registers::r0) 887 m_assembler.movwR0mr(scr, dest); 888 else { 889 add32(address.base, scr); 890 load16Signed(scr, dest); 891 } 892 893 releaseScratch(scr); 894 } 895 896 void store8(RegisterID src, BaseIndex address) 897 { 898 RegisterID scr = claimScratch(); 899 900 move(address.index, scr); 901 lshift32(TrustedImm32(address.scale), scr); 902 add32(TrustedImm32(address.offset), scr); 903 904 if (address.base == SH4Registers::r0) 905 m_assembler.movbRegMemr0(src, scr); 906 else { 907 add32(address.base, scr); 908 m_assembler.movbRegMem(src, scr); 909 } 910 911 releaseScratch(scr); 912 } 913 914 void store8(RegisterID src, void* address) 915 { 916 RegisterID destptr = claimScratch(); 917 move(TrustedImmPtr(address), destptr); 918 m_assembler.movbRegMem(src, destptr); 919 releaseScratch(destptr); 920 } 921 922 void store8(TrustedImm32 imm, void* address) 923 { 924 ASSERT((imm.m_value >= -128) && (imm.m_value <= 127)); 925 RegisterID dstptr = claimScratch(); 926 move(TrustedImmPtr(address), dstptr); 927 RegisterID srcval = claimScratch(); 928 move(imm, srcval); 929 m_assembler.movbRegMem(srcval, dstptr); 930 releaseScratch(dstptr); 931 releaseScratch(srcval); 932 } 933 934 void store16(RegisterID src, BaseIndex address) 935 { 936 RegisterID scr = claimScratch(); 937 938 move(address.index, scr); 939 lshift32(TrustedImm32(address.scale), scr); 940 add32(TrustedImm32(address.offset), scr); 941 942 if (address.base == SH4Registers::r0) 943 m_assembler.movwRegMemr0(src, scr); 944 else { 945 add32(address.base, scr); 946 m_assembler.movwRegMem(src, scr); 947 } 948 949 releaseScratch(scr); 950 } 951 952 void store32(RegisterID src, ImplicitAddress address) 953 { 954 if (!address.offset) { 955 m_assembler.movlRegMem(src, address.base); 956 return; 957 } 958 959 if ((address.offset >= 0) && (address.offset < 64)) { 960 m_assembler.movlRegMem(src, address.offset >> 2, address.base); 961 return; 962 } 963 964 RegisterID scr = claimScratch(); 965 m_assembler.loadConstant(address.offset, scr); 966 if (address.base == SH4Registers::r0) 967 m_assembler.movlRegMemr0(src, scr); 968 else { 969 m_assembler.addlRegReg(address.base, scr); 970 m_assembler.movlRegMem(src, scr); 971 } 972 releaseScratch(scr); 973 } 974 975 void store32(RegisterID src, RegisterID dst) 976 { 977 m_assembler.movlRegMem(src, dst); 978 } 979 980 void store32(TrustedImm32 imm, ImplicitAddress address) 981 { 982 RegisterID scr = claimScratch(); 983 m_assembler.loadConstant(imm.m_value, scr); 984 store32(scr, address); 985 releaseScratch(scr); 986 } 987 988 void store32(RegisterID src, BaseIndex address) 989 { 990 RegisterID scr = claimScratch(); 991 992 move(address.index, scr); 993 lshift32(TrustedImm32(address.scale), scr); 994 add32(address.base, scr); 995 store32(src, Address(scr, address.offset)); 996 997 releaseScratch(scr); 998 } 999 1000 void store32(TrustedImm32 imm, void* address) 1001 { 1002 RegisterID scr = claimScratch(); 1003 RegisterID scr1 = claimScratch(); 1004 m_assembler.loadConstant(imm.m_value, scr); 1005 move(TrustedImmPtr(address), scr1); 1006 m_assembler.movlRegMem(scr, scr1); 1007 releaseScratch(scr); 1008 releaseScratch(scr1); 1009 } 1010 1011 void store32(RegisterID src, void* address) 1012 { 1013 RegisterID scr = claimScratch(); 1014 move(TrustedImmPtr(address), scr); 1015 m_assembler.movlRegMem(src, scr); 1016 releaseScratch(scr); 1017 } 1018 1019 void store32(TrustedImm32 imm, BaseIndex address) 1020 { 1021 RegisterID destptr = claimScratch(); 1022 1023 loadEffectiveAddress(address, destptr); 1024 1025 RegisterID srcval = claimScratch(); 1026 move(imm, srcval); 1027 m_assembler.movlRegMem(srcval, destptr); 1028 releaseScratch(srcval); 1029 releaseScratch(destptr); 1030 } 1031 1032 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest) 1033 { 1034 RegisterID scr = claimScratch(); 1035 DataLabel32 label(this); 1036 m_assembler.loadConstantUnReusable(address.offset, scr); 1037 m_assembler.addlRegReg(address.base, scr); 1038 m_assembler.movlMemReg(scr, dest); 1039 releaseScratch(scr); 1040 return label; 1041 } 1042 1043 DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address) 1044 { 1045 RegisterID scr = claimScratch(); 1046 DataLabel32 label(this); 1047 m_assembler.loadConstantUnReusable(address.offset, scr); 1048 m_assembler.addlRegReg(address.base, scr); 1049 m_assembler.movlRegMem(src, scr); 1050 releaseScratch(scr); 1051 return label; 1052 } 1053 1054 DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest) 1055 { 1056 DataLabelCompact dataLabel(this); 1057 ASSERT(isCompactPtrAlignedAddressOffset(address.offset)); 1058 m_assembler.movlMemRegCompact(address.offset >> 2, address.base, dest); 1059 return dataLabel; 1060 } 1061 1062 ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest) 1063 { 1064 ConvertibleLoadLabel result(this); 1065 1066 RegisterID scr = claimScratch(); 1067 m_assembler.movImm8(address.offset, scr); 1068 m_assembler.addlRegReg(address.base, scr); 1069 m_assembler.movlMemReg(scr, dest); 1070 releaseScratch(scr); 1071 1072 return result; 1073 } 1074 1075 // Floating-point operations 1076 1077 static bool supportsFloatingPoint() { return true; } 1078 static bool supportsFloatingPointTruncate() { return true; } 1079 static bool supportsFloatingPointSqrt() { return true; } 1080 static bool supportsFloatingPointAbs() { return true; } 1081 1082 void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2) 1083 { 1084 m_assembler.fldsfpul((FPRegisterID)(src + 1)); 1085 m_assembler.stsfpulReg(dest1); 1086 m_assembler.fldsfpul(src); 1087 m_assembler.stsfpulReg(dest2); 1088 } 1089 1090 void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID) 1091 { 1092 m_assembler.ldsrmfpul(src1); 1093 m_assembler.fstsfpul((FPRegisterID)(dest + 1)); 1094 m_assembler.ldsrmfpul(src2); 1095 m_assembler.fstsfpul(dest); 1096 } 1097 1098 void moveDouble(FPRegisterID src, FPRegisterID dest) 1099 { 1100 if (src != dest) { 1101 m_assembler.fmovsRegReg((FPRegisterID)(src + 1), (FPRegisterID)(dest + 1)); 1102 m_assembler.fmovsRegReg(src, dest); 1103 } 1104 } 1105 1106 void swapDouble(FPRegisterID fr1, FPRegisterID fr2) 1107 { 1108 if (fr1 != fr2) { 1109 m_assembler.fldsfpul((FPRegisterID)(fr1 + 1)); 1110 m_assembler.fmovsRegReg((FPRegisterID)(fr2 + 1), (FPRegisterID)(fr1 + 1)); 1111 m_assembler.fstsfpul((FPRegisterID)(fr2 + 1)); 1112 m_assembler.fldsfpul(fr1); 1113 m_assembler.fmovsRegReg(fr2, fr1); 1114 m_assembler.fstsfpul(fr2); 1115 } 1116 } 1117 1118 void loadFloat(BaseIndex address, FPRegisterID dest) 1119 { 1120 RegisterID scr = claimScratch(); 1121 1122 loadEffectiveAddress(address, scr); 1123 1124 m_assembler.fmovsReadrm(scr, dest); 1125 releaseScratch(scr); 1126 } 1127 1128 void loadDouble(BaseIndex address, FPRegisterID dest) 1129 { 1130 RegisterID scr = claimScratch(); 1131 1132 loadEffectiveAddress(address, scr); 1133 1134 m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1)); 1135 m_assembler.fmovsReadrm(scr, dest); 1136 releaseScratch(scr); 1137 } 1138 1139 void loadDouble(ImplicitAddress address, FPRegisterID dest) 1140 { 1141 RegisterID scr = claimScratch(); 1142 1143 m_assembler.loadConstant(address.offset, scr); 1144 if (address.base == SH4Registers::r0) { 1145 m_assembler.fmovsReadr0r(scr, (FPRegisterID)(dest + 1)); 1146 m_assembler.addlImm8r(4, scr); 1147 m_assembler.fmovsReadr0r(scr, dest); 1148 releaseScratch(scr); 1149 return; 1150 } 1151 1152 m_assembler.addlRegReg(address.base, scr); 1153 m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1)); 1154 m_assembler.fmovsReadrm(scr, dest); 1155 releaseScratch(scr); 1156 } 1157 1158 void loadDouble(TrustedImmPtr address, FPRegisterID dest) 1159 { 1160 RegisterID scr = claimScratch(); 1161 move(address, scr); 1162 m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1)); 1163 m_assembler.fmovsReadrm(scr, dest); 1164 releaseScratch(scr); 1165 } 1166 1167 void storeFloat(FPRegisterID src, BaseIndex address) 1168 { 1169 RegisterID scr = claimScratch(); 1170 loadEffectiveAddress(address, scr); 1171 m_assembler.fmovsWriterm(src, scr); 1172 releaseScratch(scr); 1173 } 1174 1175 void storeDouble(FPRegisterID src, ImplicitAddress address) 1176 { 1177 RegisterID scr = claimScratch(); 1178 m_assembler.loadConstant(address.offset + 8, scr); 1179 m_assembler.addlRegReg(address.base, scr); 1180 m_assembler.fmovsWriterndec(src, scr); 1181 m_assembler.fmovsWriterndec((FPRegisterID)(src + 1), scr); 1182 releaseScratch(scr); 1183 } 1184 1185 void storeDouble(FPRegisterID src, BaseIndex address) 1186 { 1187 RegisterID scr = claimScratch(); 1188 1189 loadEffectiveAddress(address, scr, 8); 1190 1191 m_assembler.fmovsWriterndec(src, scr); 1192 m_assembler.fmovsWriterndec((FPRegisterID)(src + 1), scr); 1193 1194 releaseScratch(scr); 1195 } 1196 1197 void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) 1198 { 1199 if (op1 == dest) 1200 addDouble(op2, dest); 1201 else { 1202 moveDouble(op2, dest); 1203 addDouble(op1, dest); 1204 } 1205 } 1206 1207 void storeDouble(FPRegisterID src, TrustedImmPtr address) 1208 { 1209 RegisterID scr = claimScratch(); 1210 m_assembler.loadConstant(reinterpret_cast<uint32_t>(const_cast<void*>(address.m_value)) + 8, scr); 1211 m_assembler.fmovsWriterndec(src, scr); 1212 m_assembler.fmovsWriterndec((FPRegisterID)(src + 1), scr); 1213 releaseScratch(scr); 1214 } 1215 1216 void addDouble(FPRegisterID src, FPRegisterID dest) 1217 { 1218 m_assembler.daddRegReg(src, dest); 1219 } 1220 1221 void addDouble(AbsoluteAddress address, FPRegisterID dest) 1222 { 1223 loadDouble(TrustedImmPtr(address.m_ptr), fscratch); 1224 addDouble(fscratch, dest); 1225 } 1226 1227 void addDouble(Address address, FPRegisterID dest) 1228 { 1229 loadDouble(address, fscratch); 1230 addDouble(fscratch, dest); 1231 } 1232 1233 void subDouble(FPRegisterID src, FPRegisterID dest) 1234 { 1235 m_assembler.dsubRegReg(src, dest); 1236 } 1237 1238 void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) 1239 { 1240 if (op2 == dest) { 1241 moveDouble(op1, fscratch); 1242 subDouble(op2, fscratch); 1243 moveDouble(fscratch, dest); 1244 } else { 1245 moveDouble(op1, dest); 1246 subDouble(op2, dest); 1247 } 1248 } 1249 1250 void subDouble(Address address, FPRegisterID dest) 1251 { 1252 loadDouble(address, fscratch); 1253 subDouble(fscratch, dest); 1254 } 1255 1256 void mulDouble(FPRegisterID src, FPRegisterID dest) 1257 { 1258 m_assembler.dmulRegReg(src, dest); 1259 } 1260 1261 void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) 1262 { 1263 if (op1 == dest) 1264 mulDouble(op2, dest); 1265 else { 1266 moveDouble(op2, dest); 1267 mulDouble(op1, dest); 1268 } 1269 } 1270 1271 void mulDouble(Address address, FPRegisterID dest) 1272 { 1273 loadDouble(address, fscratch); 1274 mulDouble(fscratch, dest); 1275 } 1276 1277 void divDouble(FPRegisterID src, FPRegisterID dest) 1278 { 1279 m_assembler.ddivRegReg(src, dest); 1280 } 1281 1282 void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) 1283 { 1284 if (op2 == dest) { 1285 moveDouble(op1, fscratch); 1286 divDouble(op2, fscratch); 1287 moveDouble(fscratch, dest); 1288 } else { 1289 moveDouble(op1, dest); 1290 divDouble(op2, dest); 1291 } 1292 } 1293 1294 void negateDouble(FPRegisterID src, FPRegisterID dest) 1295 { 1296 moveDouble(src, dest); 1297 m_assembler.dneg(dest); 1298 } 1299 1300 void convertFloatToDouble(FPRegisterID src, FPRegisterID dst) 1301 { 1302 m_assembler.fldsfpul(src); 1303 m_assembler.dcnvsd(dst); 1304 } 1305 1306 void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst) 1307 { 1308 m_assembler.dcnvds(src); 1309 m_assembler.fstsfpul(dst); 1310 } 1311 1312 void convertInt32ToDouble(RegisterID src, FPRegisterID dest) 1313 { 1314 m_assembler.ldsrmfpul(src); 1315 m_assembler.floatfpulDreg(dest); 1316 } 1317 1318 void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest) 1319 { 1320 RegisterID scr = claimScratch(); 1321 load32(src.m_ptr, scr); 1322 convertInt32ToDouble(scr, dest); 1323 releaseScratch(scr); 1324 } 1325 1326 void convertInt32ToDouble(Address src, FPRegisterID dest) 1327 { 1328 RegisterID scr = claimScratch(); 1329 load32(src, scr); 1330 convertInt32ToDouble(scr, dest); 1331 releaseScratch(scr); 1332 } 1333 1334 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest) 1335 { 1336 RegisterID scr = claimScratch(); 1337 Jump m_jump; 1338 JumpList end; 1339 1340 loadEffectiveAddress(address, scr); 1341 1342 RegisterID scr1 = claimScratch(); 1343 if (dest != SH4Registers::r0) 1344 move(SH4Registers::r0, scr1); 1345 1346 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 58, sizeof(uint32_t)); 1347 move(scr, SH4Registers::r0); 1348 m_assembler.testlImm8r(0x3, SH4Registers::r0); 1349 m_jump = Jump(m_assembler.jne(), SH4Assembler::JumpNear); 1350 1351 if (dest != SH4Registers::r0) 1352 move(scr1, SH4Registers::r0); 1353 1354 load32(scr, dest); 1355 end.append(Jump(m_assembler.bra(), SH4Assembler::JumpNear)); 1356 m_assembler.nop(); 1357 m_jump.link(this); 1358 m_assembler.testlImm8r(0x1, SH4Registers::r0); 1359 1360 if (dest != SH4Registers::r0) 1361 move(scr1, SH4Registers::r0); 1362 1363 m_jump = Jump(m_assembler.jne(), SH4Assembler::JumpNear); 1364 load16PostInc(scr, scr1); 1365 load16(scr, dest); 1366 m_assembler.shllImm8r(16, dest); 1367 or32(scr1, dest); 1368 end.append(Jump(m_assembler.bra(), SH4Assembler::JumpNear)); 1369 m_assembler.nop(); 1370 m_jump.link(this); 1371 load8PostInc(scr, scr1); 1372 load16PostInc(scr, dest); 1373 m_assembler.shllImm8r(8, dest); 1374 or32(dest, scr1); 1375 load8(scr, dest); 1376 m_assembler.shllImm8r(8, dest); 1377 m_assembler.shllImm8r(16, dest); 1378 or32(scr1, dest); 1379 end.link(this); 1380 1381 releaseScratch(scr); 1382 releaseScratch(scr1); 1383 } 1384 1385 Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right) 1386 { 1387 RegisterID scr = scratchReg3; 1388 load32WithUnalignedHalfWords(left, scr); 1389 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value) 1390 m_assembler.testlRegReg(scr, scr); 1391 else 1392 compare32(right.m_value, scr, cond); 1393 1394 if (cond == NotEqual) 1395 return branchFalse(); 1396 return branchTrue(); 1397 } 1398 1399 Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch) 1400 { 1401 m_assembler.movImm8(0, scratchReg3); 1402 convertInt32ToDouble(scratchReg3, scratch); 1403 return branchDouble(DoubleNotEqual, reg, scratch); 1404 } 1405 1406 Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch) 1407 { 1408 m_assembler.movImm8(0, scratchReg3); 1409 convertInt32ToDouble(scratchReg3, scratch); 1410 return branchDouble(DoubleEqualOrUnordered, reg, scratch); 1411 } 1412 1413 Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right) 1414 { 1415 if (cond == DoubleEqual) { 1416 m_assembler.dcmppeq(right, left); 1417 return branchTrue(); 1418 } 1419 1420 if (cond == DoubleNotEqual) { 1421 JumpList end; 1422 m_assembler.dcmppeq(left, left); 1423 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); 1424 end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); 1425 m_assembler.dcmppeq(right, right); 1426 end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); 1427 m_assembler.dcmppeq(right, left); 1428 Jump m_jump = branchFalse(); 1429 end.link(this); 1430 return m_jump; 1431 } 1432 1433 if (cond == DoubleGreaterThan) { 1434 m_assembler.dcmppgt(right, left); 1435 return branchTrue(); 1436 } 1437 1438 if (cond == DoubleGreaterThanOrEqual) { 1439 JumpList end; 1440 m_assembler.dcmppeq(left, left); 1441 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); 1442 end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); 1443 m_assembler.dcmppeq(right, right); 1444 end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); 1445 m_assembler.dcmppgt(left, right); 1446 Jump m_jump = branchFalse(); 1447 end.link(this); 1448 return m_jump; 1449 } 1450 1451 if (cond == DoubleLessThan) { 1452 m_assembler.dcmppgt(left, right); 1453 return branchTrue(); 1454 } 1455 1456 if (cond == DoubleLessThanOrEqual) { 1457 JumpList end; 1458 m_assembler.dcmppeq(left, left); 1459 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); 1460 end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); 1461 m_assembler.dcmppeq(right, right); 1462 end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); 1463 m_assembler.dcmppgt(right, left); 1464 Jump m_jump = branchFalse(); 1465 end.link(this); 1466 return m_jump; 1467 } 1468 1469 if (cond == DoubleEqualOrUnordered) { 1470 JumpList takeBranch; 1471 m_assembler.dcmppeq(left, left); 1472 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); 1473 takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); 1474 m_assembler.dcmppeq(right, right); 1475 takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); 1476 m_assembler.dcmppeq(left, right); 1477 m_assembler.branch(BF_OPCODE, 2); 1478 takeBranch.link(this); 1479 return Jump(m_assembler.extraInstrForBranch(scratchReg3)); 1480 } 1481 1482 if (cond == DoubleGreaterThanOrUnordered) { 1483 JumpList takeBranch; 1484 m_assembler.dcmppeq(left, left); 1485 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); 1486 takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); 1487 m_assembler.dcmppeq(right, right); 1488 takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); 1489 m_assembler.dcmppgt(right, left); 1490 m_assembler.branch(BF_OPCODE, 2); 1491 takeBranch.link(this); 1492 return Jump(m_assembler.extraInstrForBranch(scratchReg3)); 1493 } 1494 1495 if (cond == DoubleGreaterThanOrEqualOrUnordered) { 1496 m_assembler.dcmppgt(left, right); 1497 return branchFalse(); 1498 } 1499 1500 if (cond == DoubleLessThanOrUnordered) { 1501 JumpList takeBranch; 1502 m_assembler.dcmppeq(left, left); 1503 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); 1504 takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); 1505 m_assembler.dcmppeq(right, right); 1506 takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); 1507 m_assembler.dcmppgt(left, right); 1508 m_assembler.branch(BF_OPCODE, 2); 1509 takeBranch.link(this); 1510 return Jump(m_assembler.extraInstrForBranch(scratchReg3)); 1511 } 1512 1513 if (cond == DoubleLessThanOrEqualOrUnordered) { 1514 m_assembler.dcmppgt(right, left); 1515 return branchFalse(); 1516 } 1517 1518 ASSERT(cond == DoubleNotEqualOrUnordered); 1519 m_assembler.dcmppeq(right, left); 1520 return branchFalse(); 1521 } 1522 1523 Jump branchTrue() 1524 { 1525 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t)); 1526 m_assembler.branch(BF_OPCODE, 2); 1527 return Jump(m_assembler.extraInstrForBranch(scratchReg3)); 1528 } 1529 1530 Jump branchFalse() 1531 { 1532 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t)); 1533 m_assembler.branch(BT_OPCODE, 2); 1534 return Jump(m_assembler.extraInstrForBranch(scratchReg3)); 1535 } 1536 1537 Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right) 1538 { 1539 RegisterID scr = claimScratch(); 1540 move(left.index, scr); 1541 lshift32(TrustedImm32(left.scale), scr); 1542 add32(left.base, scr); 1543 load32(scr, left.offset, scr); 1544 compare32(right.m_value, scr, cond); 1545 releaseScratch(scr); 1546 1547 if (cond == NotEqual) 1548 return branchFalse(); 1549 return branchTrue(); 1550 } 1551 1552 void sqrtDouble(FPRegisterID src, FPRegisterID dest) 1553 { 1554 moveDouble(src, dest); 1555 m_assembler.dsqrt(dest); 1556 } 1557 1558 void absDouble(FPRegisterID src, FPRegisterID dest) 1559 { 1560 moveDouble(src, dest); 1561 m_assembler.dabs(dest); 1562 } 1563 1564 Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) 1565 { 1566 RegisterID addressTempRegister = claimScratch(); 1567 load8(address, addressTempRegister); 1568 Jump jmp = branchTest32(cond, addressTempRegister, mask); 1569 releaseScratch(addressTempRegister); 1570 return jmp; 1571 } 1572 1573 Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) 1574 { 1575 RegisterID addressTempRegister = claimScratch(); 1576 load8(address, addressTempRegister); 1577 Jump jmp = branchTest32(cond, addressTempRegister, mask); 1578 releaseScratch(addressTempRegister); 1579 return jmp; 1580 } 1581 1582 Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) 1583 { 1584 RegisterID addressTempRegister = claimScratch(); 1585 move(TrustedImmPtr(address.m_ptr), addressTempRegister); 1586 load8(Address(addressTempRegister), addressTempRegister); 1587 Jump jmp = branchTest32(cond, addressTempRegister, mask); 1588 releaseScratch(addressTempRegister); 1589 return jmp; 1590 } 1591 1592 void signExtend32ToPtr(RegisterID src, RegisterID dest) 1593 { 1594 move(src, dest); 1595 } 1596 1597 void zeroExtend32ToPtr(RegisterID src, RegisterID dest) 1598 { 1599 move(src, dest); 1600 } 1601 1602 Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right) 1603 { 1604 RegisterID addressTempRegister = claimScratch(); 1605 load8(left, addressTempRegister); 1606 Jump jmp = branch32(cond, addressTempRegister, right); 1607 releaseScratch(addressTempRegister); 1608 return jmp; 1609 } 1610 1611 Jump branch8(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right) 1612 { 1613 RegisterID addressTempRegister = claimScratch(); 1614 load8(left, addressTempRegister); 1615 Jump jmp = branch32(cond, addressTempRegister, right); 1616 releaseScratch(addressTempRegister); 1617 return jmp; 1618 } 1619 1620 void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) 1621 { 1622 RegisterID addressTempRegister = claimScratch(); 1623 load8(left, addressTempRegister); 1624 compare32(cond, addressTempRegister, right, dest); 1625 releaseScratch(addressTempRegister); 1626 } 1627 1628 enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful }; 1629 Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed) 1630 { 1631 Jump result; 1632 truncateDoubleToInt32(src, dest); 1633 RegisterID intscr = claimScratch(); 1634 m_assembler.loadConstant(0x7fffffff, intscr); 1635 m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal)); 1636 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 12, sizeof(uint32_t)); 1637 if (branchType == BranchIfTruncateFailed) { 1638 m_assembler.branch(BT_OPCODE, 2); 1639 m_assembler.addlImm8r(1, intscr); 1640 m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal)); 1641 result = branchTrue(); 1642 } else { 1643 Jump out = Jump(m_assembler.je(), SH4Assembler::JumpNear); 1644 m_assembler.addlImm8r(1, intscr); 1645 m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal)); 1646 result = branchFalse(); 1647 out.link(this); 1648 } 1649 releaseScratch(intscr); 1650 return result; 1651 } 1652 1653 Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed) 1654 { 1655 Jump result; 1656 RegisterID intscr = claimScratch(); 1657 m_assembler.loadConstant(0x80000000, intscr); 1658 convertInt32ToDouble(intscr, fscratch); 1659 addDouble(src, fscratch); 1660 truncateDoubleToInt32(fscratch, dest); 1661 m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal)); 1662 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 16, sizeof(uint32_t)); 1663 if (branchType == BranchIfTruncateFailed) { 1664 m_assembler.branch(BT_OPCODE, 4); 1665 m_assembler.addlImm8r(-1, intscr); 1666 m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal)); 1667 m_assembler.addlImm8r(1, intscr); 1668 m_assembler.sublRegReg(intscr, dest); 1669 result = branchTrue(); 1670 } else { 1671 Jump out = Jump(m_assembler.je(), SH4Assembler::JumpNear); 1672 m_assembler.addlImm8r(-1, intscr); 1673 m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal)); 1674 m_assembler.addlImm8r(1, intscr); 1675 m_assembler.sublRegReg(intscr, dest); 1676 result = branchFalse(); 1677 out.link(this); 1678 } 1679 releaseScratch(intscr); 1680 return result; 1681 } 1682 1683 void truncateDoubleToInt32(FPRegisterID src, RegisterID dest) 1684 { 1685 m_assembler.ftrcdrmfpul(src); 1686 m_assembler.stsfpulReg(dest); 1687 } 1688 1689 void truncateDoubleToUint32(FPRegisterID src, RegisterID dest) 1690 { 1691 RegisterID intscr = claimScratch(); 1692 m_assembler.loadConstant(0x80000000, intscr); 1693 convertInt32ToDouble(intscr, fscratch); 1694 addDouble(src, fscratch); 1695 m_assembler.ftrcdrmfpul(fscratch); 1696 m_assembler.stsfpulReg(dest); 1697 m_assembler.sublRegReg(intscr, dest); 1698 releaseScratch(intscr); 1699 } 1700 1701 // Stack manipulation operations 1702 1703 void pop(RegisterID dest) 1704 { 1705 m_assembler.popReg(dest); 1706 } 1707 1708 void push(RegisterID src) 1709 { 1710 m_assembler.pushReg(src); 1711 } 1712 1713 void push(TrustedImm32 imm) 1714 { 1715 RegisterID scr = claimScratch(); 1716 m_assembler.loadConstant(imm.m_value, scr); 1717 push(scr); 1718 releaseScratch(scr); 1719 } 1720 1721 // Register move operations 1722 1723 void move(TrustedImm32 imm, RegisterID dest) 1724 { 1725 m_assembler.loadConstant(imm.m_value, dest); 1726 } 1727 1728 DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest) 1729 { 1730 m_assembler.ensureSpace(m_assembler.maxInstructionSize, sizeof(uint32_t)); 1731 DataLabelPtr dataLabel(this); 1732 m_assembler.loadConstantUnReusable(reinterpret_cast<uint32_t>(initialValue.m_value), dest); 1733 return dataLabel; 1734 } 1735 1736 void move(RegisterID src, RegisterID dest) 1737 { 1738 if (src != dest) 1739 m_assembler.movlRegReg(src, dest); 1740 } 1741 1742 void move(TrustedImmPtr imm, RegisterID dest) 1743 { 1744 m_assembler.loadConstant(imm.asIntptr(), dest); 1745 } 1746 1747 void swap(RegisterID reg1, RegisterID reg2) 1748 { 1749 if (reg1 != reg2) { 1750 xor32(reg1, reg2); 1751 xor32(reg2, reg1); 1752 xor32(reg1, reg2); 1753 } 1754 } 1755 1756 void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest) 1757 { 1758 m_assembler.cmplRegReg(right, left, SH4Condition(cond)); 1759 if (cond != NotEqual) { 1760 m_assembler.movt(dest); 1761 return; 1762 } 1763 1764 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4); 1765 m_assembler.movImm8(0, dest); 1766 m_assembler.branch(BT_OPCODE, 0); 1767 m_assembler.movImm8(1, dest); 1768 } 1769 1770 void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest) 1771 { 1772 if (left != dest) { 1773 move(right, dest); 1774 compare32(cond, left, dest, dest); 1775 return; 1776 } 1777 1778 RegisterID scr = claimScratch(); 1779 move(right, scr); 1780 compare32(cond, left, scr, dest); 1781 releaseScratch(scr); 1782 } 1783 1784 void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest) 1785 { 1786 ASSERT((cond == Zero) || (cond == NonZero)); 1787 1788 load8(address, dest); 1789 if (mask.m_value == -1) 1790 compare32(0, dest, static_cast<RelationalCondition>(cond)); 1791 else 1792 testlImm(mask.m_value, dest); 1793 if (cond != NonZero) { 1794 m_assembler.movt(dest); 1795 return; 1796 } 1797 1798 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4); 1799 m_assembler.movImm8(0, dest); 1800 m_assembler.branch(BT_OPCODE, 0); 1801 m_assembler.movImm8(1, dest); 1802 } 1803 1804 void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest) 1805 { 1806 ASSERT((cond == Zero) || (cond == NonZero)); 1807 1808 load32(address, dest); 1809 if (mask.m_value == -1) 1810 compare32(0, dest, static_cast<RelationalCondition>(cond)); 1811 else 1812 testlImm(mask.m_value, dest); 1813 if (cond != NonZero) { 1814 m_assembler.movt(dest); 1815 return; 1816 } 1817 1818 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4); 1819 m_assembler.movImm8(0, dest); 1820 m_assembler.branch(BT_OPCODE, 0); 1821 m_assembler.movImm8(1, dest); 1822 } 1823 1824 void loadPtrLinkReg(ImplicitAddress address) 1825 { 1826 RegisterID scr = claimScratch(); 1827 load32(address, scr); 1828 m_assembler.ldspr(scr); 1829 releaseScratch(scr); 1830 } 1831 1832 Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right) 1833 { 1834 m_assembler.cmplRegReg(right, left, SH4Condition(cond)); 1835 /* BT label => BF off 1836 nop LDR reg 1837 nop braf @reg 1838 nop nop 1839 */ 1840 if (cond == NotEqual) 1841 return branchFalse(); 1842 return branchTrue(); 1843 } 1844 1845 Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right) 1846 { 1847 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value) 1848 m_assembler.testlRegReg(left, left); 1849 else 1850 compare32(right.m_value, left, cond); 1851 1852 if (cond == NotEqual) 1853 return branchFalse(); 1854 return branchTrue(); 1855 } 1856 1857 Jump branch32(RelationalCondition cond, RegisterID left, Address right) 1858 { 1859 compare32(right.offset, right.base, left, cond); 1860 if (cond == NotEqual) 1861 return branchFalse(); 1862 return branchTrue(); 1863 } 1864 1865 Jump branch32(RelationalCondition cond, Address left, RegisterID right) 1866 { 1867 compare32(right, left.offset, left.base, cond); 1868 if (cond == NotEqual) 1869 return branchFalse(); 1870 return branchTrue(); 1871 } 1872 1873 Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right) 1874 { 1875 compare32(right.m_value, left.offset, left.base, cond); 1876 if (cond == NotEqual) 1877 return branchFalse(); 1878 return branchTrue(); 1879 } 1880 1881 Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right) 1882 { 1883 RegisterID scr = claimScratch(); 1884 1885 load32(left.m_ptr, scr); 1886 m_assembler.cmplRegReg(right, scr, SH4Condition(cond)); 1887 releaseScratch(scr); 1888 1889 if (cond == NotEqual) 1890 return branchFalse(); 1891 return branchTrue(); 1892 } 1893 1894 Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right) 1895 { 1896 RegisterID addressTempRegister = claimScratch(); 1897 1898 move(TrustedImmPtr(left.m_ptr), addressTempRegister); 1899 m_assembler.movlMemReg(addressTempRegister, addressTempRegister); 1900 compare32(right.m_value, addressTempRegister, cond); 1901 releaseScratch(addressTempRegister); 1902 1903 if (cond == NotEqual) 1904 return branchFalse(); 1905 return branchTrue(); 1906 } 1907 1908 Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right) 1909 { 1910 ASSERT(!(right.m_value & 0xFFFFFF00)); 1911 RegisterID lefttmp = claimScratch(); 1912 1913 loadEffectiveAddress(left, lefttmp); 1914 1915 load8(lefttmp, lefttmp); 1916 RegisterID righttmp = claimScratch(); 1917 m_assembler.loadConstant(right.m_value, righttmp); 1918 1919 Jump result = branch32(cond, lefttmp, righttmp); 1920 releaseScratch(lefttmp); 1921 releaseScratch(righttmp); 1922 return result; 1923 } 1924 1925 Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask) 1926 { 1927 ASSERT((cond == Zero) || (cond == NonZero)); 1928 1929 m_assembler.testlRegReg(reg, mask); 1930 1931 if (cond == NonZero) // NotEqual 1932 return branchFalse(); 1933 return branchTrue(); 1934 } 1935 1936 Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) 1937 { 1938 ASSERT((cond == Zero) || (cond == NonZero)); 1939 1940 if (mask.m_value == -1) 1941 m_assembler.testlRegReg(reg, reg); 1942 else 1943 testlImm(mask.m_value, reg); 1944 1945 if (cond == NonZero) // NotEqual 1946 return branchFalse(); 1947 return branchTrue(); 1948 } 1949 1950 Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) 1951 { 1952 ASSERT((cond == Zero) || (cond == NonZero)); 1953 1954 if (mask.m_value == -1) 1955 compare32(0, address.offset, address.base, static_cast<RelationalCondition>(cond)); 1956 else 1957 testImm(mask.m_value, address.offset, address.base); 1958 1959 if (cond == NonZero) // NotEqual 1960 return branchFalse(); 1961 return branchTrue(); 1962 } 1963 1964 Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) 1965 { 1966 ASSERT((cond == Zero) || (cond == NonZero)); 1967 1968 RegisterID scr = claimScratch(); 1969 1970 move(address.index, scr); 1971 lshift32(TrustedImm32(address.scale), scr); 1972 add32(address.base, scr); 1973 load32(scr, address.offset, scr); 1974 1975 if (mask.m_value == -1) 1976 m_assembler.testlRegReg(scr, scr); 1977 else 1978 testlImm(mask.m_value, scr); 1979 1980 releaseScratch(scr); 1981 1982 if (cond == NonZero) // NotEqual 1983 return branchFalse(); 1984 return branchTrue(); 1985 } 1986 1987 Jump jump() 1988 { 1989 return Jump(m_assembler.jmp()); 1990 } 1991 1992 void jump(RegisterID target) 1993 { 1994 m_assembler.jmpReg(target); 1995 } 1996 1997 void jump(Address address) 1998 { 1999 RegisterID scr = claimScratch(); 2000 load32(address, scr); 2001 m_assembler.jmpReg(scr); 2002 releaseScratch(scr); 2003 } 2004 2005 void jump(AbsoluteAddress address) 2006 { 2007 RegisterID scr = claimScratch(); 2008 2009 move(TrustedImmPtr(address.m_ptr), scr); 2010 m_assembler.movlMemReg(scr, scr); 2011 m_assembler.jmpReg(scr); 2012 releaseScratch(scr); 2013 } 2014 2015 // Arithmetic control flow operations 2016 2017 Jump branchNeg32(ResultCondition cond, RegisterID srcDest) 2018 { 2019 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 2020 2021 if (cond == Overflow) 2022 return branchMul32(cond, TrustedImm32(-1), srcDest, srcDest); 2023 2024 neg32(srcDest); 2025 2026 if (cond == Signed) { 2027 m_assembler.cmppz(srcDest); 2028 return branchFalse(); 2029 } 2030 2031 compare32(0, srcDest, Equal); 2032 return (cond == NonZero) ? branchFalse() : branchTrue(); 2033 } 2034 2035 Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest) 2036 { 2037 ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); 2038 2039 if (cond == Overflow) { 2040 m_assembler.addvlRegReg(src, dest); 2041 return branchTrue(); 2042 } 2043 2044 m_assembler.addlRegReg(src, dest); 2045 2046 if ((cond == Signed) || (cond == PositiveOrZero)) { 2047 m_assembler.cmppz(dest); 2048 return (cond == Signed) ? branchFalse() : branchTrue(); 2049 } 2050 2051 compare32(0, dest, Equal); 2052 return (cond == NonZero) ? branchFalse() : branchTrue(); 2053 } 2054 2055 Jump branchAdd32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest) 2056 { 2057 ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); 2058 2059 if (cond == Overflow) { 2060 if (src1 == dest) 2061 m_assembler.addvlRegReg(src2, dest); 2062 else { 2063 move(src2, dest); 2064 m_assembler.addvlRegReg(src1, dest); 2065 } 2066 return branchTrue(); 2067 } 2068 2069 add32(src1, src2, dest); 2070 2071 if ((cond == Signed) || (cond == PositiveOrZero)) { 2072 m_assembler.cmppz(dest); 2073 return (cond == Signed) ? branchFalse() : branchTrue(); 2074 } 2075 2076 compare32(0, dest, Equal); 2077 return (cond == NonZero) ? branchFalse() : branchTrue(); 2078 } 2079 2080 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) 2081 { 2082 ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); 2083 2084 RegisterID immval = claimScratch(); 2085 move(imm, immval); 2086 Jump result = branchAdd32(cond, immval, dest); 2087 releaseScratch(immval); 2088 return result; 2089 } 2090 2091 Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) 2092 { 2093 ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); 2094 2095 move(src, dest); 2096 2097 if (cond == Overflow) { 2098 move(imm, scratchReg3); 2099 m_assembler.addvlRegReg(scratchReg3, dest); 2100 return branchTrue(); 2101 } 2102 2103 add32(imm, dest); 2104 2105 if ((cond == Signed) || (cond == PositiveOrZero)) { 2106 m_assembler.cmppz(dest); 2107 return (cond == Signed) ? branchFalse() : branchTrue(); 2108 } 2109 2110 compare32(0, dest, Equal); 2111 return (cond == NonZero) ? branchFalse() : branchTrue(); 2112 } 2113 2114 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest) 2115 { 2116 ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); 2117 bool result; 2118 2119 move(imm, scratchReg3); 2120 RegisterID destptr = claimScratch(); 2121 RegisterID destval = claimScratch(); 2122 move(TrustedImmPtr(dest.m_ptr), destptr); 2123 m_assembler.movlMemReg(destptr, destval); 2124 if (cond == Overflow) { 2125 m_assembler.addvlRegReg(scratchReg3, destval); 2126 result = true; 2127 } else { 2128 m_assembler.addlRegReg(scratchReg3, destval); 2129 if ((cond == Signed) || (cond == PositiveOrZero)) { 2130 m_assembler.cmppz(destval); 2131 result = (cond == PositiveOrZero); 2132 } else { 2133 m_assembler.testlRegReg(destval, destval); 2134 result = (cond != NonZero); 2135 } 2136 } 2137 m_assembler.movlRegMem(destval, destptr); 2138 releaseScratch(destval); 2139 releaseScratch(destptr); 2140 return result ? branchTrue() : branchFalse(); 2141 } 2142 2143 Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest) 2144 { 2145 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 2146 2147 if (cond == Overflow) { 2148 RegisterID scrsign = claimScratch(); 2149 RegisterID msbres = claimScratch(); 2150 m_assembler.dmulslRegReg(src, dest); 2151 m_assembler.stsmacl(dest); 2152 m_assembler.cmppz(dest); 2153 m_assembler.movt(scrsign); 2154 m_assembler.addlImm8r(-1, scrsign); 2155 m_assembler.stsmach(msbres); 2156 m_assembler.cmplRegReg(msbres, scrsign, SH4Condition(Equal)); 2157 releaseScratch(msbres); 2158 releaseScratch(scrsign); 2159 return branchFalse(); 2160 } 2161 2162 mul32(src, dest); 2163 2164 if (cond == Signed) { 2165 m_assembler.cmppz(dest); 2166 return branchFalse(); 2167 } 2168 2169 compare32(0, dest, static_cast<RelationalCondition>(cond)); 2170 return (cond == NonZero) ? branchFalse() : branchTrue(); 2171 } 2172 2173 Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest) 2174 { 2175 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 2176 2177 if (cond == Overflow) { 2178 RegisterID scrsign = claimScratch(); 2179 RegisterID msbres = claimScratch(); 2180 m_assembler.dmulslRegReg(src1, src2); 2181 m_assembler.stsmacl(dest); 2182 m_assembler.cmppz(dest); 2183 m_assembler.movt(scrsign); 2184 m_assembler.addlImm8r(-1, scrsign); 2185 m_assembler.stsmach(msbres); 2186 m_assembler.cmplRegReg(msbres, scrsign, SH4Condition(Equal)); 2187 releaseScratch(msbres); 2188 releaseScratch(scrsign); 2189 return branchFalse(); 2190 } 2191 2192 mul32(src1, src2, dest); 2193 2194 if (cond == Signed) { 2195 m_assembler.cmppz(dest); 2196 return branchFalse(); 2197 } 2198 2199 compare32(0, dest, Equal); 2200 return (cond == NonZero) ? branchFalse() : branchTrue(); 2201 } 2202 2203 Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest) 2204 { 2205 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 2206 2207 if (src == dest) { 2208 move(imm, scratchReg3); 2209 return branchMul32(cond, scratchReg3, dest); 2210 } 2211 2212 move(imm, dest); 2213 return branchMul32(cond, src, dest); 2214 } 2215 2216 Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest) 2217 { 2218 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 2219 2220 if (cond == Overflow) { 2221 m_assembler.subvlRegReg(src, dest); 2222 return branchTrue(); 2223 } 2224 2225 sub32(src, dest); 2226 2227 if (cond == Signed) { 2228 m_assembler.cmppz(dest); 2229 return branchFalse(); 2230 } 2231 2232 compare32(0, dest, static_cast<RelationalCondition>(cond)); 2233 return (cond == NonZero) ? branchFalse() : branchTrue(); 2234 } 2235 2236 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) 2237 { 2238 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 2239 2240 RegisterID immval = claimScratch(); 2241 move(imm, immval); 2242 Jump result = branchSub32(cond, immval, dest); 2243 releaseScratch(immval); 2244 return result; 2245 } 2246 2247 Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) 2248 { 2249 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 2250 2251 move(src, dest); 2252 return branchSub32(cond, imm, dest); 2253 } 2254 2255 Jump branchSub32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest) 2256 { 2257 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 2258 2259 if (src2 != dest) { 2260 move(src1, dest); 2261 return branchSub32(cond, src2, dest); 2262 } 2263 2264 if (cond == Overflow) { 2265 RegisterID tmpval = claimScratch(); 2266 move(src1, tmpval); 2267 m_assembler.subvlRegReg(src2, tmpval); 2268 move(tmpval, dest); 2269 releaseScratch(tmpval); 2270 return branchTrue(); 2271 } 2272 2273 RegisterID tmpval = claimScratch(); 2274 move(src1, tmpval); 2275 sub32(src2, tmpval); 2276 move(tmpval, dest); 2277 releaseScratch(tmpval); 2278 2279 if (cond == Signed) { 2280 m_assembler.cmppz(dest); 2281 return branchFalse(); 2282 } 2283 2284 compare32(0, dest, static_cast<RelationalCondition>(cond)); 2285 return (cond == NonZero) ? branchFalse() : branchTrue(); 2286 } 2287 2288 Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest) 2289 { 2290 ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero)); 2291 2292 or32(src, dest); 2293 2294 if (cond == Signed) { 2295 m_assembler.cmppz(dest); 2296 return branchFalse(); 2297 } 2298 2299 compare32(0, dest, static_cast<RelationalCondition>(cond)); 2300 return (cond == NonZero) ? branchFalse() : branchTrue(); 2301 } 2302 2303 void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID, bool negZeroCheck = true) 2304 { 2305 truncateDoubleToInt32(src, dest); 2306 convertInt32ToDouble(dest, fscratch); 2307 failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fscratch, src)); 2308 2309 if (negZeroCheck) 2310 failureCases.append(branch32(Equal, dest, TrustedImm32(0))); 2311 } 2312 2313 void neg32(RegisterID dst) 2314 { 2315 m_assembler.neg(dst, dst); 2316 } 2317 2318 void urshift32(RegisterID shiftamount, RegisterID dest) 2319 { 2320 RegisterID shiftTmp = claimScratch(); 2321 m_assembler.loadConstant(0x1f, shiftTmp); 2322 m_assembler.andlRegReg(shiftamount, shiftTmp); 2323 m_assembler.neg(shiftTmp, shiftTmp); 2324 m_assembler.shldRegReg(dest, shiftTmp); 2325 releaseScratch(shiftTmp); 2326 } 2327 2328 void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) 2329 { 2330 move(src, dest); 2331 urshift32(shiftAmount, dest); 2332 } 2333 2334 void urshift32(TrustedImm32 imm, RegisterID dest) 2335 { 2336 int immMasked = imm.m_value & 0x1f; 2337 if (!immMasked) 2338 return; 2339 2340 if ((immMasked == 1) || (immMasked == 2) || (immMasked == 8) || (immMasked == 16)) { 2341 m_assembler.shlrImm8r(immMasked, dest); 2342 return; 2343 } 2344 2345 RegisterID shiftTmp = claimScratch(); 2346 m_assembler.loadConstant(-immMasked, shiftTmp); 2347 m_assembler.shldRegReg(dest, shiftTmp); 2348 releaseScratch(shiftTmp); 2349 } 2350 2351 void urshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest) 2352 { 2353 move(src, dest); 2354 urshift32(shiftamount, dest); 2355 } 2356 2357 Call call() 2358 { 2359 return Call(m_assembler.call(), Call::Linkable); 2360 } 2361 2362 Call nearCall() 2363 { 2364 return Call(m_assembler.call(), Call::LinkableNear); 2365 } 2366 2367 Call call(RegisterID target) 2368 { 2369 return Call(m_assembler.call(target), Call::None); 2370 } 2371 2372 void call(Address address) 2373 { 2374 RegisterID target = claimScratch(); 2375 load32(address.base, address.offset, target); 2376 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 2); 2377 m_assembler.branch(JSR_OPCODE, target); 2378 m_assembler.nop(); 2379 releaseScratch(target); 2380 } 2381 2382 void breakpoint() 2383 { 2384 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 2); 2385 m_assembler.bkpt(); 2386 m_assembler.nop(); 2387 } 2388 2389 Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) 2390 { 2391 RegisterID dataTempRegister = claimScratch(); 2392 2393 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 10, 2 * sizeof(uint32_t)); 2394 dataLabel = moveWithPatch(initialRightValue, dataTempRegister); 2395 m_assembler.cmplRegReg(dataTempRegister, left, SH4Condition(cond)); 2396 releaseScratch(dataTempRegister); 2397 2398 if (cond == NotEqual) 2399 return branchFalse(); 2400 return branchTrue(); 2401 } 2402 2403 Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) 2404 { 2405 RegisterID scr = claimScratch(); 2406 2407 m_assembler.loadConstant(left.offset, scr); 2408 m_assembler.addlRegReg(left.base, scr); 2409 m_assembler.movlMemReg(scr, scr); 2410 RegisterID scr1 = claimScratch(); 2411 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 10, 2 * sizeof(uint32_t)); 2412 dataLabel = moveWithPatch(initialRightValue, scr1); 2413 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond)); 2414 releaseScratch(scr); 2415 releaseScratch(scr1); 2416 2417 if (cond == NotEqual) 2418 return branchFalse(); 2419 return branchTrue(); 2420 } 2421 2422 void ret() 2423 { 2424 m_assembler.ret(); 2425 m_assembler.nop(); 2426 } 2427 2428 DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address) 2429 { 2430 RegisterID scr = claimScratch(); 2431 DataLabelPtr label = moveWithPatch(initialValue, scr); 2432 store32(scr, address); 2433 releaseScratch(scr); 2434 return label; 2435 } 2436 2437 DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(TrustedImmPtr(0), address); } 2438 2439 int sizeOfConstantPool() 2440 { 2441 return m_assembler.sizeOfConstantPool(); 2442 } 2443 2444 Call tailRecursiveCall() 2445 { 2446 RegisterID scr = claimScratch(); 2447 2448 m_assembler.loadConstantUnReusable(0x0, scr, true); 2449 Jump m_jump = Jump(m_assembler.jmp(scr)); 2450 releaseScratch(scr); 2451 2452 return Call::fromTailJump(m_jump); 2453 } 2454 2455 Call makeTailRecursiveCall(Jump oldJump) 2456 { 2457 oldJump.link(this); 2458 return tailRecursiveCall(); 2459 } 2460 2461 void nop() 2462 { 2463 m_assembler.nop(); 2464 } 2465 2466 void memoryFence() 2467 { 2468 m_assembler.synco(); 2469 } 2470 2471 static FunctionPtr readCallTarget(CodeLocationCall call) 2472 { 2473 return FunctionPtr(reinterpret_cast<void(*)()>(SH4Assembler::readCallTarget(call.dataLocation()))); 2474 } 2475 2476 static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination) 2477 { 2478 SH4Assembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation()); 2479 } 2480 2481 static ptrdiff_t maxJumpReplacementSize() 2482 { 2483 return SH4Assembler::maxJumpReplacementSize(); 2484 } 2485 2486 static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; } 2487 2488 static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label) 2489 { 2490 return label.labelAtOffset(0); 2491 } 2492 2493 static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID rd, void* initialValue) 2494 { 2495 SH4Assembler::revertJumpReplacementToBranchPtrWithPatch(instructionStart.dataLocation(), rd, reinterpret_cast<int>(initialValue)); 2496 } 2497 2498 static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr) 2499 { 2500 UNREACHABLE_FOR_PLATFORM(); 2501 return CodeLocationLabel(); 2502 } 2503 2504 static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel, Address, void*) 2505 { 2506 UNREACHABLE_FOR_PLATFORM(); 2507 } 2508 2509protected: 2510 SH4Assembler::Condition SH4Condition(RelationalCondition cond) 2511 { 2512 return static_cast<SH4Assembler::Condition>(cond); 2513 } 2514 2515 SH4Assembler::Condition SH4Condition(ResultCondition cond) 2516 { 2517 return static_cast<SH4Assembler::Condition>(cond); 2518 } 2519private: 2520 friend class LinkBuffer; 2521 friend class RepatchBuffer; 2522 2523 static void linkCall(void* code, Call call, FunctionPtr function) 2524 { 2525 SH4Assembler::linkCall(code, call.m_label, function.value()); 2526 } 2527 2528 static void repatchCall(CodeLocationCall call, CodeLocationLabel destination) 2529 { 2530 SH4Assembler::relinkCall(call.dataLocation(), destination.executableAddress()); 2531 } 2532 2533 static void repatchCall(CodeLocationCall call, FunctionPtr destination) 2534 { 2535 SH4Assembler::relinkCall(call.dataLocation(), destination.executableAddress()); 2536 } 2537}; 2538 2539} // namespace JSC 2540 2541#endif // ENABLE(ASSEMBLER) 2542 2543#endif // MacroAssemblerSH4_h 2544