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