1/* 2 * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved. 3 * Copyright (C) 2008 Apple Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*/ 26 27#ifndef MacroAssemblerSH4_h 28#define MacroAssemblerSH4_h 29 30#if ENABLE(ASSEMBLER) && CPU(SH4) 31 32#include "AbstractMacroAssembler.h" 33#include "SH4Assembler.h" 34#include <wtf/Assertions.h> 35 36namespace JSC { 37typedef SH4Assembler::Condition Condition; 38 39class MacroAssemblerSH4 : public AbstractMacroAssembler<SH4Assembler> { 40public: 41 typedef SH4Assembler::FPRegisterID FPRegisterID; 42 43 static const Condition Equal; 44 static const Condition NotEqual; 45 static const Condition GreaterThan; 46 static const Condition GreaterThanOrEqual; 47 static const Condition LessThan; 48 static const Condition LessThanOrEqual; 49 static const Condition UGreaterThan; 50 static const Condition UGreaterThanOrEqual; 51 static const Condition ULessThan; 52 static const Condition ULessThanOrEqual; 53 static const Condition Zero; 54 static const Condition NonZero; 55 static const Condition Overflow; 56 static const Condition Above; 57 static const Condition AboveOrEqual; 58 static const Condition Below; 59 static const Condition BelowOrEqual; 60 static const Condition DoubleEqual; 61 static const Condition DoubleNotEqual; 62 static const Condition DoubleGreaterThan; 63 static const Condition DoubleGreaterThanOrEqual; 64 static const Condition DoubleLessThan; 65 static const Condition DoubleLessThanOrEqual; 66 static const Condition DoubleEqualOrUnordered; 67 static const Condition DoubleNotEqualOrUnordered; 68 static const Condition DoubleGreaterThanOrUnordered; 69 static const Condition DoubleGreaterThanOrEqualOrUnordered; 70 static const Condition DoubleLessThanOrUnordered; 71 static const Condition DoubleLessThanOrEqualOrUnordered; 72 static const Condition Signed; 73 static const Scale ScalePtr = TimesFour; 74 static const FPRegisterID fscratch = SH4Registers::fr10; 75 static const RegisterID stackPointerRegister = SH4Registers::sp; 76 static const RegisterID linkRegister = SH4Registers::pr; 77 static const RegisterID scratchReg3 = SH4Registers::r13; 78 79 RegisterID claimScratch() 80 { 81 return m_assembler.claimScratch(); 82 } 83 84 void releaseScratch(RegisterID reg) 85 { 86 m_assembler.releaseScratch(reg); 87 } 88 89 // Integer arithmetic operations 90 91 void add32(RegisterID src, RegisterID dest) 92 { 93 m_assembler.addlRegReg(src, dest); 94 } 95 96 void add32(TrustedImm32 imm, RegisterID dest) 97 { 98 if (m_assembler.isImmediate(imm.m_value)) { 99 m_assembler.addlImm8r(imm.m_value, dest); 100 return; 101 } 102 103 RegisterID scr = claimScratch(); 104 m_assembler.loadConstant(imm.m_value, scr); 105 m_assembler.addlRegReg(scr, dest); 106 releaseScratch(scr); 107 } 108 109 void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) 110 { 111 if (src != dest) 112 m_assembler.movlRegReg(src, dest); 113 add32(imm, dest); 114 } 115 116 void add32(TrustedImm32 imm, Address address) 117 { 118 RegisterID scr = claimScratch(); 119 load32(address, scr); 120 add32(imm, scr); 121 store32(scr, address); 122 releaseScratch(scr); 123 } 124 125 void add32(Address src, RegisterID dest) 126 { 127 RegisterID scr = claimScratch(); 128 load32(src, scr); 129 m_assembler.addlRegReg(scr, dest); 130 releaseScratch(scr); 131 } 132 133 void and32(RegisterID src, RegisterID dest) 134 { 135 m_assembler.andlRegReg(src, dest); 136 } 137 138 void and32(TrustedImm32 imm, RegisterID dest) 139 { 140 if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) { 141 m_assembler.andlImm8r(imm.m_value, dest); 142 return; 143 } 144 145 RegisterID scr = claimScratch(); 146 m_assembler.loadConstant((imm.m_value), scr); 147 m_assembler.andlRegReg(scr, dest); 148 releaseScratch(scr); 149 } 150 151 void lshift32(RegisterID shiftamount, RegisterID dest) 152 { 153 m_assembler.shllRegReg(dest, shiftamount); 154 } 155 156 void rshift32(int imm, RegisterID dest) 157 { 158 RegisterID scr = claimScratch(); 159 m_assembler.loadConstant(-imm, scr); 160 m_assembler.shaRegReg(dest, scr); 161 releaseScratch(scr); 162 } 163 164 void lshift32(TrustedImm32 imm, RegisterID dest) 165 { 166 if ((imm.m_value == 1) || (imm.m_value == 2) || (imm.m_value == 8) || (imm.m_value == 16)) { 167 m_assembler.shllImm8r(imm.m_value, dest); 168 return; 169 } 170 171 RegisterID scr = claimScratch(); 172 m_assembler.loadConstant(imm.m_value, scr); 173 m_assembler.shllRegReg(dest, scr); 174 releaseScratch(scr); 175 } 176 177 void mul32(RegisterID src, RegisterID dest) 178 { 179 m_assembler.imullRegReg(src, dest); 180 m_assembler.stsmacl(dest); 181 } 182 183 void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest) 184 { 185 RegisterID scr = claimScratch(); 186 move(imm, scr); 187 if (src != dest) 188 move(src, dest); 189 mul32(scr, dest); 190 releaseScratch(scr); 191 } 192 193 void not32(RegisterID src, RegisterID dest) 194 { 195 m_assembler.notlReg(src, dest); 196 } 197 198 void or32(RegisterID src, RegisterID dest) 199 { 200 m_assembler.orlRegReg(src, dest); 201 } 202 203 void or32(TrustedImm32 imm, RegisterID dest) 204 { 205 if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) { 206 m_assembler.orlImm8r(imm.m_value, dest); 207 return; 208 } 209 210 RegisterID scr = claimScratch(); 211 m_assembler.loadConstant(imm.m_value, scr); 212 m_assembler.orlRegReg(scr, dest); 213 releaseScratch(scr); 214 } 215 216 void rshift32(RegisterID shiftamount, RegisterID dest) 217 { 218 compare32(32, shiftamount, Equal); 219 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4); 220 m_assembler.branch(BT_OPCODE, 1); 221 m_assembler.neg(shiftamount, shiftamount); 222 m_assembler.shaRegReg(dest, shiftamount); 223 } 224 225 void rshift32(TrustedImm32 imm, RegisterID dest) 226 { 227 if (imm.m_value & 0x1f) 228 rshift32(imm.m_value & 0x1f, dest); 229 } 230 231 void sub32(RegisterID src, RegisterID dest) 232 { 233 m_assembler.sublRegReg(src, dest); 234 } 235 236 void sub32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg) 237 { 238 RegisterID result = claimScratch(); 239 240 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg); 241 m_assembler.movlMemReg(scratchReg, result); 242 243 if (m_assembler.isImmediate(-imm.m_value)) 244 m_assembler.addlImm8r(-imm.m_value, result); 245 else { 246 m_assembler.loadConstant(imm.m_value, scratchReg3); 247 m_assembler.sublRegReg(scratchReg3, result); 248 } 249 250 store32(result, scratchReg); 251 releaseScratch(result); 252 } 253 254 void sub32(TrustedImm32 imm, AbsoluteAddress address) 255 { 256 RegisterID result = claimScratch(); 257 RegisterID scratchReg = claimScratch(); 258 259 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg); 260 m_assembler.movlMemReg(scratchReg, result); 261 262 if (m_assembler.isImmediate(-imm.m_value)) 263 m_assembler.addlImm8r(-imm.m_value, result); 264 else { 265 m_assembler.loadConstant(imm.m_value, scratchReg3); 266 m_assembler.sublRegReg(scratchReg3, result); 267 } 268 269 store32(result, scratchReg); 270 releaseScratch(result); 271 releaseScratch(scratchReg); 272 } 273 274 void add32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg) 275 { 276 RegisterID result = claimScratch(); 277 278 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg); 279 m_assembler.movlMemReg(scratchReg, result); 280 281 if (m_assembler.isImmediate(imm.m_value)) 282 m_assembler.addlImm8r(imm.m_value, result); 283 else { 284 m_assembler.loadConstant(imm.m_value, scratchReg3); 285 m_assembler.addlRegReg(scratchReg3, result); 286 } 287 288 store32(result, scratchReg); 289 releaseScratch(result); 290 } 291 292 void add32(TrustedImm32 imm, AbsoluteAddress address) 293 { 294 RegisterID result = claimScratch(); 295 RegisterID scratchReg = claimScratch(); 296 297 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg); 298 m_assembler.movlMemReg(scratchReg, result); 299 300 if (m_assembler.isImmediate(imm.m_value)) 301 m_assembler.addlImm8r(imm.m_value, result); 302 else { 303 m_assembler.loadConstant(imm.m_value, scratchReg3); 304 m_assembler.addlRegReg(scratchReg3, result); 305 } 306 307 store32(result, scratchReg); 308 releaseScratch(result); 309 releaseScratch(scratchReg); 310 } 311 312 void sub32(TrustedImm32 imm, RegisterID dest) 313 { 314 if (m_assembler.isImmediate(-imm.m_value)) { 315 m_assembler.addlImm8r(-imm.m_value, dest); 316 return; 317 } 318 319 RegisterID scr = claimScratch(); 320 m_assembler.loadConstant(imm.m_value, scr); 321 m_assembler.sublRegReg(scr, dest); 322 releaseScratch(scr); 323 } 324 325 void sub32(Address src, RegisterID dest) 326 { 327 RegisterID scr = claimScratch(); 328 load32(src, scr); 329 m_assembler.sublRegReg(scr, dest); 330 releaseScratch(scr); 331 } 332 333 void xor32(RegisterID src, RegisterID dest) 334 { 335 m_assembler.xorlRegReg(src, dest); 336 } 337 338 void xor32(TrustedImm32 imm, RegisterID srcDest) 339 { 340 if ((srcDest != SH4Registers::r0) || (imm.m_value > 255) || (imm.m_value < 0)) { 341 RegisterID scr = claimScratch(); 342 m_assembler.loadConstant((imm.m_value), scr); 343 m_assembler.xorlRegReg(scr, srcDest); 344 releaseScratch(scr); 345 return; 346 } 347 348 m_assembler.xorlImm8r(imm.m_value, srcDest); 349 } 350 351 void compare32(int imm, RegisterID dst, Condition cond) 352 { 353 if (((cond == Equal) || (cond == NotEqual)) && (dst == SH4Registers::r0) && m_assembler.isImmediate(imm)) { 354 m_assembler.cmpEqImmR0(imm, dst, cond); 355 return; 356 } 357 358 RegisterID scr = claimScratch(); 359 m_assembler.loadConstant(imm, scr); 360 m_assembler.cmplRegReg(scr, dst, cond); 361 releaseScratch(scr); 362 } 363 364 void compare32(int offset, RegisterID base, RegisterID left, Condition cond) 365 { 366 RegisterID scr = claimScratch(); 367 if (!offset) { 368 m_assembler.movlMemReg(base, scr); 369 m_assembler.cmplRegReg(scr, left, cond); 370 releaseScratch(scr); 371 return; 372 } 373 374 if ((offset < 0) || (offset >= 64)) { 375 m_assembler.loadConstant(offset, scr); 376 m_assembler.addlRegReg(base, scr); 377 m_assembler.movlMemReg(scr, scr); 378 m_assembler.cmplRegReg(scr, left, cond); 379 releaseScratch(scr); 380 return; 381 } 382 383 m_assembler.movlMemReg(offset >> 2, base, scr); 384 m_assembler.cmplRegReg(scr, left, cond); 385 releaseScratch(scr); 386 } 387 388 void testImm(int imm, int offset, RegisterID base) 389 { 390 RegisterID scr = claimScratch(); 391 RegisterID scr1 = claimScratch(); 392 393 if ((offset < 0) || (offset >= 64)) { 394 m_assembler.loadConstant(offset, scr); 395 m_assembler.addlRegReg(base, scr); 396 m_assembler.movlMemReg(scr, scr); 397 } else if (offset) 398 m_assembler.movlMemReg(offset >> 2, base, scr); 399 else 400 m_assembler.movlMemReg(base, scr); 401 if (m_assembler.isImmediate(imm)) 402 m_assembler.movImm8(imm, scr1); 403 else 404 m_assembler.loadConstant(imm, scr1); 405 406 m_assembler.testlRegReg(scr, scr1); 407 releaseScratch(scr); 408 releaseScratch(scr1); 409 } 410 411 void testlImm(int imm, RegisterID dst) 412 { 413 if ((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0)) { 414 m_assembler.testlImm8r(imm, dst); 415 return; 416 } 417 418 RegisterID scr = claimScratch(); 419 m_assembler.loadConstant(imm, scr); 420 m_assembler.testlRegReg(scr, dst); 421 releaseScratch(scr); 422 } 423 424 void compare32(RegisterID right, int offset, RegisterID base, Condition cond) 425 { 426 if (!offset) { 427 RegisterID scr = claimScratch(); 428 m_assembler.movlMemReg(base, scr); 429 m_assembler.cmplRegReg(right, scr, cond); 430 releaseScratch(scr); 431 return; 432 } 433 434 if ((offset < 0) || (offset >= 64)) { 435 RegisterID scr = claimScratch(); 436 m_assembler.loadConstant(offset, scr); 437 m_assembler.addlRegReg(base, scr); 438 m_assembler.movlMemReg(scr, scr); 439 m_assembler.cmplRegReg(right, scr, cond); 440 releaseScratch(scr); 441 return; 442 } 443 444 RegisterID scr = claimScratch(); 445 m_assembler.movlMemReg(offset >> 2, base, scr); 446 m_assembler.cmplRegReg(right, scr, cond); 447 releaseScratch(scr); 448 } 449 450 void compare32(int imm, int offset, RegisterID base, Condition cond) 451 { 452 if (!offset) { 453 RegisterID scr = claimScratch(); 454 RegisterID scr1 = claimScratch(); 455 m_assembler.movlMemReg(base, scr); 456 m_assembler.loadConstant(imm, scr1); 457 m_assembler.cmplRegReg(scr1, scr, cond); 458 releaseScratch(scr1); 459 releaseScratch(scr); 460 return; 461 } 462 463 if ((offset < 0) || (offset >= 64)) { 464 RegisterID scr = claimScratch(); 465 RegisterID scr1 = claimScratch(); 466 m_assembler.loadConstant(offset, scr); 467 m_assembler.addlRegReg(base, scr); 468 m_assembler.movlMemReg(scr, scr); 469 m_assembler.loadConstant(imm, scr1); 470 m_assembler.cmplRegReg(scr1, scr, cond); 471 releaseScratch(scr1); 472 releaseScratch(scr); 473 return; 474 } 475 476 RegisterID scr = claimScratch(); 477 RegisterID scr1 = claimScratch(); 478 m_assembler.movlMemReg(offset >> 2, base, scr); 479 m_assembler.loadConstant(imm, scr1); 480 m_assembler.cmplRegReg(scr1, scr, cond); 481 releaseScratch(scr1); 482 releaseScratch(scr); 483 } 484 485 // Memory access operation 486 487 void load32(ImplicitAddress address, RegisterID dest) 488 { 489 load32(address.base, address.offset, dest); 490 } 491 492 void load8(ImplicitAddress address, RegisterID dest) 493 { 494 load8(address.base, address.offset, dest); 495 } 496 497 void load32(BaseIndex address, RegisterID dest) 498 { 499 RegisterID scr = claimScratch(); 500 move(address.index, scr); 501 lshift32(TrustedImm32(address.scale), scr); 502 add32(address.base, scr); 503 load32(scr, address.offset, dest); 504 releaseScratch(scr); 505 } 506 507 void load32(void* address, RegisterID dest) 508 { 509 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), dest); 510 m_assembler.movlMemReg(dest, dest); 511 } 512 513 void load32(RegisterID base, int offset, RegisterID dest) 514 { 515 if (!offset) { 516 m_assembler.movlMemReg(base, dest); 517 return; 518 } 519 520 if ((offset >= 0) && (offset < 64)) { 521 m_assembler.movlMemReg(offset >> 2, base, dest); 522 return; 523 } 524 525 if ((dest == SH4Registers::r0) && (dest != base)) { 526 m_assembler.loadConstant((offset), dest); 527 m_assembler.movlR0mr(base, dest); 528 return; 529 } 530 531 RegisterID scr; 532 if (dest == base) 533 scr = claimScratch(); 534 else 535 scr = dest; 536 m_assembler.loadConstant((offset), scr); 537 m_assembler.addlRegReg(base, scr); 538 m_assembler.movlMemReg(scr, dest); 539 540 if (dest == base) 541 releaseScratch(scr); 542 } 543 544 void load8(RegisterID base, int offset, RegisterID dest) 545 { 546 if (!offset) { 547 m_assembler.movbMemReg(base, dest); 548 return; 549 } 550 551 if ((offset > 0) && (offset < 64) && (dest == SH4Registers::r0)) { 552 m_assembler.movbMemReg(offset, base, dest); 553 return; 554 } 555 556 if (base != dest) { 557 m_assembler.loadConstant((offset), dest); 558 m_assembler.addlRegReg(base, dest); 559 m_assembler.movbMemReg(dest, dest); 560 return; 561 } 562 563 RegisterID scr = claimScratch(); 564 m_assembler.loadConstant((offset), scr); 565 m_assembler.addlRegReg(base, scr); 566 m_assembler.movbMemReg(scr, dest); 567 releaseScratch(scr); 568 } 569 570 void load32(RegisterID r0, RegisterID src, RegisterID dst) 571 { 572 ASSERT(r0 == SH4Registers::r0); 573 m_assembler.movlR0mr(src, dst); 574 } 575 576 void load32(RegisterID src, RegisterID dst) 577 { 578 m_assembler.movlMemReg(src, dst); 579 } 580 581 void load16(ImplicitAddress address, RegisterID dest) 582 { 583 if (!address.offset) { 584 m_assembler.movwMemReg(address.base, dest); 585 return; 586 } 587 588 if ((address.offset > 0) && (address.offset < 64) && (dest == SH4Registers::r0)) { 589 m_assembler.movwMemReg(address.offset, address.base, dest); 590 return; 591 } 592 593 if (address.base != dest) { 594 m_assembler.loadConstant((address.offset), dest); 595 m_assembler.addlRegReg(address.base, dest); 596 m_assembler.movwMemReg(dest, dest); 597 return; 598 } 599 600 RegisterID scr = claimScratch(); 601 m_assembler.loadConstant((address.offset), scr); 602 m_assembler.addlRegReg(address.base, scr); 603 m_assembler.movwMemReg(scr, dest); 604 releaseScratch(scr); 605 } 606 607 void load16(RegisterID src, RegisterID dest) 608 { 609 m_assembler.movwMemReg(src, dest); 610 } 611 612 void load16(RegisterID r0, RegisterID src, RegisterID dest) 613 { 614 ASSERT(r0 == SH4Registers::r0); 615 m_assembler.movwR0mr(src, dest); 616 } 617 618 void load16(BaseIndex address, RegisterID dest) 619 { 620 RegisterID scr = claimScratch(); 621 622 move(address.index, scr); 623 lshift32(TrustedImm32(address.scale), scr); 624 625 if (address.offset) 626 add32(TrustedImm32(address.offset), scr); 627 if (scr == SH4Registers::r0) 628 m_assembler.movwR0mr(address.base, scr); 629 else { 630 add32(address.base, scr); 631 load16(scr, scr); 632 } 633 634 extuw(scr, dest); 635 releaseScratch(scr); 636 } 637 638 void store32(RegisterID src, ImplicitAddress address) 639 { 640 RegisterID scr = claimScratch(); 641 store32(src, address.offset, address.base, scr); 642 releaseScratch(scr); 643 } 644 645 void store32(RegisterID src, int offset, RegisterID base, RegisterID scr) 646 { 647 if (!offset) { 648 m_assembler.movlRegMem(src, base); 649 return; 650 } 651 652 if ((offset >=0) && (offset < 64)) { 653 m_assembler.movlRegMem(src, offset >> 2, base); 654 return; 655 } 656 657 m_assembler.loadConstant((offset), scr); 658 if (scr == SH4Registers::r0) { 659 m_assembler.movlRegMemr0(src, base); 660 return; 661 } 662 663 m_assembler.addlRegReg(base, scr); 664 m_assembler.movlRegMem(src, scr); 665 } 666 667 void store32(RegisterID src, RegisterID offset, RegisterID base) 668 { 669 ASSERT(offset == SH4Registers::r0); 670 m_assembler.movlRegMemr0(src, base); 671 } 672 673 void store32(RegisterID src, RegisterID dst) 674 { 675 m_assembler.movlRegMem(src, dst); 676 } 677 678 void store32(TrustedImm32 imm, ImplicitAddress address) 679 { 680 RegisterID scr = claimScratch(); 681 RegisterID scr1 = claimScratch(); 682 m_assembler.loadConstant((imm.m_value), scr); 683 store32(scr, address.offset, address.base, scr1); 684 releaseScratch(scr); 685 releaseScratch(scr1); 686 } 687 688 void store32(RegisterID src, BaseIndex address) 689 { 690 RegisterID scr = claimScratch(); 691 692 move(address.index, scr); 693 lshift32(TrustedImm32(address.scale), scr); 694 add32(address.base, scr); 695 store32(src, Address(scr, address.offset)); 696 697 releaseScratch(scr); 698 } 699 700 void store32(TrustedImm32 imm, void* address) 701 { 702 RegisterID scr = claimScratch(); 703 RegisterID scr1 = claimScratch(); 704 m_assembler.loadConstant((imm.m_value), scr); 705 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr1); 706 m_assembler.movlMemReg(scr, scr1); 707 releaseScratch(scr); 708 releaseScratch(scr1); 709 } 710 711 void store32(RegisterID src, void* address) 712 { 713 RegisterID scr = claimScratch(); 714 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr); 715 m_assembler.movlMemReg(src, scr); 716 releaseScratch(scr); 717 } 718 719 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest) 720 { 721 RegisterID scr = claimScratch(); 722 DataLabel32 label(this); 723 m_assembler.loadConstantUnReusable(address.offset, scr); 724 m_assembler.addlRegReg(address.base, scr); 725 m_assembler.movlMemReg(scr, dest); 726 releaseScratch(scr); 727 return label; 728 } 729 730 DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address) 731 { 732 RegisterID scr = claimScratch(); 733 DataLabel32 label(this); 734 m_assembler.loadConstantUnReusable(address.offset, scr); 735 m_assembler.addlRegReg(address.base, scr); 736 m_assembler.movlRegMem(src, scr); 737 releaseScratch(scr); 738 return label; 739 } 740 741 // Floating-point operations 742 743 bool supportsFloatingPoint() const { return true; } 744 bool supportsFloatingPointTruncate() const { return true; } 745 bool supportsFloatingPointSqrt() const { return true; } 746 747 void loadDouble(ImplicitAddress address, FPRegisterID dest) 748 { 749 RegisterID scr = claimScratch(); 750 751 m_assembler.loadConstant(address.offset, scr); 752 if (address.base == SH4Registers::r0) { 753 m_assembler.fmovsReadr0r(scr, (FPRegisterID)(dest + 1)); 754 m_assembler.addlImm8r(4, scr); 755 m_assembler.fmovsReadr0r(scr, dest); 756 releaseScratch(scr); 757 return; 758 } 759 760 m_assembler.addlRegReg(address.base, scr); 761 m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1)); 762 m_assembler.fmovsReadrm(scr, dest); 763 releaseScratch(scr); 764 } 765 766 void loadDouble(const void* address, FPRegisterID dest) 767 { 768 RegisterID scr = claimScratch(); 769 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr); 770 m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1)); 771 m_assembler.fmovsReadrm(scr, dest); 772 releaseScratch(scr); 773 } 774 775 void storeDouble(FPRegisterID src, ImplicitAddress address) 776 { 777 RegisterID scr = claimScratch(); 778 m_assembler.loadConstant(address.offset, scr); 779 m_assembler.addlRegReg(address.base, scr); 780 m_assembler.fmovsWriterm((FPRegisterID)(src + 1), scr); 781 m_assembler.addlImm8r(4, scr); 782 m_assembler.fmovsWriterm(src, scr); 783 releaseScratch(scr); 784 } 785 786 void addDouble(FPRegisterID src, FPRegisterID dest) 787 { 788 m_assembler.daddRegReg(src, dest); 789 } 790 791 void addDouble(Address address, FPRegisterID dest) 792 { 793 loadDouble(address, fscratch); 794 addDouble(fscratch, dest); 795 } 796 797 void subDouble(FPRegisterID src, FPRegisterID dest) 798 { 799 m_assembler.dsubRegReg(src, dest); 800 } 801 802 void subDouble(Address address, FPRegisterID dest) 803 { 804 loadDouble(address, fscratch); 805 subDouble(fscratch, dest); 806 } 807 808 void mulDouble(FPRegisterID src, FPRegisterID dest) 809 { 810 m_assembler.dmulRegReg(src, dest); 811 } 812 813 void mulDouble(Address address, FPRegisterID dest) 814 { 815 loadDouble(address, fscratch); 816 mulDouble(fscratch, dest); 817 } 818 819 void divDouble(FPRegisterID src, FPRegisterID dest) 820 { 821 m_assembler.ddivRegReg(src, dest); 822 } 823 824 void convertInt32ToDouble(RegisterID src, FPRegisterID dest) 825 { 826 m_assembler.ldsrmfpul(src); 827 m_assembler.floatfpulDreg(dest); 828 } 829 830 void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest) 831 { 832 RegisterID scr = claimScratch(); 833 m_assembler.loadConstant(reinterpret_cast<uint32_t>(src.m_ptr), scr); 834 convertInt32ToDouble(scr, dest); 835 releaseScratch(scr); 836 } 837 838 void convertInt32ToDouble(Address src, FPRegisterID dest) 839 { 840 RegisterID scr = claimScratch(); 841 load32(src, scr); 842 convertInt32ToDouble(scr, dest); 843 releaseScratch(scr); 844 } 845 846 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest) 847 { 848 RegisterID scr = claimScratch(); 849 850 move(address.index, scr); 851 lshift32(TrustedImm32(address.scale), scr); 852 add32(address.base, scr); 853 854 if (address.offset) 855 add32(TrustedImm32(address.offset), scr); 856 857 RegisterID scr1 = claimScratch(); 858 load16(scr, scr1); 859 add32(TrustedImm32(2), scr); 860 load16(scr, dest); 861 move(TrustedImm32(16), scr); 862 m_assembler.shllRegReg(dest, scr); 863 or32(scr1, dest); 864 865 releaseScratch(scr); 866 releaseScratch(scr1); 867 } 868 869 Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right) 870 { 871 RegisterID scr = scratchReg3; 872 load32WithUnalignedHalfWords(left, scr); 873 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value) 874 m_assembler.testlRegReg(scr, scr); 875 else 876 compare32(right.m_value, scr, cond); 877 878 if (cond == NotEqual) 879 return branchFalse(); 880 return branchTrue(); 881 } 882 883 Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch) 884 { 885 m_assembler.movImm8(0, scratchReg3); 886 convertInt32ToDouble(scratchReg3, scratch); 887 return branchDouble(DoubleNotEqual, reg, scratch); 888 } 889 890 Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch) 891 { 892 m_assembler.movImm8(0, scratchReg3); 893 convertInt32ToDouble(scratchReg3, scratch); 894 return branchDouble(DoubleEqualOrUnordered, reg, scratch); 895 } 896 897 Jump branchDouble(Condition cond, FPRegisterID left, FPRegisterID right) 898 { 899 if (cond == DoubleEqual) { 900 m_assembler.dcmppeq(right, left); 901 return branchTrue(); 902 } 903 904 if (cond == DoubleNotEqual) { 905 RegisterID scr = claimScratch(); 906 m_assembler.loadConstant(0x7fbfffff, scratchReg3); 907 m_assembler.dcnvds(right); 908 m_assembler.stsfpulReg(scr); 909 m_assembler.cmplRegReg(scratchReg3, scr, Equal); 910 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); 911 m_assembler.branch(BT_OPCODE, 8); 912 m_assembler.dcnvds(left); 913 m_assembler.stsfpulReg(scr); 914 m_assembler.cmplRegReg(scratchReg3, scr, Equal); 915 m_assembler.branch(BT_OPCODE, 4); 916 m_assembler.dcmppeq(right, left); 917 releaseScratch(scr); 918 return branchFalse(); 919 } 920 921 if (cond == DoubleGreaterThan) { 922 m_assembler.dcmppgt(right, left); 923 return branchTrue(); 924 } 925 926 if (cond == DoubleGreaterThanOrEqual) { 927 m_assembler.dcmppgt(left, right); 928 return branchFalse(); 929 } 930 931 if (cond == DoubleLessThan) { 932 m_assembler.dcmppgt(left, right); 933 return branchTrue(); 934 } 935 936 if (cond == DoubleLessThanOrEqual) { 937 m_assembler.dcmppgt(right, left); 938 return branchFalse(); 939 } 940 941 if (cond == DoubleEqualOrUnordered) { 942 RegisterID scr = claimScratch(); 943 m_assembler.loadConstant(0x7fbfffff, scratchReg3); 944 m_assembler.dcnvds(right); 945 m_assembler.stsfpulReg(scr); 946 m_assembler.cmplRegReg(scratchReg3, scr, Equal); 947 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); 948 m_assembler.branch(BT_OPCODE, 5); 949 m_assembler.dcnvds(left); 950 m_assembler.stsfpulReg(scr); 951 m_assembler.cmplRegReg(scratchReg3, scr, Equal); 952 m_assembler.branch(BT_OPCODE, 1); 953 m_assembler.dcmppeq(left, right); 954 releaseScratch(scr); 955 return branchTrue(); 956 } 957 958 if (cond == DoubleGreaterThanOrUnordered) { 959 RegisterID scr = claimScratch(); 960 m_assembler.loadConstant(0x7fbfffff, scratchReg3); 961 m_assembler.dcnvds(right); 962 m_assembler.stsfpulReg(scr); 963 m_assembler.cmplRegReg(scratchReg3, scr, Equal); 964 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); 965 m_assembler.branch(BT_OPCODE, 5); 966 m_assembler.dcnvds(left); 967 m_assembler.stsfpulReg(scr); 968 m_assembler.cmplRegReg(scratchReg3, scr, Equal); 969 m_assembler.branch(BT_OPCODE, 1); 970 m_assembler.dcmppgt(right, left); 971 releaseScratch(scr); 972 return branchTrue(); 973 } 974 975 if (cond == DoubleGreaterThanOrEqualOrUnordered) { 976 RegisterID scr = claimScratch(); 977 m_assembler.loadConstant(0x7fbfffff, scratchReg3); 978 m_assembler.dcnvds(right); 979 m_assembler.stsfpulReg(scr); 980 m_assembler.cmplRegReg(scratchReg3, scr, Equal); 981 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); 982 m_assembler.branch(BT_OPCODE, 5); 983 m_assembler.dcnvds(left); 984 m_assembler.stsfpulReg(scr); 985 m_assembler.cmplRegReg(scratchReg3, scr, Equal); 986 m_assembler.branch(BT_OPCODE, 1); 987 m_assembler.dcmppgt(left, right); 988 releaseScratch(scr); 989 return branchFalse(); 990 } 991 992 if (cond == DoubleLessThanOrUnordered) { 993 RegisterID scr = claimScratch(); 994 m_assembler.loadConstant(0x7fbfffff, scratchReg3); 995 m_assembler.dcnvds(right); 996 m_assembler.stsfpulReg(scr); 997 m_assembler.cmplRegReg(scratchReg3, scr, Equal); 998 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); 999 m_assembler.branch(BT_OPCODE, 5); 1000 m_assembler.dcnvds(left); 1001 m_assembler.stsfpulReg(scr); 1002 m_assembler.cmplRegReg(scratchReg3, scr, Equal); 1003 m_assembler.branch(BT_OPCODE, 1); 1004 m_assembler.dcmppgt(left, right); 1005 releaseScratch(scr); 1006 return branchTrue(); 1007 } 1008 1009 if (cond == DoubleLessThanOrEqualOrUnordered) { 1010 RegisterID scr = claimScratch(); 1011 m_assembler.loadConstant(0x7fbfffff, scratchReg3); 1012 m_assembler.dcnvds(right); 1013 m_assembler.stsfpulReg(scr); 1014 m_assembler.cmplRegReg(scratchReg3, scr, Equal); 1015 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); 1016 m_assembler.branch(BT_OPCODE, 5); 1017 m_assembler.dcnvds(left); 1018 m_assembler.stsfpulReg(scr); 1019 m_assembler.cmplRegReg(scratchReg3, scr, Equal); 1020 m_assembler.branch(BT_OPCODE, 1); 1021 m_assembler.dcmppgt(right, left); 1022 releaseScratch(scr); 1023 return branchFalse(); 1024 } 1025 1026 ASSERT(cond == DoubleNotEqualOrUnordered); 1027 RegisterID scr = claimScratch(); 1028 m_assembler.loadConstant(0x7fbfffff, scratchReg3); 1029 m_assembler.dcnvds(right); 1030 m_assembler.stsfpulReg(scr); 1031 m_assembler.cmplRegReg(scratchReg3, scr, Equal); 1032 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); 1033 m_assembler.branch(BT_OPCODE, 5); 1034 m_assembler.dcnvds(left); 1035 m_assembler.stsfpulReg(scr); 1036 m_assembler.cmplRegReg(scratchReg3, scr, Equal); 1037 m_assembler.branch(BT_OPCODE, 1); 1038 m_assembler.dcmppeq(right, left); 1039 releaseScratch(scr); 1040 return branchFalse(); 1041 } 1042 1043 Jump branchTrue() 1044 { 1045 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t)); 1046 Jump m_jump = Jump(m_assembler.je()); 1047 m_assembler.loadConstantUnReusable(0x0, scratchReg3); 1048 m_assembler.nop(); 1049 m_assembler.nop(); 1050 return m_jump; 1051 } 1052 1053 Jump branchFalse() 1054 { 1055 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t)); 1056 Jump m_jump = Jump(m_assembler.jne()); 1057 m_assembler.loadConstantUnReusable(0x0, scratchReg3); 1058 m_assembler.nop(); 1059 m_assembler.nop(); 1060 return m_jump; 1061 } 1062 1063 void set8Compare32(Condition cond, RegisterID left, RegisterID right, RegisterID dest) 1064 { 1065 set32Compare32(cond, left, right, dest); 1066 } 1067 1068 void set8Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest) 1069 { 1070 if (left != dest) { 1071 m_assembler.loadConstant(right.m_value, dest); 1072 set32Compare32(cond, left, dest, dest); 1073 return; 1074 } 1075 1076 RegisterID scr = claimScratch(); 1077 m_assembler.loadConstant(right.m_value, scr); 1078 set32Compare32(cond, left, scr, dest); 1079 releaseScratch(scr); 1080 } 1081 1082 Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right) 1083 { 1084 RegisterID scr = claimScratch(); 1085 move(left.index, scr); 1086 lshift32(TrustedImm32(left.scale), scr); 1087 add32(left.base, scr); 1088 load32(scr, left.offset, scr); 1089 compare32(right.m_value, scr, cond); 1090 releaseScratch(scr); 1091 1092 if (cond == NotEqual) 1093 return branchFalse(); 1094 return branchTrue(); 1095 } 1096 1097 void sqrtDouble(FPRegisterID src, FPRegisterID dest) 1098 { 1099 if (dest != src) 1100 m_assembler.dmovRegReg(src, dest); 1101 m_assembler.dsqrt(dest); 1102 } 1103 1104 Jump branchTest8(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) 1105 { 1106 RegisterID addressTempRegister = claimScratch(); 1107 load8(address, addressTempRegister); 1108 Jump jmp = branchTest32(cond, addressTempRegister, mask); 1109 releaseScratch(addressTempRegister); 1110 return jmp; 1111 } 1112 1113 void signExtend32ToPtr(RegisterID src, RegisterID dest) 1114 { 1115 if (src != dest) 1116 move(src, dest); 1117 } 1118 1119 Jump branch8(Condition cond, Address left, TrustedImm32 right) 1120 { 1121 RegisterID addressTempRegister = claimScratch(); 1122 load8(left, addressTempRegister); 1123 Jump jmp = branch32(cond, addressTempRegister, right); 1124 releaseScratch(addressTempRegister); 1125 return jmp; 1126 } 1127 1128 Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest) 1129 { 1130 m_assembler.ftrcdrmfpul(src); 1131 m_assembler.stsfpulReg(dest); 1132 m_assembler.loadConstant(0x7fffffff, scratchReg3); 1133 m_assembler.cmplRegReg(dest, scratchReg3, Equal); 1134 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 14, sizeof(uint32_t)); 1135 m_assembler.branch(BT_OPCODE, 2); 1136 m_assembler.addlImm8r(1, scratchReg3); 1137 m_assembler.cmplRegReg(dest, scratchReg3, Equal); 1138 return branchTrue(); 1139 } 1140 1141 // Stack manipulation operations 1142 1143 void pop(RegisterID dest) 1144 { 1145 m_assembler.popReg(dest); 1146 } 1147 1148 void push(RegisterID src) 1149 { 1150 m_assembler.pushReg(src); 1151 } 1152 1153 void push(Address address) 1154 { 1155 if (!address.offset) { 1156 push(address.base); 1157 return; 1158 } 1159 1160 if ((address.offset < 0) || (address.offset >= 64)) { 1161 RegisterID scr = claimScratch(); 1162 m_assembler.loadConstant(address.offset, scr); 1163 m_assembler.addlRegReg(address.base, scr); 1164 m_assembler.movlMemReg(scr, SH4Registers::sp); 1165 m_assembler.addlImm8r(-4, SH4Registers::sp); 1166 releaseScratch(scr); 1167 return; 1168 } 1169 1170 m_assembler.movlMemReg(address.offset >> 2, address.base, SH4Registers::sp); 1171 m_assembler.addlImm8r(-4, SH4Registers::sp); 1172 } 1173 1174 void push(TrustedImm32 imm) 1175 { 1176 RegisterID scr = claimScratch(); 1177 m_assembler.loadConstant(imm.m_value, scr); 1178 push(scr); 1179 releaseScratch(scr); 1180 } 1181 1182 // Register move operations 1183 1184 void move(TrustedImm32 imm, RegisterID dest) 1185 { 1186 m_assembler.loadConstant(imm.m_value, dest); 1187 } 1188 1189 DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest) 1190 { 1191 DataLabelPtr dataLabel(this); 1192 m_assembler.loadConstantUnReusable(reinterpret_cast<uint32_t>(initialValue.m_value), dest, true); 1193 return dataLabel; 1194 } 1195 1196 void move(RegisterID src, RegisterID dest) 1197 { 1198 m_assembler.movlRegReg(src, dest); 1199 } 1200 1201 void move(TrustedImmPtr imm, RegisterID dest) 1202 { 1203 m_assembler.loadConstant(imm.asIntptr(), dest); 1204 } 1205 1206 void extuw(RegisterID src, RegisterID dst) 1207 { 1208 m_assembler.extuw(src, dst); 1209 } 1210 1211 void set32Compare32(Condition cond, RegisterID left, RegisterID right, RegisterID dest) 1212 { 1213 m_assembler.cmplRegReg(right, left, cond); 1214 if (cond != NotEqual) { 1215 m_assembler.movt(dest); 1216 return; 1217 } 1218 1219 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4); 1220 m_assembler.movImm8(0, dest); 1221 m_assembler.branch(BT_OPCODE, 0); 1222 m_assembler.movImm8(1, dest); 1223 } 1224 1225 void set32Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest) 1226 { 1227 if (left != dest) { 1228 move(right, dest); 1229 set32Compare32(cond, left, dest, dest); 1230 return; 1231 } 1232 1233 RegisterID scr = claimScratch(); 1234 move(right, scr); 1235 set32Compare32(cond, left, scr, dest); 1236 releaseScratch(scr); 1237 } 1238 1239 void set32Test8(Condition cond, Address address, TrustedImm32 mask, RegisterID dest) 1240 { 1241 ASSERT((cond == Zero) || (cond == NonZero)); 1242 1243 load8(address, dest); 1244 if (mask.m_value == -1) 1245 compare32(0, dest, cond); 1246 else 1247 testlImm(mask.m_value, dest); 1248 if (cond != NonZero) { 1249 m_assembler.movt(dest); 1250 return; 1251 } 1252 1253 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4); 1254 m_assembler.movImm8(0, dest); 1255 m_assembler.branch(BT_OPCODE, 0); 1256 m_assembler.movImm8(1, dest); 1257 } 1258 1259 void loadPtrLinkReg(ImplicitAddress address) 1260 { 1261 RegisterID scr = claimScratch(); 1262 load32(address, scr); 1263 m_assembler.ldspr(scr); 1264 releaseScratch(scr); 1265 } 1266 1267 Jump branch32(Condition cond, RegisterID left, RegisterID right) 1268 { 1269 m_assembler.cmplRegReg(right, left, cond); 1270 /* BT label => BF off 1271 nop LDR reg 1272 nop braf @reg 1273 nop nop 1274 */ 1275 if (cond == NotEqual) 1276 return branchFalse(); 1277 return branchTrue(); 1278 } 1279 1280 Jump branch32(Condition cond, RegisterID left, TrustedImm32 right) 1281 { 1282 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value) 1283 m_assembler.testlRegReg(left, left); 1284 else 1285 compare32(right.m_value, left, cond); 1286 1287 if (cond == NotEqual) 1288 return branchFalse(); 1289 return branchTrue(); 1290 } 1291 1292 Jump branch32(Condition cond, RegisterID left, Address right) 1293 { 1294 compare32(right.offset, right.base, left, cond); 1295 if (cond == NotEqual) 1296 return branchFalse(); 1297 return branchTrue(); 1298 } 1299 1300 Jump branch32(Condition cond, Address left, RegisterID right) 1301 { 1302 compare32(right, left.offset, left.base, cond); 1303 if (cond == NotEqual) 1304 return branchFalse(); 1305 return branchTrue(); 1306 } 1307 1308 Jump branch32(Condition cond, Address left, TrustedImm32 right) 1309 { 1310 compare32(right.m_value, left.offset, left.base, cond); 1311 if (cond == NotEqual) 1312 return branchFalse(); 1313 return branchTrue(); 1314 } 1315 1316 Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right) 1317 { 1318 RegisterID scr = claimScratch(); 1319 1320 move(TrustedImm32(reinterpret_cast<uint32_t>(left.m_ptr)), scr); 1321 m_assembler.cmplRegReg(right, scr, cond); 1322 releaseScratch(scr); 1323 1324 if (cond == NotEqual) 1325 return branchFalse(); 1326 return branchTrue(); 1327 } 1328 1329 Jump branch32(Condition cond, AbsoluteAddress left, TrustedImm32 right) 1330 { 1331 RegisterID addressTempRegister = claimScratch(); 1332 1333 m_assembler.loadConstant(reinterpret_cast<uint32_t>(left.m_ptr), addressTempRegister); 1334 m_assembler.movlMemReg(addressTempRegister, addressTempRegister); 1335 compare32(right.m_value, addressTempRegister, cond); 1336 releaseScratch(addressTempRegister); 1337 1338 if (cond == NotEqual) 1339 return branchFalse(); 1340 return branchTrue(); 1341 } 1342 1343 Jump branch16(Condition cond, BaseIndex left, RegisterID right) 1344 { 1345 RegisterID scr = claimScratch(); 1346 1347 move(left.index, scr); 1348 lshift32(TrustedImm32(left.scale), scr); 1349 1350 if (left.offset) 1351 add32(TrustedImm32(left.offset), scr); 1352 add32(left.base, scr); 1353 load16(scr, scr); 1354 extuw(scr, scr); 1355 releaseScratch(scr); 1356 1357 return branch32(cond, scr, right); 1358 } 1359 1360 Jump branch16(Condition cond, BaseIndex left, TrustedImm32 right) 1361 { 1362 RegisterID scr = claimScratch(); 1363 1364 move(left.index, scr); 1365 lshift32(TrustedImm32(left.scale), scr); 1366 1367 if (left.offset) 1368 add32(TrustedImm32(left.offset), scr); 1369 add32(left.base, scr); 1370 load16(scr, scr); 1371 extuw(scr, scr); 1372 RegisterID scr1 = claimScratch(); 1373 m_assembler.loadConstant(right.m_value, scr1); 1374 releaseScratch(scr); 1375 releaseScratch(scr1); 1376 1377 return branch32(cond, scr, scr1); 1378 } 1379 1380 Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask) 1381 { 1382 ASSERT((cond == Zero) || (cond == NonZero)); 1383 1384 m_assembler.testlRegReg(reg, mask); 1385 1386 if (cond == NotEqual) 1387 return branchFalse(); 1388 return branchTrue(); 1389 } 1390 1391 Jump branchTest32(Condition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) 1392 { 1393 ASSERT((cond == Zero) || (cond == NonZero)); 1394 1395 if (mask.m_value == -1) 1396 m_assembler.testlRegReg(reg, reg); 1397 else 1398 testlImm(mask.m_value, reg); 1399 1400 if (cond == NotEqual) 1401 return branchFalse(); 1402 return branchTrue(); 1403 } 1404 1405 Jump branchTest32(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) 1406 { 1407 ASSERT((cond == Zero) || (cond == NonZero)); 1408 1409 if (mask.m_value == -1) 1410 compare32(0, address.offset, address.base, cond); 1411 else 1412 testImm(mask.m_value, address.offset, address.base); 1413 1414 if (cond == NotEqual) 1415 return branchFalse(); 1416 return branchTrue(); 1417 } 1418 1419 Jump branchTest32(Condition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) 1420 { 1421 RegisterID scr = claimScratch(); 1422 1423 move(address.index, scr); 1424 lshift32(TrustedImm32(address.scale), scr); 1425 add32(address.base, scr); 1426 load32(scr, address.offset, scr); 1427 1428 if (mask.m_value == -1) 1429 m_assembler.testlRegReg(scr, scr); 1430 else 1431 testlImm(mask.m_value, scr); 1432 1433 releaseScratch(scr); 1434 1435 if (cond == NotEqual) 1436 return branchFalse(); 1437 return branchTrue(); 1438 } 1439 1440 Jump jump() 1441 { 1442 return Jump(m_assembler.jmp()); 1443 } 1444 1445 void jump(RegisterID target) 1446 { 1447 m_assembler.jmpReg(target); 1448 } 1449 1450 void jump(Address address) 1451 { 1452 RegisterID scr = claimScratch(); 1453 1454 if ((address.offset < 0) || (address.offset >= 64)) { 1455 m_assembler.loadConstant(address.offset, scr); 1456 m_assembler.addlRegReg(address.base, scr); 1457 m_assembler.movlMemReg(scr, scr); 1458 } else if (address.offset) 1459 m_assembler.movlMemReg(address.offset >> 2, address.base, scr); 1460 else 1461 m_assembler.movlMemReg(address.base, scr); 1462 m_assembler.jmpReg(scr); 1463 1464 releaseScratch(scr); 1465 } 1466 1467 // Arithmetic control flow operations 1468 1469 Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest) 1470 { 1471 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1472 1473 if (cond == Overflow) { 1474 m_assembler.addvlRegReg(src, dest); 1475 return branchTrue(); 1476 } 1477 1478 if (cond == Signed) { 1479 m_assembler.addlRegReg(src, dest); 1480 // Check if dest is negative 1481 m_assembler.cmppz(dest); 1482 return branchFalse(); 1483 } 1484 1485 m_assembler.addlRegReg(src, dest); 1486 compare32(0, dest, Equal); 1487 1488 if (cond == NotEqual) 1489 return branchFalse(); 1490 return branchTrue(); 1491 } 1492 1493 Jump branchAdd32(Condition cond, TrustedImm32 imm, RegisterID dest) 1494 { 1495 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1496 1497 move(imm, scratchReg3); 1498 return branchAdd32(cond, scratchReg3, dest); 1499 } 1500 1501 Jump branchMul32(Condition cond, RegisterID src, RegisterID dest) 1502 { 1503 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1504 1505 if (cond == Overflow) { 1506 RegisterID scr1 = claimScratch(); 1507 RegisterID scr = claimScratch(); 1508 m_assembler.dmullRegReg(src, dest); 1509 m_assembler.stsmacl(dest); 1510 m_assembler.movImm8(-31, scr); 1511 m_assembler.movlRegReg(dest, scr1); 1512 m_assembler.shaRegReg(scr1, scr); 1513 m_assembler.stsmach(scr); 1514 m_assembler.cmplRegReg(scr, scr1, Zero); 1515 releaseScratch(scr1); 1516 releaseScratch(scr); 1517 return branchFalse(); 1518 } 1519 1520 m_assembler.imullRegReg(src, dest); 1521 m_assembler.stsmacl(dest); 1522 if (cond == Signed) { 1523 // Check if dest is negative 1524 m_assembler.cmppz(dest); 1525 return branchFalse(); 1526 } 1527 1528 compare32(0, dest, cond); 1529 1530 if (cond == NotEqual) 1531 return branchFalse(); 1532 return branchTrue(); 1533 } 1534 1535 Jump branchMul32(Condition cond, TrustedImm32 imm, RegisterID src, RegisterID dest) 1536 { 1537 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1538 1539 move(imm, scratchReg3); 1540 if (src != dest) 1541 move(src, dest); 1542 1543 return branchMul32(cond, scratchReg3, dest); 1544 } 1545 1546 Jump branchSub32(Condition cond, RegisterID src, RegisterID dest) 1547 { 1548 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1549 1550 if (cond == Overflow) { 1551 m_assembler.subvlRegReg(src, dest); 1552 return branchTrue(); 1553 } 1554 1555 if (cond == Signed) { 1556 // Check if dest is negative 1557 m_assembler.sublRegReg(src, dest); 1558 compare32(0, dest, LessThan); 1559 return branchTrue(); 1560 } 1561 1562 sub32(src, dest); 1563 compare32(0, dest, cond); 1564 1565 if (cond == NotEqual) 1566 return branchFalse(); 1567 return branchTrue(); 1568 } 1569 1570 Jump branchSub32(Condition cond, TrustedImm32 imm, RegisterID dest) 1571 { 1572 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1573 1574 move(imm, scratchReg3); 1575 return branchSub32(cond, scratchReg3, dest); 1576 } 1577 1578 Jump branchOr32(Condition cond, RegisterID src, RegisterID dest) 1579 { 1580 ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero)); 1581 1582 if (cond == Signed) { 1583 or32(src, dest); 1584 compare32(0, dest, LessThan); 1585 return branchTrue(); 1586 } 1587 1588 or32(src, dest); 1589 compare32(0, dest, cond); 1590 1591 if (cond == NotEqual) 1592 return branchFalse(); 1593 return branchTrue(); 1594 } 1595 1596 void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp) 1597 { 1598 m_assembler.ftrcdrmfpul(src); 1599 m_assembler.stsfpulReg(dest); 1600 convertInt32ToDouble(dest, fscratch); 1601 failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fscratch, src)); 1602 1603 if (dest == SH4Registers::r0) 1604 m_assembler.cmpEqImmR0(0, dest, Equal); 1605 else { 1606 m_assembler.movImm8(0, scratchReg3); 1607 m_assembler.cmplRegReg(scratchReg3, dest, Equal); 1608 } 1609 failureCases.append(branchTrue()); 1610 } 1611 1612 void neg32(RegisterID dst) 1613 { 1614 m_assembler.neg(dst, dst); 1615 } 1616 1617 void not32(RegisterID dst) 1618 { 1619 m_assembler.notlReg(dst, dst); 1620 } 1621 1622 void urshift32(RegisterID shiftamount, RegisterID dest) 1623 { 1624 compare32(32, shiftamount, Equal); 1625 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4); 1626 m_assembler.branch(BT_OPCODE, 1); 1627 m_assembler.neg(shiftamount, shiftamount); 1628 m_assembler.shllRegReg(dest, shiftamount); 1629 } 1630 1631 void urshift32(TrustedImm32 imm, RegisterID dest) 1632 { 1633 RegisterID scr = claimScratch(); 1634 m_assembler.loadConstant(-(imm.m_value), scr); 1635 m_assembler.shaRegReg(dest, scr); 1636 releaseScratch(scr); 1637 } 1638 1639 Call call() 1640 { 1641 return Call(m_assembler.call(), Call::Linkable); 1642 } 1643 1644 Call nearCall() 1645 { 1646 return Call(m_assembler.call(), Call::LinkableNear); 1647 } 1648 1649 Call call(RegisterID target) 1650 { 1651 return Call(m_assembler.call(target), Call::None); 1652 } 1653 1654 void call(Address address, RegisterID target) 1655 { 1656 load32(address.base, address.offset, target); 1657 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 2); 1658 m_assembler.branch(JSR_OPCODE, target); 1659 m_assembler.nop(); 1660 } 1661 1662 void breakpoint() 1663 { 1664 m_assembler.bkpt(); 1665 m_assembler.nop(); 1666 } 1667 1668 Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) 1669 { 1670 RegisterID dataTempRegister = claimScratch(); 1671 1672 dataLabel = moveWithPatch(initialRightValue, dataTempRegister); 1673 m_assembler.cmplRegReg(dataTempRegister, left, cond); 1674 releaseScratch(dataTempRegister); 1675 1676 if (cond == NotEqual) 1677 return branchFalse(); 1678 return branchTrue(); 1679 } 1680 1681 Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) 1682 { 1683 RegisterID scr = claimScratch(); 1684 1685 m_assembler.loadConstant(left.offset, scr); 1686 m_assembler.addlRegReg(left.base, scr); 1687 m_assembler.movlMemReg(scr, scr); 1688 RegisterID scr1 = claimScratch(); 1689 dataLabel = moveWithPatch(initialRightValue, scr1); 1690 m_assembler.cmplRegReg(scr1, scr, cond); 1691 releaseScratch(scr); 1692 releaseScratch(scr1); 1693 1694 if (cond == NotEqual) 1695 return branchFalse(); 1696 return branchTrue(); 1697 } 1698 1699 void ret() 1700 { 1701 m_assembler.ret(); 1702 m_assembler.nop(); 1703 } 1704 1705 DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address) 1706 { 1707 RegisterID scr = claimScratch(); 1708 DataLabelPtr label = moveWithPatch(initialValue, scr); 1709 store32(scr, address); 1710 releaseScratch(scr); 1711 return label; 1712 } 1713 1714 DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(TrustedImmPtr(0), address); } 1715 1716 int sizeOfConstantPool() 1717 { 1718 return m_assembler.sizeOfConstantPool(); 1719 } 1720 1721 Call tailRecursiveCall() 1722 { 1723 RegisterID scr = claimScratch(); 1724 1725 m_assembler.loadConstantUnReusable(0x0, scr, true); 1726 Jump m_jump = Jump(m_assembler.jmp(scr)); 1727 releaseScratch(scr); 1728 1729 return Call::fromTailJump(m_jump); 1730 } 1731 1732 Call makeTailRecursiveCall(Jump oldJump) 1733 { 1734 oldJump.link(this); 1735 return tailRecursiveCall(); 1736 } 1737 1738private: 1739 friend class LinkBuffer; 1740 friend class RepatchBuffer; 1741 1742 static void linkCall(void*, Call, FunctionPtr); 1743 static void repatchCall(CodeLocationCall, CodeLocationLabel); 1744 static void repatchCall(CodeLocationCall, FunctionPtr); 1745}; 1746 1747} // namespace JSC 1748 1749#endif // ENABLE(ASSEMBLER) 1750 1751#endif // MacroAssemblerSH4_h 1752