1 /* 2 * Copyright (C) 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2010 MIPS Technologies, 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 MIPS TECHNOLOGIES, 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 MIPS TECHNOLOGIES, 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 MacroAssemblerMIPS_h 28 #define MacroAssemblerMIPS_h 29 30 #include <Platform.h> 31 32 #if ENABLE(ASSEMBLER) && CPU(MIPS) 33 34 #include "AbstractMacroAssembler.h" 35 #include "MIPSAssembler.h" 36 37 namespace JSC { 38 39 class MacroAssemblerMIPS : public AbstractMacroAssembler<MIPSAssembler> { 40 public: 41 typedef MIPSRegisters::FPRegisterID FPRegisterID; 42 static const int PointerSize = 4; 43 MacroAssemblerMIPS()44 MacroAssemblerMIPS() 45 : m_fixedWidth(false) 46 { 47 } 48 isCompactPtrAlignedAddressOffset(ptrdiff_t value)49 static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value) 50 { 51 return value >= -2147483647 - 1 && value <= 2147483647; 52 } 53 54 static const Scale ScalePtr = TimesFour; 55 56 // For storing immediate number 57 static const RegisterID immTempRegister = MIPSRegisters::t0; 58 // For storing data loaded from the memory 59 static const RegisterID dataTempRegister = MIPSRegisters::t1; 60 // For storing address base 61 static const RegisterID addrTempRegister = MIPSRegisters::t2; 62 // For storing compare result 63 static const RegisterID cmpTempRegister = MIPSRegisters::t3; 64 65 // FP temp register 66 static const FPRegisterID fpTempRegister = MIPSRegisters::f16; 67 68 static const int MaximumCompactPtrAlignedAddressOffset = 0x7FFFFFFF; 69 70 enum RelationalCondition { 71 Equal, 72 NotEqual, 73 Above, 74 AboveOrEqual, 75 Below, 76 BelowOrEqual, 77 GreaterThan, 78 GreaterThanOrEqual, 79 LessThan, 80 LessThanOrEqual 81 }; 82 83 enum ResultCondition { 84 Overflow, 85 Signed, 86 Zero, 87 NonZero 88 }; 89 90 enum DoubleCondition { 91 DoubleEqual, 92 DoubleNotEqual, 93 DoubleGreaterThan, 94 DoubleGreaterThanOrEqual, 95 DoubleLessThan, 96 DoubleLessThanOrEqual, 97 DoubleEqualOrUnordered, 98 DoubleNotEqualOrUnordered, 99 DoubleGreaterThanOrUnordered, 100 DoubleGreaterThanOrEqualOrUnordered, 101 DoubleLessThanOrUnordered, 102 DoubleLessThanOrEqualOrUnordered 103 }; 104 105 static const RegisterID stackPointerRegister = MIPSRegisters::sp; 106 static const RegisterID returnAddressRegister = MIPSRegisters::ra; 107 108 // Integer arithmetic operations: 109 // 110 // Operations are typically two operand - operation(source, srcDst) 111 // For many operations the source may be an TrustedImm32, the srcDst operand 112 // may often be a memory location (explictly described using an Address 113 // object). 114 add32(RegisterID src,RegisterID dest)115 void add32(RegisterID src, RegisterID dest) 116 { 117 m_assembler.addu(dest, dest, src); 118 } 119 add32(RegisterID op1,RegisterID op2,RegisterID dest)120 void add32(RegisterID op1, RegisterID op2, RegisterID dest) 121 { 122 m_assembler.addu(dest, op1, op2); 123 } 124 add32(TrustedImm32 imm,RegisterID dest)125 void add32(TrustedImm32 imm, RegisterID dest) 126 { 127 add32(imm, dest, dest); 128 } 129 add32(TrustedImm32 imm,RegisterID src,RegisterID dest)130 void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) 131 { 132 if (imm.m_value >= -32768 && imm.m_value <= 32767 133 && !m_fixedWidth) { 134 /* 135 addiu dest, src, imm 136 */ 137 m_assembler.addiu(dest, src, imm.m_value); 138 } else { 139 /* 140 li immTemp, imm 141 addu dest, src, immTemp 142 */ 143 move(imm, immTempRegister); 144 m_assembler.addu(dest, src, immTempRegister); 145 } 146 } 147 add32(RegisterID src,TrustedImm32 imm,RegisterID dest)148 void add32(RegisterID src, TrustedImm32 imm, RegisterID dest) 149 { 150 add32(imm, src, dest); 151 } 152 add32(TrustedImm32 imm,Address address)153 void add32(TrustedImm32 imm, Address address) 154 { 155 if (address.offset >= -32768 && address.offset <= 32767 156 && !m_fixedWidth) { 157 /* 158 lw dataTemp, offset(base) 159 li immTemp, imm 160 addu dataTemp, dataTemp, immTemp 161 sw dataTemp, offset(base) 162 */ 163 m_assembler.lw(dataTempRegister, address.base, address.offset); 164 if (imm.m_value >= -32768 && imm.m_value <= 32767 165 && !m_fixedWidth) 166 m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value); 167 else { 168 move(imm, immTempRegister); 169 m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister); 170 } 171 m_assembler.sw(dataTempRegister, address.base, address.offset); 172 } else { 173 /* 174 lui addrTemp, (offset + 0x8000) >> 16 175 addu addrTemp, addrTemp, base 176 lw dataTemp, (offset & 0xffff)(addrTemp) 177 li immtemp, imm 178 addu dataTemp, dataTemp, immTemp 179 sw dataTemp, (offset & 0xffff)(addrTemp) 180 */ 181 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 182 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 183 m_assembler.lw(dataTempRegister, addrTempRegister, address.offset); 184 185 if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) 186 m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value); 187 else { 188 move(imm, immTempRegister); 189 m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister); 190 } 191 m_assembler.sw(dataTempRegister, addrTempRegister, address.offset); 192 } 193 } 194 add32(Address src,RegisterID dest)195 void add32(Address src, RegisterID dest) 196 { 197 load32(src, dataTempRegister); 198 add32(dataTempRegister, dest); 199 } 200 add32(AbsoluteAddress src,RegisterID dest)201 void add32(AbsoluteAddress src, RegisterID dest) 202 { 203 load32(src.m_ptr, dataTempRegister); 204 add32(dataTempRegister, dest); 205 } 206 add32(RegisterID src,Address dest)207 void add32(RegisterID src, Address dest) 208 { 209 if (dest.offset >= -32768 && dest.offset <= 32767 && !m_fixedWidth) { 210 /* 211 lw dataTemp, offset(base) 212 addu dataTemp, dataTemp, src 213 sw dataTemp, offset(base) 214 */ 215 m_assembler.lw(dataTempRegister, dest.base, dest.offset); 216 m_assembler.addu(dataTempRegister, dataTempRegister, src); 217 m_assembler.sw(dataTempRegister, dest.base, dest.offset); 218 } else { 219 /* 220 lui addrTemp, (offset + 0x8000) >> 16 221 addu addrTemp, addrTemp, base 222 lw dataTemp, (offset & 0xffff)(addrTemp) 223 addu dataTemp, dataTemp, src 224 sw dataTemp, (offset & 0xffff)(addrTemp) 225 */ 226 m_assembler.lui(addrTempRegister, (dest.offset + 0x8000) >> 16); 227 m_assembler.addu(addrTempRegister, addrTempRegister, dest.base); 228 m_assembler.lw(dataTempRegister, addrTempRegister, dest.offset); 229 m_assembler.addu(dataTempRegister, dataTempRegister, src); 230 m_assembler.sw(dataTempRegister, addrTempRegister, dest.offset); 231 } 232 } 233 add32(TrustedImm32 imm,AbsoluteAddress address)234 void add32(TrustedImm32 imm, AbsoluteAddress address) 235 { 236 /* 237 li addrTemp, address 238 li immTemp, imm 239 lw cmpTemp, 0(addrTemp) 240 addu dataTemp, cmpTemp, immTemp 241 sw dataTemp, 0(addrTemp) 242 */ 243 move(TrustedImmPtr(address.m_ptr), addrTempRegister); 244 m_assembler.lw(cmpTempRegister, addrTempRegister, 0); 245 if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) 246 m_assembler.addiu(dataTempRegister, cmpTempRegister, imm.m_value); 247 else { 248 move(imm, immTempRegister); 249 m_assembler.addu(dataTempRegister, cmpTempRegister, immTempRegister); 250 } 251 m_assembler.sw(dataTempRegister, addrTempRegister, 0); 252 } 253 add64(TrustedImm32 imm,AbsoluteAddress address)254 void add64(TrustedImm32 imm, AbsoluteAddress address) 255 { 256 /* 257 add32(imm, address) 258 sltu immTemp, dataTemp, cmpTemp # set carry-in bit 259 lw dataTemp, 4(addrTemp) 260 addiu dataTemp, imm.m_value >> 31 ? -1 : 0 261 addu dataTemp, dataTemp, immTemp 262 sw dataTemp, 4(addrTemp) 263 */ 264 add32(imm, address); 265 m_assembler.sltu(immTempRegister, dataTempRegister, cmpTempRegister); 266 m_assembler.lw(dataTempRegister, addrTempRegister, 4); 267 if (imm.m_value >> 31) 268 m_assembler.addiu(dataTempRegister, dataTempRegister, -1); 269 m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister); 270 m_assembler.sw(dataTempRegister, addrTempRegister, 4); 271 } 272 getEffectiveAddress(BaseIndex address,RegisterID dest)273 void getEffectiveAddress(BaseIndex address, RegisterID dest) 274 { 275 if (!address.scale && !m_fixedWidth) 276 m_assembler.addu(dest, address.index, address.base); 277 else { 278 m_assembler.sll(addrTempRegister, address.index, address.scale); 279 m_assembler.addu(dest, addrTempRegister, address.base); 280 } 281 if (address.offset) 282 add32(TrustedImm32(address.offset), dest); 283 } 284 and32(Address src,RegisterID dest)285 void and32(Address src, RegisterID dest) 286 { 287 load32(src, dataTempRegister); 288 and32(dataTempRegister, dest); 289 } 290 and32(RegisterID src,RegisterID dest)291 void and32(RegisterID src, RegisterID dest) 292 { 293 m_assembler.andInsn(dest, dest, src); 294 } 295 and32(RegisterID op1,RegisterID op2,RegisterID dest)296 void and32(RegisterID op1, RegisterID op2, RegisterID dest) 297 { 298 m_assembler.andInsn(dest, op1, op2); 299 } 300 and32(TrustedImm32 imm,RegisterID dest)301 void and32(TrustedImm32 imm, RegisterID dest) 302 { 303 if (!imm.m_value && !m_fixedWidth) 304 move(MIPSRegisters::zero, dest); 305 else if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth) 306 m_assembler.andi(dest, dest, imm.m_value); 307 else { 308 /* 309 li immTemp, imm 310 and dest, dest, immTemp 311 */ 312 move(imm, immTempRegister); 313 m_assembler.andInsn(dest, dest, immTempRegister); 314 } 315 } 316 and32(TrustedImm32 imm,RegisterID src,RegisterID dest)317 void and32(TrustedImm32 imm, RegisterID src, RegisterID dest) 318 { 319 if (!imm.m_value && !m_fixedWidth) 320 move(MIPSRegisters::zero, dest); 321 else if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth) 322 m_assembler.andi(dest, src, imm.m_value); 323 else { 324 move(imm, immTempRegister); 325 m_assembler.andInsn(dest, src, immTempRegister); 326 } 327 } 328 lshift32(RegisterID shiftAmount,RegisterID dest)329 void lshift32(RegisterID shiftAmount, RegisterID dest) 330 { 331 m_assembler.sllv(dest, dest, shiftAmount); 332 } 333 lshift32(RegisterID src,RegisterID shiftAmount,RegisterID dest)334 void lshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) 335 { 336 m_assembler.sllv(dest, src, shiftAmount); 337 } 338 lshift32(TrustedImm32 imm,RegisterID dest)339 void lshift32(TrustedImm32 imm, RegisterID dest) 340 { 341 move(imm, immTempRegister); 342 m_assembler.sllv(dest, dest, immTempRegister); 343 } 344 lshift32(RegisterID src,TrustedImm32 imm,RegisterID dest)345 void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) 346 { 347 move(imm, immTempRegister); 348 m_assembler.sllv(dest, src, immTempRegister); 349 } 350 mul32(RegisterID src,RegisterID dest)351 void mul32(RegisterID src, RegisterID dest) 352 { 353 m_assembler.mul(dest, dest, src); 354 } 355 mul32(RegisterID op1,RegisterID op2,RegisterID dest)356 void mul32(RegisterID op1, RegisterID op2, RegisterID dest) 357 { 358 m_assembler.mul(dest, op1, op2); 359 } 360 mul32(TrustedImm32 imm,RegisterID src,RegisterID dest)361 void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest) 362 { 363 if (!imm.m_value && !m_fixedWidth) 364 move(MIPSRegisters::zero, dest); 365 else if (imm.m_value == 1 && !m_fixedWidth) 366 move(src, dest); 367 else { 368 /* 369 li dataTemp, imm 370 mul dest, src, dataTemp 371 */ 372 move(imm, dataTempRegister); 373 m_assembler.mul(dest, src, dataTempRegister); 374 } 375 } 376 mul32(Address src,RegisterID dest)377 void mul32(Address src, RegisterID dest) 378 { 379 load32(src, dataTempRegister); 380 mul32(dataTempRegister, dest); 381 } 382 neg32(RegisterID srcDest)383 void neg32(RegisterID srcDest) 384 { 385 m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest); 386 } 387 or32(RegisterID src,RegisterID dest)388 void or32(RegisterID src, RegisterID dest) 389 { 390 m_assembler.orInsn(dest, dest, src); 391 } 392 or32(RegisterID op1,RegisterID op2,RegisterID dest)393 void or32(RegisterID op1, RegisterID op2, RegisterID dest) 394 { 395 m_assembler.orInsn(dest, op1, op2); 396 } 397 or32(TrustedImm32 imm,RegisterID dest)398 void or32(TrustedImm32 imm, RegisterID dest) 399 { 400 if (!imm.m_value && !m_fixedWidth) 401 return; 402 403 if (imm.m_value > 0 && imm.m_value < 65535 404 && !m_fixedWidth) { 405 m_assembler.ori(dest, dest, imm.m_value); 406 return; 407 } 408 409 /* 410 li dataTemp, imm 411 or dest, dest, dataTemp 412 */ 413 move(imm, dataTempRegister); 414 m_assembler.orInsn(dest, dest, dataTempRegister); 415 } 416 or32(TrustedImm32 imm,RegisterID src,RegisterID dest)417 void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) 418 { 419 if (!imm.m_value && !m_fixedWidth) { 420 move(src, dest); 421 return; 422 } 423 424 if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth) { 425 m_assembler.ori(dest, src, imm.m_value); 426 return; 427 } 428 429 /* 430 li dataTemp, imm 431 or dest, src, dataTemp 432 */ 433 move(imm, dataTempRegister); 434 m_assembler.orInsn(dest, src, dataTempRegister); 435 } 436 or32(RegisterID src,AbsoluteAddress dest)437 void or32(RegisterID src, AbsoluteAddress dest) 438 { 439 load32(dest.m_ptr, dataTempRegister); 440 m_assembler.orInsn(dataTempRegister, dataTempRegister, src); 441 store32(dataTempRegister, dest.m_ptr); 442 } 443 or32(Address src,RegisterID dest)444 void or32(Address src, RegisterID dest) 445 { 446 load32(src, dataTempRegister); 447 or32(dataTempRegister, dest); 448 } 449 rshift32(RegisterID shiftAmount,RegisterID dest)450 void rshift32(RegisterID shiftAmount, RegisterID dest) 451 { 452 m_assembler.srav(dest, dest, shiftAmount); 453 } 454 rshift32(RegisterID src,RegisterID shiftAmount,RegisterID dest)455 void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) 456 { 457 m_assembler.srav(dest, src, shiftAmount); 458 } 459 rshift32(TrustedImm32 imm,RegisterID dest)460 void rshift32(TrustedImm32 imm, RegisterID dest) 461 { 462 m_assembler.sra(dest, dest, imm.m_value); 463 } 464 rshift32(RegisterID src,TrustedImm32 imm,RegisterID dest)465 void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) 466 { 467 m_assembler.sra(dest, src, imm.m_value); 468 } 469 urshift32(RegisterID shiftAmount,RegisterID dest)470 void urshift32(RegisterID shiftAmount, RegisterID dest) 471 { 472 m_assembler.srlv(dest, dest, shiftAmount); 473 } 474 urshift32(RegisterID src,RegisterID shiftAmount,RegisterID dest)475 void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) 476 { 477 m_assembler.srlv(dest, src, shiftAmount); 478 } 479 urshift32(TrustedImm32 imm,RegisterID dest)480 void urshift32(TrustedImm32 imm, RegisterID dest) 481 { 482 m_assembler.srl(dest, dest, imm.m_value); 483 } 484 urshift32(RegisterID src,TrustedImm32 imm,RegisterID dest)485 void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) 486 { 487 m_assembler.srl(dest, src, imm.m_value); 488 } 489 sub32(RegisterID src,RegisterID dest)490 void sub32(RegisterID src, RegisterID dest) 491 { 492 m_assembler.subu(dest, dest, src); 493 } 494 sub32(RegisterID op1,RegisterID op2,RegisterID dest)495 void sub32(RegisterID op1, RegisterID op2, RegisterID dest) 496 { 497 m_assembler.subu(dest, op1, op2); 498 } 499 sub32(TrustedImm32 imm,RegisterID dest)500 void sub32(TrustedImm32 imm, RegisterID dest) 501 { 502 if (imm.m_value >= -32767 && imm.m_value <= 32768 503 && !m_fixedWidth) { 504 /* 505 addiu dest, src, imm 506 */ 507 m_assembler.addiu(dest, dest, -imm.m_value); 508 } else { 509 /* 510 li immTemp, imm 511 subu dest, src, immTemp 512 */ 513 move(imm, immTempRegister); 514 m_assembler.subu(dest, dest, immTempRegister); 515 } 516 } 517 sub32(RegisterID src,TrustedImm32 imm,RegisterID dest)518 void sub32(RegisterID src, TrustedImm32 imm, RegisterID dest) 519 { 520 if (imm.m_value >= -32767 && imm.m_value <= 32768 521 && !m_fixedWidth) { 522 /* 523 addiu dest, src, imm 524 */ 525 m_assembler.addiu(dest, src, -imm.m_value); 526 } else { 527 /* 528 li immTemp, imm 529 subu dest, src, immTemp 530 */ 531 move(imm, immTempRegister); 532 m_assembler.subu(dest, src, immTempRegister); 533 } 534 } 535 sub32(TrustedImm32 imm,Address address)536 void sub32(TrustedImm32 imm, Address address) 537 { 538 if (address.offset >= -32768 && address.offset <= 32767 539 && !m_fixedWidth) { 540 /* 541 lw dataTemp, offset(base) 542 li immTemp, imm 543 subu dataTemp, dataTemp, immTemp 544 sw dataTemp, offset(base) 545 */ 546 m_assembler.lw(dataTempRegister, address.base, address.offset); 547 if (imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth) 548 m_assembler.addiu(dataTempRegister, dataTempRegister, -imm.m_value); 549 else { 550 move(imm, immTempRegister); 551 m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister); 552 } 553 m_assembler.sw(dataTempRegister, address.base, address.offset); 554 } else { 555 /* 556 lui addrTemp, (offset + 0x8000) >> 16 557 addu addrTemp, addrTemp, base 558 lw dataTemp, (offset & 0xffff)(addrTemp) 559 li immtemp, imm 560 subu dataTemp, dataTemp, immTemp 561 sw dataTemp, (offset & 0xffff)(addrTemp) 562 */ 563 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 564 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 565 m_assembler.lw(dataTempRegister, addrTempRegister, address.offset); 566 567 if (imm.m_value >= -32767 && imm.m_value <= 32768 568 && !m_fixedWidth) 569 m_assembler.addiu(dataTempRegister, dataTempRegister, -imm.m_value); 570 else { 571 move(imm, immTempRegister); 572 m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister); 573 } 574 m_assembler.sw(dataTempRegister, addrTempRegister, address.offset); 575 } 576 } 577 sub32(Address src,RegisterID dest)578 void sub32(Address src, RegisterID dest) 579 { 580 load32(src, dataTempRegister); 581 sub32(dataTempRegister, dest); 582 } 583 sub32(TrustedImm32 imm,AbsoluteAddress address)584 void sub32(TrustedImm32 imm, AbsoluteAddress address) 585 { 586 /* 587 li addrTemp, address 588 li immTemp, imm 589 lw dataTemp, 0(addrTemp) 590 subu dataTemp, dataTemp, immTemp 591 sw dataTemp, 0(addrTemp) 592 */ 593 move(TrustedImmPtr(address.m_ptr), addrTempRegister); 594 m_assembler.lw(dataTempRegister, addrTempRegister, 0); 595 596 if (imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth) 597 m_assembler.addiu(dataTempRegister, dataTempRegister, -imm.m_value); 598 else { 599 move(imm, immTempRegister); 600 m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister); 601 } 602 m_assembler.sw(dataTempRegister, addrTempRegister, 0); 603 } 604 xor32(RegisterID src,RegisterID dest)605 void xor32(RegisterID src, RegisterID dest) 606 { 607 m_assembler.xorInsn(dest, dest, src); 608 } 609 xor32(RegisterID op1,RegisterID op2,RegisterID dest)610 void xor32(RegisterID op1, RegisterID op2, RegisterID dest) 611 { 612 m_assembler.xorInsn(dest, op1, op2); 613 } 614 xor32(TrustedImm32 imm,RegisterID dest)615 void xor32(TrustedImm32 imm, RegisterID dest) 616 { 617 if (imm.m_value == -1) { 618 m_assembler.nor(dest, dest, MIPSRegisters::zero); 619 return; 620 } 621 622 /* 623 li immTemp, imm 624 xor dest, dest, immTemp 625 */ 626 move(imm, immTempRegister); 627 m_assembler.xorInsn(dest, dest, immTempRegister); 628 } 629 xor32(TrustedImm32 imm,RegisterID src,RegisterID dest)630 void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest) 631 { 632 if (imm.m_value == -1) { 633 m_assembler.nor(dest, src, MIPSRegisters::zero); 634 return; 635 } 636 637 /* 638 li immTemp, imm 639 xor dest, dest, immTemp 640 */ 641 move(imm, immTempRegister); 642 m_assembler.xorInsn(dest, src, immTempRegister); 643 } 644 xor32(Address src,RegisterID dest)645 void xor32(Address src, RegisterID dest) 646 { 647 load32(src, dataTempRegister); 648 xor32(dataTempRegister, dest); 649 } 650 sqrtDouble(FPRegisterID src,FPRegisterID dst)651 void sqrtDouble(FPRegisterID src, FPRegisterID dst) 652 { 653 m_assembler.sqrtd(dst, src); 654 } 655 absDouble(FPRegisterID,FPRegisterID)656 void absDouble(FPRegisterID, FPRegisterID) 657 { 658 RELEASE_ASSERT_NOT_REACHED(); 659 } 660 convertibleLoadPtr(Address address,RegisterID dest)661 ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest) 662 { 663 ConvertibleLoadLabel result(this); 664 /* 665 lui addrTemp, (offset + 0x8000) >> 16 666 addu addrTemp, addrTemp, base 667 lw dest, (offset & 0xffff)(addrTemp) 668 */ 669 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 670 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 671 m_assembler.lw(dest, addrTempRegister, address.offset); 672 return result; 673 } 674 675 // Memory access operations: 676 // 677 // Loads are of the form load(address, destination) and stores of the form 678 // store(source, address). The source for a store may be an TrustedImm32. Address 679 // operand objects to loads and store will be implicitly constructed if a 680 // register is passed. 681 682 /* Need to use zero-extened load byte for load8. */ load8(ImplicitAddress address,RegisterID dest)683 void load8(ImplicitAddress address, RegisterID dest) 684 { 685 if (address.offset >= -32768 && address.offset <= 32767 686 && !m_fixedWidth) 687 m_assembler.lbu(dest, address.base, address.offset); 688 else { 689 /* 690 lui addrTemp, (offset + 0x8000) >> 16 691 addu addrTemp, addrTemp, base 692 lbu dest, (offset & 0xffff)(addrTemp) 693 */ 694 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 695 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 696 m_assembler.lbu(dest, addrTempRegister, address.offset); 697 } 698 } 699 load8(BaseIndex address,RegisterID dest)700 void load8(BaseIndex address, RegisterID dest) 701 { 702 if (address.offset >= -32768 && address.offset <= 32767 703 && !m_fixedWidth) { 704 /* 705 sll addrTemp, address.index, address.scale 706 addu addrTemp, addrTemp, address.base 707 lbu dest, address.offset(addrTemp) 708 */ 709 m_assembler.sll(addrTempRegister, address.index, address.scale); 710 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 711 m_assembler.lbu(dest, addrTempRegister, address.offset); 712 } else { 713 /* 714 sll addrTemp, address.index, address.scale 715 addu addrTemp, addrTemp, address.base 716 lui immTemp, (address.offset + 0x8000) >> 16 717 addu addrTemp, addrTemp, immTemp 718 lbu dest, (address.offset & 0xffff)(at) 719 */ 720 m_assembler.sll(addrTempRegister, address.index, address.scale); 721 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 722 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 723 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 724 m_assembler.lbu(dest, addrTempRegister, address.offset); 725 } 726 } 727 load8Signed(BaseIndex address,RegisterID dest)728 void load8Signed(BaseIndex address, RegisterID dest) 729 { 730 if (address.offset >= -32768 && address.offset <= 32767 731 && !m_fixedWidth) { 732 /* 733 sll addrTemp, address.index, address.scale 734 addu addrTemp, addrTemp, address.base 735 lb dest, address.offset(addrTemp) 736 */ 737 m_assembler.sll(addrTempRegister, address.index, address.scale); 738 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 739 m_assembler.lb(dest, addrTempRegister, address.offset); 740 } else { 741 /* 742 sll addrTemp, address.index, address.scale 743 addu addrTemp, addrTemp, address.base 744 lui immTemp, (address.offset + 0x8000) >> 16 745 addu addrTemp, addrTemp, immTemp 746 lb dest, (address.offset & 0xffff)(at) 747 */ 748 m_assembler.sll(addrTempRegister, address.index, address.scale); 749 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 750 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 751 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 752 m_assembler.lb(dest, addrTempRegister, address.offset); 753 } 754 } 755 load32(ImplicitAddress address,RegisterID dest)756 void load32(ImplicitAddress address, RegisterID dest) 757 { 758 if (address.offset >= -32768 && address.offset <= 32767 759 && !m_fixedWidth) 760 m_assembler.lw(dest, address.base, address.offset); 761 else { 762 /* 763 lui addrTemp, (offset + 0x8000) >> 16 764 addu addrTemp, addrTemp, base 765 lw dest, (offset & 0xffff)(addrTemp) 766 */ 767 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 768 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 769 m_assembler.lw(dest, addrTempRegister, address.offset); 770 } 771 } 772 load32(BaseIndex address,RegisterID dest)773 void load32(BaseIndex address, RegisterID dest) 774 { 775 if (address.offset >= -32768 && address.offset <= 32767 776 && !m_fixedWidth) { 777 /* 778 sll addrTemp, address.index, address.scale 779 addu addrTemp, addrTemp, address.base 780 lw dest, address.offset(addrTemp) 781 */ 782 m_assembler.sll(addrTempRegister, address.index, address.scale); 783 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 784 m_assembler.lw(dest, addrTempRegister, address.offset); 785 } else { 786 /* 787 sll addrTemp, address.index, address.scale 788 addu addrTemp, addrTemp, address.base 789 lui immTemp, (address.offset + 0x8000) >> 16 790 addu addrTemp, addrTemp, immTemp 791 lw dest, (address.offset & 0xffff)(at) 792 */ 793 m_assembler.sll(addrTempRegister, address.index, address.scale); 794 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 795 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 796 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 797 m_assembler.lw(dest, addrTempRegister, address.offset); 798 } 799 } 800 load16Unaligned(BaseIndex address,RegisterID dest)801 void load16Unaligned(BaseIndex address, RegisterID dest) 802 { 803 if (address.offset >= -32768 && address.offset <= 32766 && !m_fixedWidth) { 804 /* 805 sll addrtemp, address.index, address.scale 806 addu addrtemp, addrtemp, address.base 807 lbu immTemp, address.offset+x(addrtemp) (x=0 for LE, x=1 for BE) 808 lbu dest, address.offset+x(addrtemp) (x=1 for LE, x=0 for BE) 809 sll dest, dest, 8 810 or dest, dest, immTemp 811 */ 812 m_assembler.sll(addrTempRegister, address.index, address.scale); 813 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 814 #if CPU(BIG_ENDIAN) 815 m_assembler.lbu(immTempRegister, addrTempRegister, address.offset + 1); 816 m_assembler.lbu(dest, addrTempRegister, address.offset); 817 #else 818 m_assembler.lbu(immTempRegister, addrTempRegister, address.offset); 819 m_assembler.lbu(dest, addrTempRegister, address.offset + 1); 820 #endif 821 m_assembler.sll(dest, dest, 8); 822 m_assembler.orInsn(dest, dest, immTempRegister); 823 } else { 824 /* 825 sll addrTemp, address.index, address.scale 826 addu addrTemp, addrTemp, address.base 827 lui immTemp, address.offset >> 16 828 ori immTemp, immTemp, address.offset & 0xffff 829 addu addrTemp, addrTemp, immTemp 830 lbu immTemp, x(addrtemp) (x=0 for LE, x=1 for BE) 831 lbu dest, x(addrtemp) (x=1 for LE, x=0 for BE) 832 sll dest, dest, 8 833 or dest, dest, immTemp 834 */ 835 m_assembler.sll(addrTempRegister, address.index, address.scale); 836 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 837 m_assembler.lui(immTempRegister, address.offset >> 16); 838 m_assembler.ori(immTempRegister, immTempRegister, address.offset); 839 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 840 #if CPU(BIG_ENDIAN) 841 m_assembler.lbu(immTempRegister, addrTempRegister, 1); 842 m_assembler.lbu(dest, addrTempRegister, 0); 843 #else 844 m_assembler.lbu(immTempRegister, addrTempRegister, 0); 845 m_assembler.lbu(dest, addrTempRegister, 1); 846 #endif 847 m_assembler.sll(dest, dest, 8); 848 m_assembler.orInsn(dest, dest, immTempRegister); 849 } 850 } 851 load32WithUnalignedHalfWords(BaseIndex address,RegisterID dest)852 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest) 853 { 854 if (address.offset >= -32768 && address.offset <= 32764 855 && !m_fixedWidth) { 856 /* 857 sll addrTemp, address.index, address.scale 858 addu addrTemp, addrTemp, address.base 859 (Big-Endian) 860 lwl dest, address.offset(addrTemp) 861 lwr dest, address.offset+3(addrTemp) 862 (Little-Endian) 863 lwl dest, address.offset+3(addrTemp) 864 lwr dest, address.offset(addrTemp) 865 */ 866 m_assembler.sll(addrTempRegister, address.index, address.scale); 867 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 868 #if CPU(BIG_ENDIAN) 869 m_assembler.lwl(dest, addrTempRegister, address.offset); 870 m_assembler.lwr(dest, addrTempRegister, address.offset + 3); 871 #else 872 m_assembler.lwl(dest, addrTempRegister, address.offset + 3); 873 m_assembler.lwr(dest, addrTempRegister, address.offset); 874 875 #endif 876 } else { 877 /* 878 sll addrTemp, address.index, address.scale 879 addu addrTemp, addrTemp, address.base 880 lui immTemp, address.offset >> 16 881 ori immTemp, immTemp, address.offset & 0xffff 882 addu addrTemp, addrTemp, immTemp 883 (Big-Endian) 884 lw dest, 0(at) 885 lw dest, 3(at) 886 (Little-Endian) 887 lw dest, 3(at) 888 lw dest, 0(at) 889 */ 890 m_assembler.sll(addrTempRegister, address.index, address.scale); 891 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 892 m_assembler.lui(immTempRegister, address.offset >> 16); 893 m_assembler.ori(immTempRegister, immTempRegister, address.offset); 894 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 895 #if CPU(BIG_ENDIAN) 896 m_assembler.lwl(dest, addrTempRegister, 0); 897 m_assembler.lwr(dest, addrTempRegister, 3); 898 #else 899 m_assembler.lwl(dest, addrTempRegister, 3); 900 m_assembler.lwr(dest, addrTempRegister, 0); 901 #endif 902 } 903 } 904 load32(const void * address,RegisterID dest)905 void load32(const void* address, RegisterID dest) 906 { 907 /* 908 li addrTemp, address 909 lw dest, 0(addrTemp) 910 */ 911 move(TrustedImmPtr(address), addrTempRegister); 912 m_assembler.lw(dest, addrTempRegister, 0); 913 } 914 load32WithAddressOffsetPatch(Address address,RegisterID dest)915 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest) 916 { 917 m_fixedWidth = true; 918 /* 919 lui addrTemp, address.offset >> 16 920 ori addrTemp, addrTemp, address.offset & 0xffff 921 addu addrTemp, addrTemp, address.base 922 lw dest, 0(addrTemp) 923 */ 924 DataLabel32 dataLabel(this); 925 move(TrustedImm32(address.offset), addrTempRegister); 926 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 927 m_assembler.lw(dest, addrTempRegister, 0); 928 m_fixedWidth = false; 929 return dataLabel; 930 } 931 load32WithCompactAddressOffsetPatch(Address address,RegisterID dest)932 DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest) 933 { 934 DataLabelCompact dataLabel(this); 935 load32WithAddressOffsetPatch(address, dest); 936 return dataLabel; 937 } 938 939 /* Need to use zero-extened load half-word for load16. */ load16(ImplicitAddress address,RegisterID dest)940 void load16(ImplicitAddress address, RegisterID dest) 941 { 942 if (address.offset >= -32768 && address.offset <= 32767 943 && !m_fixedWidth) 944 m_assembler.lhu(dest, address.base, address.offset); 945 else { 946 /* 947 lui addrTemp, (offset + 0x8000) >> 16 948 addu addrTemp, addrTemp, base 949 lhu dest, (offset & 0xffff)(addrTemp) 950 */ 951 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 952 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 953 m_assembler.lhu(dest, addrTempRegister, address.offset); 954 } 955 } 956 957 /* Need to use zero-extened load half-word for load16. */ load16(BaseIndex address,RegisterID dest)958 void load16(BaseIndex address, RegisterID dest) 959 { 960 if (address.offset >= -32768 && address.offset <= 32767 961 && !m_fixedWidth) { 962 /* 963 sll addrTemp, address.index, address.scale 964 addu addrTemp, addrTemp, address.base 965 lhu dest, address.offset(addrTemp) 966 */ 967 m_assembler.sll(addrTempRegister, address.index, address.scale); 968 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 969 m_assembler.lhu(dest, addrTempRegister, address.offset); 970 } else { 971 /* 972 sll addrTemp, address.index, address.scale 973 addu addrTemp, addrTemp, address.base 974 lui immTemp, (address.offset + 0x8000) >> 16 975 addu addrTemp, addrTemp, immTemp 976 lhu dest, (address.offset & 0xffff)(addrTemp) 977 */ 978 m_assembler.sll(addrTempRegister, address.index, address.scale); 979 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 980 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 981 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 982 m_assembler.lhu(dest, addrTempRegister, address.offset); 983 } 984 } 985 load16Signed(BaseIndex address,RegisterID dest)986 void load16Signed(BaseIndex address, RegisterID dest) 987 { 988 if (address.offset >= -32768 && address.offset <= 32767 989 && !m_fixedWidth) { 990 /* 991 sll addrTemp, address.index, address.scale 992 addu addrTemp, addrTemp, address.base 993 lh dest, address.offset(addrTemp) 994 */ 995 m_assembler.sll(addrTempRegister, address.index, address.scale); 996 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 997 m_assembler.lh(dest, addrTempRegister, address.offset); 998 } else { 999 /* 1000 sll addrTemp, address.index, address.scale 1001 addu addrTemp, addrTemp, address.base 1002 lui immTemp, (address.offset + 0x8000) >> 16 1003 addu addrTemp, addrTemp, immTemp 1004 lh dest, (address.offset & 0xffff)(addrTemp) 1005 */ 1006 m_assembler.sll(addrTempRegister, address.index, address.scale); 1007 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1008 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 1009 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 1010 m_assembler.lh(dest, addrTempRegister, address.offset); 1011 } 1012 } 1013 store32WithAddressOffsetPatch(RegisterID src,Address address)1014 DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address) 1015 { 1016 m_fixedWidth = true; 1017 /* 1018 lui addrTemp, address.offset >> 16 1019 ori addrTemp, addrTemp, address.offset & 0xffff 1020 addu addrTemp, addrTemp, address.base 1021 sw src, 0(addrTemp) 1022 */ 1023 DataLabel32 dataLabel(this); 1024 move(TrustedImm32(address.offset), addrTempRegister); 1025 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1026 m_assembler.sw(src, addrTempRegister, 0); 1027 m_fixedWidth = false; 1028 return dataLabel; 1029 } 1030 store8(RegisterID src,BaseIndex address)1031 void store8(RegisterID src, BaseIndex address) 1032 { 1033 if (address.offset >= -32768 && address.offset <= 32767 1034 && !m_fixedWidth) { 1035 /* 1036 sll addrTemp, address.index, address.scale 1037 addu addrTemp, addrTemp, address.base 1038 sb src, address.offset(addrTemp) 1039 */ 1040 m_assembler.sll(addrTempRegister, address.index, address.scale); 1041 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1042 m_assembler.sb(src, addrTempRegister, address.offset); 1043 } else { 1044 /* 1045 sll addrTemp, address.index, address.scale 1046 addu addrTemp, addrTemp, address.base 1047 lui immTemp, (address.offset + 0x8000) >> 16 1048 addu addrTemp, addrTemp, immTemp 1049 sb src, (address.offset & 0xffff)(at) 1050 */ 1051 m_assembler.sll(addrTempRegister, address.index, address.scale); 1052 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1053 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 1054 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 1055 m_assembler.sb(src, addrTempRegister, address.offset); 1056 } 1057 } 1058 store8(TrustedImm32 imm,void * address)1059 void store8(TrustedImm32 imm, void* address) 1060 { 1061 /* 1062 li immTemp, imm 1063 li addrTemp, address 1064 sb src, 0(addrTemp) 1065 */ 1066 if (!imm.m_value && !m_fixedWidth) { 1067 move(TrustedImmPtr(address), addrTempRegister); 1068 m_assembler.sb(MIPSRegisters::zero, addrTempRegister, 0); 1069 } else { 1070 move(imm, immTempRegister); 1071 move(TrustedImmPtr(address), addrTempRegister); 1072 m_assembler.sb(immTempRegister, addrTempRegister, 0); 1073 } 1074 } 1075 store16(RegisterID src,BaseIndex address)1076 void store16(RegisterID src, BaseIndex address) 1077 { 1078 if (address.offset >= -32768 && address.offset <= 32767 1079 && !m_fixedWidth) { 1080 /* 1081 sll addrTemp, address.index, address.scale 1082 addu addrTemp, addrTemp, address.base 1083 sh src, address.offset(addrTemp) 1084 */ 1085 m_assembler.sll(addrTempRegister, address.index, address.scale); 1086 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1087 m_assembler.sh(src, addrTempRegister, address.offset); 1088 } else { 1089 /* 1090 sll addrTemp, address.index, address.scale 1091 addu addrTemp, addrTemp, address.base 1092 lui immTemp, (address.offset + 0x8000) >> 16 1093 addu addrTemp, addrTemp, immTemp 1094 sh src, (address.offset & 0xffff)(at) 1095 */ 1096 m_assembler.sll(addrTempRegister, address.index, address.scale); 1097 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1098 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 1099 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 1100 m_assembler.sh(src, addrTempRegister, address.offset); 1101 } 1102 } 1103 store32(RegisterID src,ImplicitAddress address)1104 void store32(RegisterID src, ImplicitAddress address) 1105 { 1106 if (address.offset >= -32768 && address.offset <= 32767 1107 && !m_fixedWidth) 1108 m_assembler.sw(src, address.base, address.offset); 1109 else { 1110 /* 1111 lui addrTemp, (offset + 0x8000) >> 16 1112 addu addrTemp, addrTemp, base 1113 sw src, (offset & 0xffff)(addrTemp) 1114 */ 1115 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 1116 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1117 m_assembler.sw(src, addrTempRegister, address.offset); 1118 } 1119 } 1120 store32(RegisterID src,BaseIndex address)1121 void store32(RegisterID src, BaseIndex address) 1122 { 1123 if (address.offset >= -32768 && address.offset <= 32767 1124 && !m_fixedWidth) { 1125 /* 1126 sll addrTemp, address.index, address.scale 1127 addu addrTemp, addrTemp, address.base 1128 sw src, address.offset(addrTemp) 1129 */ 1130 m_assembler.sll(addrTempRegister, address.index, address.scale); 1131 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1132 m_assembler.sw(src, addrTempRegister, address.offset); 1133 } else { 1134 /* 1135 sll addrTemp, address.index, address.scale 1136 addu addrTemp, addrTemp, address.base 1137 lui immTemp, (address.offset + 0x8000) >> 16 1138 addu addrTemp, addrTemp, immTemp 1139 sw src, (address.offset & 0xffff)(at) 1140 */ 1141 m_assembler.sll(addrTempRegister, address.index, address.scale); 1142 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1143 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 1144 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 1145 m_assembler.sw(src, addrTempRegister, address.offset); 1146 } 1147 } 1148 store32(TrustedImm32 imm,ImplicitAddress address)1149 void store32(TrustedImm32 imm, ImplicitAddress address) 1150 { 1151 if (address.offset >= -32768 && address.offset <= 32767 1152 && !m_fixedWidth) { 1153 if (!imm.m_value) 1154 m_assembler.sw(MIPSRegisters::zero, address.base, address.offset); 1155 else { 1156 move(imm, immTempRegister); 1157 m_assembler.sw(immTempRegister, address.base, address.offset); 1158 } 1159 } else { 1160 /* 1161 lui addrTemp, (offset + 0x8000) >> 16 1162 addu addrTemp, addrTemp, base 1163 sw immTemp, (offset & 0xffff)(addrTemp) 1164 */ 1165 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 1166 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1167 if (!imm.m_value && !m_fixedWidth) 1168 m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset); 1169 else { 1170 move(imm, immTempRegister); 1171 m_assembler.sw(immTempRegister, addrTempRegister, address.offset); 1172 } 1173 } 1174 } 1175 store32(TrustedImm32 imm,BaseIndex address)1176 void store32(TrustedImm32 imm, BaseIndex address) 1177 { 1178 if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) { 1179 /* 1180 sll addrTemp, address.index, address.scale 1181 addu addrTemp, addrTemp, address.base 1182 sw src, address.offset(addrTemp) 1183 */ 1184 m_assembler.sll(addrTempRegister, address.index, address.scale); 1185 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1186 if (!imm.m_value) 1187 m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset); 1188 else { 1189 move(imm, immTempRegister); 1190 m_assembler.sw(immTempRegister, addrTempRegister, address.offset); 1191 } 1192 } else { 1193 /* 1194 sll addrTemp, address.index, address.scale 1195 addu addrTemp, addrTemp, address.base 1196 lui immTemp, (address.offset + 0x8000) >> 16 1197 addu addrTemp, addrTemp, immTemp 1198 sw src, (address.offset & 0xffff)(at) 1199 */ 1200 m_assembler.sll(addrTempRegister, address.index, address.scale); 1201 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1202 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 1203 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 1204 if (!imm.m_value && !m_fixedWidth) 1205 m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset); 1206 else { 1207 move(imm, immTempRegister); 1208 m_assembler.sw(immTempRegister, addrTempRegister, address.offset); 1209 } 1210 } 1211 } 1212 1213 store32(RegisterID src,const void * address)1214 void store32(RegisterID src, const void* address) 1215 { 1216 /* 1217 li addrTemp, address 1218 sw src, 0(addrTemp) 1219 */ 1220 move(TrustedImmPtr(address), addrTempRegister); 1221 m_assembler.sw(src, addrTempRegister, 0); 1222 } 1223 store32(TrustedImm32 imm,const void * address)1224 void store32(TrustedImm32 imm, const void* address) 1225 { 1226 /* 1227 li immTemp, imm 1228 li addrTemp, address 1229 sw src, 0(addrTemp) 1230 */ 1231 if (!imm.m_value && !m_fixedWidth) { 1232 move(TrustedImmPtr(address), addrTempRegister); 1233 m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0); 1234 } else { 1235 move(imm, immTempRegister); 1236 move(TrustedImmPtr(address), addrTempRegister); 1237 m_assembler.sw(immTempRegister, addrTempRegister, 0); 1238 } 1239 } 1240 1241 // Floating-point operations: 1242 supportsFloatingPoint()1243 static bool supportsFloatingPoint() 1244 { 1245 #if WTF_MIPS_DOUBLE_FLOAT 1246 return true; 1247 #else 1248 return false; 1249 #endif 1250 } 1251 supportsFloatingPointTruncate()1252 static bool supportsFloatingPointTruncate() 1253 { 1254 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2) 1255 return true; 1256 #else 1257 return false; 1258 #endif 1259 } 1260 supportsFloatingPointSqrt()1261 static bool supportsFloatingPointSqrt() 1262 { 1263 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2) 1264 return true; 1265 #else 1266 return false; 1267 #endif 1268 } supportsFloatingPointAbs()1269 static bool supportsFloatingPointAbs() { return false; } 1270 1271 // Stack manipulation operations: 1272 // 1273 // The ABI is assumed to provide a stack abstraction to memory, 1274 // containing machine word sized units of data. Push and pop 1275 // operations add and remove a single register sized unit of data 1276 // to or from the stack. Peek and poke operations read or write 1277 // values on the stack, without moving the current stack position. 1278 pop(RegisterID dest)1279 void pop(RegisterID dest) 1280 { 1281 m_assembler.lw(dest, MIPSRegisters::sp, 0); 1282 m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, 4); 1283 } 1284 push(RegisterID src)1285 void push(RegisterID src) 1286 { 1287 m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, -4); 1288 m_assembler.sw(src, MIPSRegisters::sp, 0); 1289 } 1290 push(Address address)1291 void push(Address address) 1292 { 1293 load32(address, dataTempRegister); 1294 push(dataTempRegister); 1295 } 1296 push(TrustedImm32 imm)1297 void push(TrustedImm32 imm) 1298 { 1299 move(imm, immTempRegister); 1300 push(immTempRegister); 1301 } 1302 1303 // Register move operations: 1304 // 1305 // Move values in registers. 1306 move(TrustedImm32 imm,RegisterID dest)1307 void move(TrustedImm32 imm, RegisterID dest) 1308 { 1309 if (!imm.m_value && !m_fixedWidth) 1310 move(MIPSRegisters::zero, dest); 1311 else if (m_fixedWidth) { 1312 m_assembler.lui(dest, imm.m_value >> 16); 1313 m_assembler.ori(dest, dest, imm.m_value); 1314 } else 1315 m_assembler.li(dest, imm.m_value); 1316 } 1317 move(RegisterID src,RegisterID dest)1318 void move(RegisterID src, RegisterID dest) 1319 { 1320 if (src != dest || m_fixedWidth) 1321 m_assembler.move(dest, src); 1322 } 1323 move(TrustedImmPtr imm,RegisterID dest)1324 void move(TrustedImmPtr imm, RegisterID dest) 1325 { 1326 move(TrustedImm32(imm), dest); 1327 } 1328 swap(RegisterID reg1,RegisterID reg2)1329 void swap(RegisterID reg1, RegisterID reg2) 1330 { 1331 move(reg1, immTempRegister); 1332 move(reg2, reg1); 1333 move(immTempRegister, reg2); 1334 } 1335 signExtend32ToPtr(RegisterID src,RegisterID dest)1336 void signExtend32ToPtr(RegisterID src, RegisterID dest) 1337 { 1338 if (src != dest || m_fixedWidth) 1339 move(src, dest); 1340 } 1341 zeroExtend32ToPtr(RegisterID src,RegisterID dest)1342 void zeroExtend32ToPtr(RegisterID src, RegisterID dest) 1343 { 1344 if (src != dest || m_fixedWidth) 1345 move(src, dest); 1346 } 1347 1348 // Forwards / external control flow operations: 1349 // 1350 // This set of jump and conditional branch operations return a Jump 1351 // object which may linked at a later point, allow forwards jump, 1352 // or jumps that will require external linkage (after the code has been 1353 // relocated). 1354 // 1355 // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge 1356 // respecitvely, for unsigned comparisons the names b, a, be, and ae are 1357 // used (representing the names 'below' and 'above'). 1358 // 1359 // Operands to the comparision are provided in the expected order, e.g. 1360 // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when 1361 // treated as a signed 32bit value, is less than or equal to 5. 1362 // 1363 // jz and jnz test whether the first operand is equal to zero, and take 1364 // an optional second operand of a mask under which to perform the test. 1365 branch8(RelationalCondition cond,Address left,TrustedImm32 right)1366 Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right) 1367 { 1368 // Make sure the immediate value is unsigned 8 bits. 1369 ASSERT(!(right.m_value & 0xFFFFFF00)); 1370 load8(left, dataTempRegister); 1371 move(right, immTempRegister); 1372 return branch32(cond, dataTempRegister, immTempRegister); 1373 } 1374 compare8(RelationalCondition cond,Address left,TrustedImm32 right,RegisterID dest)1375 void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) 1376 { 1377 // Make sure the immediate value is unsigned 8 bits. 1378 ASSERT(!(right.m_value & 0xFFFFFF00)); 1379 load8(left, dataTempRegister); 1380 move(right, immTempRegister); 1381 compare32(cond, dataTempRegister, immTempRegister, dest); 1382 } 1383 branch8(RelationalCondition cond,BaseIndex left,TrustedImm32 right)1384 Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right) 1385 { 1386 ASSERT(!(right.m_value & 0xFFFFFF00)); 1387 load8(left, dataTempRegister); 1388 // Be careful that the previous load8() uses immTempRegister. 1389 // So, we need to put move() after load8(). 1390 move(right, immTempRegister); 1391 return branch32(cond, dataTempRegister, immTempRegister); 1392 } 1393 branch32(RelationalCondition cond,RegisterID left,RegisterID right)1394 Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right) 1395 { 1396 if (cond == Equal) 1397 return branchEqual(left, right); 1398 if (cond == NotEqual) 1399 return branchNotEqual(left, right); 1400 if (cond == Above) { 1401 m_assembler.sltu(cmpTempRegister, right, left); 1402 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1403 } 1404 if (cond == AboveOrEqual) { 1405 m_assembler.sltu(cmpTempRegister, left, right); 1406 return branchEqual(cmpTempRegister, MIPSRegisters::zero); 1407 } 1408 if (cond == Below) { 1409 m_assembler.sltu(cmpTempRegister, left, right); 1410 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1411 } 1412 if (cond == BelowOrEqual) { 1413 m_assembler.sltu(cmpTempRegister, right, left); 1414 return branchEqual(cmpTempRegister, MIPSRegisters::zero); 1415 } 1416 if (cond == GreaterThan) { 1417 m_assembler.slt(cmpTempRegister, right, left); 1418 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1419 } 1420 if (cond == GreaterThanOrEqual) { 1421 m_assembler.slt(cmpTempRegister, left, right); 1422 return branchEqual(cmpTempRegister, MIPSRegisters::zero); 1423 } 1424 if (cond == LessThan) { 1425 m_assembler.slt(cmpTempRegister, left, right); 1426 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1427 } 1428 if (cond == LessThanOrEqual) { 1429 m_assembler.slt(cmpTempRegister, right, left); 1430 return branchEqual(cmpTempRegister, MIPSRegisters::zero); 1431 } 1432 ASSERT(0); 1433 1434 return Jump(); 1435 } 1436 branch32(RelationalCondition cond,RegisterID left,TrustedImm32 right)1437 Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right) 1438 { 1439 move(right, immTempRegister); 1440 return branch32(cond, left, immTempRegister); 1441 } 1442 branch32(RelationalCondition cond,RegisterID left,Address right)1443 Jump branch32(RelationalCondition cond, RegisterID left, Address right) 1444 { 1445 load32(right, dataTempRegister); 1446 return branch32(cond, left, dataTempRegister); 1447 } 1448 branch32(RelationalCondition cond,Address left,RegisterID right)1449 Jump branch32(RelationalCondition cond, Address left, RegisterID right) 1450 { 1451 load32(left, dataTempRegister); 1452 return branch32(cond, dataTempRegister, right); 1453 } 1454 branch32(RelationalCondition cond,Address left,TrustedImm32 right)1455 Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right) 1456 { 1457 load32(left, dataTempRegister); 1458 move(right, immTempRegister); 1459 return branch32(cond, dataTempRegister, immTempRegister); 1460 } 1461 branch32(RelationalCondition cond,BaseIndex left,TrustedImm32 right)1462 Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right) 1463 { 1464 load32(left, dataTempRegister); 1465 // Be careful that the previous load32() uses immTempRegister. 1466 // So, we need to put move() after load32(). 1467 move(right, immTempRegister); 1468 return branch32(cond, dataTempRegister, immTempRegister); 1469 } 1470 branch32WithUnalignedHalfWords(RelationalCondition cond,BaseIndex left,TrustedImm32 right)1471 Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right) 1472 { 1473 load32WithUnalignedHalfWords(left, dataTempRegister); 1474 // Be careful that the previous load32WithUnalignedHalfWords() 1475 // uses immTempRegister. 1476 // So, we need to put move() after load32WithUnalignedHalfWords(). 1477 move(right, immTempRegister); 1478 return branch32(cond, dataTempRegister, immTempRegister); 1479 } 1480 branch32(RelationalCondition cond,AbsoluteAddress left,RegisterID right)1481 Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right) 1482 { 1483 load32(left.m_ptr, dataTempRegister); 1484 return branch32(cond, dataTempRegister, right); 1485 } 1486 branch32(RelationalCondition cond,AbsoluteAddress left,TrustedImm32 right)1487 Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right) 1488 { 1489 load32(left.m_ptr, dataTempRegister); 1490 move(right, immTempRegister); 1491 return branch32(cond, dataTempRegister, immTempRegister); 1492 } 1493 branchTest32(ResultCondition cond,RegisterID reg,RegisterID mask)1494 Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask) 1495 { 1496 ASSERT((cond == Zero) || (cond == NonZero)); 1497 m_assembler.andInsn(cmpTempRegister, reg, mask); 1498 if (cond == Zero) 1499 return branchEqual(cmpTempRegister, MIPSRegisters::zero); 1500 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1501 } 1502 1503 Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) 1504 { 1505 ASSERT((cond == Zero) || (cond == NonZero)); 1506 if (mask.m_value == -1 && !m_fixedWidth) { 1507 if (cond == Zero) 1508 return branchEqual(reg, MIPSRegisters::zero); 1509 return branchNotEqual(reg, MIPSRegisters::zero); 1510 } 1511 move(mask, immTempRegister); 1512 return branchTest32(cond, reg, immTempRegister); 1513 } 1514 1515 Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) 1516 { 1517 load32(address, dataTempRegister); 1518 return branchTest32(cond, dataTempRegister, mask); 1519 } 1520 1521 Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) 1522 { 1523 load32(address, dataTempRegister); 1524 return branchTest32(cond, dataTempRegister, mask); 1525 } 1526 1527 Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) 1528 { 1529 load8(address, dataTempRegister); 1530 return branchTest32(cond, dataTempRegister, mask); 1531 } 1532 1533 Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) 1534 { 1535 move(TrustedImmPtr(address.m_ptr), dataTempRegister); 1536 load8(Address(dataTempRegister), dataTempRegister); 1537 return branchTest32(cond, dataTempRegister, mask); 1538 } 1539 jump()1540 Jump jump() 1541 { 1542 return branchEqual(MIPSRegisters::zero, MIPSRegisters::zero); 1543 } 1544 jump(RegisterID target)1545 void jump(RegisterID target) 1546 { 1547 move(target, MIPSRegisters::t9); 1548 m_assembler.jr(MIPSRegisters::t9); 1549 m_assembler.nop(); 1550 } 1551 jump(Address address)1552 void jump(Address address) 1553 { 1554 m_fixedWidth = true; 1555 load32(address, MIPSRegisters::t9); 1556 m_assembler.jr(MIPSRegisters::t9); 1557 m_assembler.nop(); 1558 m_fixedWidth = false; 1559 } 1560 jump(AbsoluteAddress address)1561 void jump(AbsoluteAddress address) 1562 { 1563 m_fixedWidth = true; 1564 load32(address.m_ptr, MIPSRegisters::t9); 1565 m_assembler.jr(MIPSRegisters::t9); 1566 m_assembler.nop(); 1567 m_fixedWidth = false; 1568 } 1569 moveDoubleToInts(FPRegisterID src,RegisterID dest1,RegisterID dest2)1570 void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2) 1571 { 1572 m_assembler.vmov(dest1, dest2, src); 1573 } 1574 moveIntsToDouble(RegisterID src1,RegisterID src2,FPRegisterID dest,FPRegisterID scratch)1575 void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID scratch) 1576 { 1577 UNUSED_PARAM(scratch); 1578 m_assembler.vmov(dest, src1, src2); 1579 } 1580 1581 // Arithmetic control flow operations: 1582 // 1583 // This set of conditional branch operations branch based 1584 // on the result of an arithmetic operation. The operation 1585 // is performed as normal, storing the result. 1586 // 1587 // * jz operations branch if the result is zero. 1588 // * jo operations branch if the (signed) arithmetic 1589 // operation caused an overflow to occur. 1590 branchAdd32(ResultCondition cond,RegisterID src,RegisterID dest)1591 Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest) 1592 { 1593 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1594 if (cond == Overflow) { 1595 /* 1596 move dest, dataTemp 1597 xor cmpTemp, dataTemp, src 1598 bltz cmpTemp, No_overflow # diff sign bit -> no overflow 1599 addu dest, dataTemp, src 1600 xor cmpTemp, dest, dataTemp 1601 bgez cmpTemp, No_overflow # same sign big -> no overflow 1602 nop 1603 b Overflow 1604 nop 1605 nop 1606 nop 1607 nop 1608 nop 1609 No_overflow: 1610 */ 1611 move(dest, dataTempRegister); 1612 m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src); 1613 m_assembler.bltz(cmpTempRegister, 10); 1614 m_assembler.addu(dest, dataTempRegister, src); 1615 m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister); 1616 m_assembler.bgez(cmpTempRegister, 7); 1617 m_assembler.nop(); 1618 return jump(); 1619 } 1620 if (cond == Signed) { 1621 add32(src, dest); 1622 // Check if dest is negative. 1623 m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); 1624 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1625 } 1626 if (cond == Zero) { 1627 add32(src, dest); 1628 return branchEqual(dest, MIPSRegisters::zero); 1629 } 1630 if (cond == NonZero) { 1631 add32(src, dest); 1632 return branchNotEqual(dest, MIPSRegisters::zero); 1633 } 1634 ASSERT(0); 1635 return Jump(); 1636 } 1637 branchAdd32(ResultCondition cond,RegisterID op1,RegisterID op2,RegisterID dest)1638 Jump branchAdd32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest) 1639 { 1640 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1641 if (cond == Overflow) { 1642 /* 1643 move dataTemp, op1 1644 xor cmpTemp, dataTemp, op2 1645 bltz cmpTemp, No_overflow # diff sign bit -> no overflow 1646 addu dest, dataTemp, op2 1647 xor cmpTemp, dest, dataTemp 1648 bgez cmpTemp, No_overflow # same sign big -> no overflow 1649 nop 1650 b Overflow 1651 nop 1652 nop 1653 nop 1654 nop 1655 nop 1656 No_overflow: 1657 */ 1658 move(op1, dataTempRegister); 1659 m_assembler.xorInsn(cmpTempRegister, dataTempRegister, op2); 1660 m_assembler.bltz(cmpTempRegister, 10); 1661 m_assembler.addu(dest, dataTempRegister, op2); 1662 m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister); 1663 m_assembler.bgez(cmpTempRegister, 7); 1664 m_assembler.nop(); 1665 return jump(); 1666 } 1667 if (cond == Signed) { 1668 add32(op1, op2, dest); 1669 // Check if dest is negative. 1670 m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); 1671 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1672 } 1673 if (cond == Zero) { 1674 add32(op1, op2, dest); 1675 return branchEqual(dest, MIPSRegisters::zero); 1676 } 1677 if (cond == NonZero) { 1678 add32(op1, op2, dest); 1679 return branchNotEqual(dest, MIPSRegisters::zero); 1680 } 1681 ASSERT(0); 1682 return Jump(); 1683 } 1684 branchAdd32(ResultCondition cond,TrustedImm32 imm,RegisterID dest)1685 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) 1686 { 1687 move(imm, immTempRegister); 1688 return branchAdd32(cond, immTempRegister, dest); 1689 } 1690 branchAdd32(ResultCondition cond,RegisterID src,TrustedImm32 imm,RegisterID dest)1691 Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) 1692 { 1693 move(imm, immTempRegister); 1694 move(src, dest); 1695 return branchAdd32(cond, immTempRegister, dest); 1696 } 1697 branchAdd32(ResultCondition cond,TrustedImm32 imm,AbsoluteAddress dest)1698 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest) 1699 { 1700 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1701 if (cond == Overflow) { 1702 /* 1703 move dataTemp, dest 1704 xori cmpTemp, dataTemp, imm 1705 bltz cmpTemp, No_overflow # diff sign bit -> no overflow 1706 addiu dataTemp, dataTemp, imm 1707 move dest, dataTemp 1708 xori cmpTemp, dataTemp, imm 1709 bgez cmpTemp, No_overflow # same sign big -> no overflow 1710 nop 1711 b Overflow 1712 nop 1713 nop 1714 nop 1715 nop 1716 nop 1717 No_overflow: 1718 */ 1719 if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) { 1720 load32(dest.m_ptr, dataTempRegister); 1721 m_assembler.xori(cmpTempRegister, dataTempRegister, imm.m_value); 1722 m_assembler.bltz(cmpTempRegister, 10); 1723 m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value); 1724 store32(dataTempRegister, dest.m_ptr); 1725 m_assembler.xori(cmpTempRegister, dataTempRegister, imm.m_value); 1726 m_assembler.bgez(cmpTempRegister, 7); 1727 m_assembler.nop(); 1728 } else { 1729 load32(dest.m_ptr, dataTempRegister); 1730 move(imm, immTempRegister); 1731 m_assembler.xorInsn(cmpTempRegister, dataTempRegister, immTempRegister); 1732 m_assembler.bltz(cmpTempRegister, 10); 1733 m_assembler.addiu(dataTempRegister, dataTempRegister, immTempRegister); 1734 store32(dataTempRegister, dest.m_ptr); 1735 m_assembler.xori(cmpTempRegister, dataTempRegister, immTempRegister); 1736 m_assembler.bgez(cmpTempRegister, 7); 1737 m_assembler.nop(); 1738 } 1739 return jump(); 1740 } 1741 move(imm, immTempRegister); 1742 load32(dest.m_ptr, dataTempRegister); 1743 add32(immTempRegister, dataTempRegister); 1744 store32(dataTempRegister, dest.m_ptr); 1745 if (cond == Signed) { 1746 // Check if dest is negative. 1747 m_assembler.slt(cmpTempRegister, dataTempRegister, MIPSRegisters::zero); 1748 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1749 } 1750 if (cond == Zero) 1751 return branchEqual(dataTempRegister, MIPSRegisters::zero); 1752 if (cond == NonZero) 1753 return branchNotEqual(dataTempRegister, MIPSRegisters::zero); 1754 ASSERT(0); 1755 return Jump(); 1756 } 1757 branchMul32(ResultCondition cond,RegisterID src1,RegisterID src2,RegisterID dest)1758 Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest) 1759 { 1760 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1761 if (cond == Overflow) { 1762 /* 1763 mult src, dest 1764 mfhi dataTemp 1765 mflo dest 1766 sra addrTemp, dest, 31 1767 beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow 1768 nop 1769 b Overflow 1770 nop 1771 nop 1772 nop 1773 nop 1774 nop 1775 No_overflow: 1776 */ 1777 m_assembler.mult(src1, src2); 1778 m_assembler.mfhi(dataTempRegister); 1779 m_assembler.mflo(dest); 1780 m_assembler.sra(addrTempRegister, dest, 31); 1781 m_assembler.beq(dataTempRegister, addrTempRegister, 7); 1782 m_assembler.nop(); 1783 return jump(); 1784 } 1785 if (cond == Signed) { 1786 mul32(src1, src2, dest); 1787 // Check if dest is negative. 1788 m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); 1789 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1790 } 1791 if (cond == Zero) { 1792 mul32(src1, src2, dest); 1793 return branchEqual(dest, MIPSRegisters::zero); 1794 } 1795 if (cond == NonZero) { 1796 mul32(src1, src2, dest); 1797 return branchNotEqual(dest, MIPSRegisters::zero); 1798 } 1799 ASSERT(0); 1800 return Jump(); 1801 } 1802 branchMul32(ResultCondition cond,RegisterID src,RegisterID dest)1803 Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest) 1804 { 1805 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1806 if (cond == Overflow) { 1807 /* 1808 mult src, dest 1809 mfhi dataTemp 1810 mflo dest 1811 sra addrTemp, dest, 31 1812 beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow 1813 nop 1814 b Overflow 1815 nop 1816 nop 1817 nop 1818 nop 1819 nop 1820 No_overflow: 1821 */ 1822 m_assembler.mult(src, dest); 1823 m_assembler.mfhi(dataTempRegister); 1824 m_assembler.mflo(dest); 1825 m_assembler.sra(addrTempRegister, dest, 31); 1826 m_assembler.beq(dataTempRegister, addrTempRegister, 7); 1827 m_assembler.nop(); 1828 return jump(); 1829 } 1830 if (cond == Signed) { 1831 mul32(src, dest); 1832 // Check if dest is negative. 1833 m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); 1834 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1835 } 1836 if (cond == Zero) { 1837 mul32(src, dest); 1838 return branchEqual(dest, MIPSRegisters::zero); 1839 } 1840 if (cond == NonZero) { 1841 mul32(src, dest); 1842 return branchNotEqual(dest, MIPSRegisters::zero); 1843 } 1844 ASSERT(0); 1845 return Jump(); 1846 } 1847 branchMul32(ResultCondition cond,TrustedImm32 imm,RegisterID src,RegisterID dest)1848 Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest) 1849 { 1850 move(imm, immTempRegister); 1851 return branchMul32(cond, immTempRegister, src, dest); 1852 } 1853 branchSub32(ResultCondition cond,RegisterID src,RegisterID dest)1854 Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest) 1855 { 1856 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1857 if (cond == Overflow) { 1858 /* 1859 move dest, dataTemp 1860 xor cmpTemp, dataTemp, src 1861 bgez cmpTemp, No_overflow # same sign bit -> no overflow 1862 subu dest, dataTemp, src 1863 xor cmpTemp, dest, dataTemp 1864 bgez cmpTemp, No_overflow # same sign bit -> no overflow 1865 nop 1866 b Overflow 1867 nop 1868 nop 1869 nop 1870 nop 1871 nop 1872 No_overflow: 1873 */ 1874 move(dest, dataTempRegister); 1875 m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src); 1876 m_assembler.bgez(cmpTempRegister, 10); 1877 m_assembler.subu(dest, dataTempRegister, src); 1878 m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister); 1879 m_assembler.bgez(cmpTempRegister, 7); 1880 m_assembler.nop(); 1881 return jump(); 1882 } 1883 if (cond == Signed) { 1884 sub32(src, dest); 1885 // Check if dest is negative. 1886 m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); 1887 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1888 } 1889 if (cond == Zero) { 1890 sub32(src, dest); 1891 return branchEqual(dest, MIPSRegisters::zero); 1892 } 1893 if (cond == NonZero) { 1894 sub32(src, dest); 1895 return branchNotEqual(dest, MIPSRegisters::zero); 1896 } 1897 ASSERT(0); 1898 return Jump(); 1899 } 1900 branchSub32(ResultCondition cond,TrustedImm32 imm,RegisterID dest)1901 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) 1902 { 1903 move(imm, immTempRegister); 1904 return branchSub32(cond, immTempRegister, dest); 1905 } 1906 branchSub32(ResultCondition cond,RegisterID src,TrustedImm32 imm,RegisterID dest)1907 Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) 1908 { 1909 move(imm, immTempRegister); 1910 return branchSub32(cond, src, immTempRegister, dest); 1911 } 1912 branchSub32(ResultCondition cond,RegisterID op1,RegisterID op2,RegisterID dest)1913 Jump branchSub32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest) 1914 { 1915 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1916 if (cond == Overflow) { 1917 /* 1918 move dataTemp, op1 1919 xor cmpTemp, dataTemp, op2 1920 bgez cmpTemp, No_overflow # same sign bit -> no overflow 1921 subu dest, dataTemp, op2 1922 xor cmpTemp, dest, dataTemp 1923 bgez cmpTemp, No_overflow # same sign bit -> no overflow 1924 nop 1925 b Overflow 1926 nop 1927 nop 1928 nop 1929 nop 1930 nop 1931 No_overflow: 1932 */ 1933 move(op1, dataTempRegister); 1934 m_assembler.xorInsn(cmpTempRegister, dataTempRegister, op2); 1935 m_assembler.bgez(cmpTempRegister, 10); 1936 m_assembler.subu(dest, dataTempRegister, op2); 1937 m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister); 1938 m_assembler.bgez(cmpTempRegister, 7); 1939 m_assembler.nop(); 1940 return jump(); 1941 } 1942 if (cond == Signed) { 1943 sub32(op1, op2, dest); 1944 // Check if dest is negative. 1945 m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); 1946 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1947 } 1948 if (cond == Zero) { 1949 sub32(op1, op2, dest); 1950 return branchEqual(dest, MIPSRegisters::zero); 1951 } 1952 if (cond == NonZero) { 1953 sub32(op1, op2, dest); 1954 return branchNotEqual(dest, MIPSRegisters::zero); 1955 } 1956 ASSERT(0); 1957 return Jump(); 1958 } 1959 branchNeg32(ResultCondition cond,RegisterID srcDest)1960 Jump branchNeg32(ResultCondition cond, RegisterID srcDest) 1961 { 1962 m_assembler.li(dataTempRegister, -1); 1963 return branchMul32(cond, dataTempRegister, srcDest); 1964 } 1965 branchOr32(ResultCondition cond,RegisterID src,RegisterID dest)1966 Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest) 1967 { 1968 ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero)); 1969 if (cond == Signed) { 1970 or32(src, dest); 1971 // Check if dest is negative. 1972 m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); 1973 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1974 } 1975 if (cond == Zero) { 1976 or32(src, dest); 1977 return branchEqual(dest, MIPSRegisters::zero); 1978 } 1979 if (cond == NonZero) { 1980 or32(src, dest); 1981 return branchNotEqual(dest, MIPSRegisters::zero); 1982 } 1983 ASSERT(0); 1984 return Jump(); 1985 } 1986 1987 // Miscellaneous operations: 1988 breakpoint()1989 void breakpoint() 1990 { 1991 m_assembler.bkpt(); 1992 } 1993 nearCall()1994 Call nearCall() 1995 { 1996 /* We need two words for relaxation. */ 1997 m_assembler.nop(); 1998 m_assembler.nop(); 1999 m_assembler.jal(); 2000 m_assembler.nop(); 2001 return Call(m_assembler.label(), Call::LinkableNear); 2002 } 2003 call()2004 Call call() 2005 { 2006 m_assembler.lui(MIPSRegisters::t9, 0); 2007 m_assembler.ori(MIPSRegisters::t9, MIPSRegisters::t9, 0); 2008 m_assembler.jalr(MIPSRegisters::t9); 2009 m_assembler.nop(); 2010 return Call(m_assembler.label(), Call::Linkable); 2011 } 2012 call(RegisterID target)2013 Call call(RegisterID target) 2014 { 2015 move(target, MIPSRegisters::t9); 2016 m_assembler.jalr(MIPSRegisters::t9); 2017 m_assembler.nop(); 2018 return Call(m_assembler.label(), Call::None); 2019 } 2020 call(Address address)2021 Call call(Address address) 2022 { 2023 m_fixedWidth = true; 2024 load32(address, MIPSRegisters::t9); 2025 m_assembler.jalr(MIPSRegisters::t9); 2026 m_assembler.nop(); 2027 m_fixedWidth = false; 2028 return Call(m_assembler.label(), Call::None); 2029 } 2030 ret()2031 void ret() 2032 { 2033 m_assembler.jr(MIPSRegisters::ra); 2034 m_assembler.nop(); 2035 } 2036 compare32(RelationalCondition cond,RegisterID left,RegisterID right,RegisterID dest)2037 void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest) 2038 { 2039 if (cond == Equal) { 2040 m_assembler.xorInsn(dest, left, right); 2041 m_assembler.sltiu(dest, dest, 1); 2042 } else if (cond == NotEqual) { 2043 m_assembler.xorInsn(dest, left, right); 2044 m_assembler.sltu(dest, MIPSRegisters::zero, dest); 2045 } else if (cond == Above) 2046 m_assembler.sltu(dest, right, left); 2047 else if (cond == AboveOrEqual) { 2048 m_assembler.sltu(dest, left, right); 2049 m_assembler.xori(dest, dest, 1); 2050 } else if (cond == Below) 2051 m_assembler.sltu(dest, left, right); 2052 else if (cond == BelowOrEqual) { 2053 m_assembler.sltu(dest, right, left); 2054 m_assembler.xori(dest, dest, 1); 2055 } else if (cond == GreaterThan) 2056 m_assembler.slt(dest, right, left); 2057 else if (cond == GreaterThanOrEqual) { 2058 m_assembler.slt(dest, left, right); 2059 m_assembler.xori(dest, dest, 1); 2060 } else if (cond == LessThan) 2061 m_assembler.slt(dest, left, right); 2062 else if (cond == LessThanOrEqual) { 2063 m_assembler.slt(dest, right, left); 2064 m_assembler.xori(dest, dest, 1); 2065 } 2066 } 2067 compare32(RelationalCondition cond,RegisterID left,TrustedImm32 right,RegisterID dest)2068 void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest) 2069 { 2070 move(right, immTempRegister); 2071 compare32(cond, left, immTempRegister, dest); 2072 } 2073 test8(ResultCondition cond,Address address,TrustedImm32 mask,RegisterID dest)2074 void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest) 2075 { 2076 ASSERT((cond == Zero) || (cond == NonZero)); 2077 load8(address, dataTempRegister); 2078 if (mask.m_value == -1 && !m_fixedWidth) { 2079 if (cond == Zero) 2080 m_assembler.sltiu(dest, dataTempRegister, 1); 2081 else 2082 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister); 2083 } else { 2084 move(mask, immTempRegister); 2085 m_assembler.andInsn(cmpTempRegister, dataTempRegister, immTempRegister); 2086 if (cond == Zero) 2087 m_assembler.sltiu(dest, cmpTempRegister, 1); 2088 else 2089 m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister); 2090 } 2091 } 2092 test32(ResultCondition cond,Address address,TrustedImm32 mask,RegisterID dest)2093 void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest) 2094 { 2095 ASSERT((cond == Zero) || (cond == NonZero)); 2096 load32(address, dataTempRegister); 2097 if (mask.m_value == -1 && !m_fixedWidth) { 2098 if (cond == Zero) 2099 m_assembler.sltiu(dest, dataTempRegister, 1); 2100 else 2101 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister); 2102 } else { 2103 move(mask, immTempRegister); 2104 m_assembler.andInsn(cmpTempRegister, dataTempRegister, immTempRegister); 2105 if (cond == Zero) 2106 m_assembler.sltiu(dest, cmpTempRegister, 1); 2107 else 2108 m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister); 2109 } 2110 } 2111 moveWithPatch(TrustedImm32 imm,RegisterID dest)2112 DataLabel32 moveWithPatch(TrustedImm32 imm, RegisterID dest) 2113 { 2114 m_fixedWidth = true; 2115 DataLabel32 label(this); 2116 move(imm, dest); 2117 m_fixedWidth = false; 2118 return label; 2119 } 2120 moveWithPatch(TrustedImmPtr initialValue,RegisterID dest)2121 DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest) 2122 { 2123 m_fixedWidth = true; 2124 DataLabelPtr label(this); 2125 move(initialValue, dest); 2126 m_fixedWidth = false; 2127 return label; 2128 } 2129 2130 Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) 2131 { 2132 m_fixedWidth = true; 2133 dataLabel = moveWithPatch(initialRightValue, immTempRegister); 2134 Jump temp = branch32(cond, left, immTempRegister); 2135 m_fixedWidth = false; 2136 return temp; 2137 } 2138 2139 Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) 2140 { 2141 m_fixedWidth = true; 2142 load32(left, dataTempRegister); 2143 dataLabel = moveWithPatch(initialRightValue, immTempRegister); 2144 Jump temp = branch32(cond, dataTempRegister, immTempRegister); 2145 m_fixedWidth = false; 2146 return temp; 2147 } 2148 storePtrWithPatch(TrustedImmPtr initialValue,ImplicitAddress address)2149 DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address) 2150 { 2151 m_fixedWidth = true; 2152 DataLabelPtr dataLabel = moveWithPatch(initialValue, dataTempRegister); 2153 store32(dataTempRegister, address); 2154 m_fixedWidth = false; 2155 return dataLabel; 2156 } 2157 storePtrWithPatch(ImplicitAddress address)2158 DataLabelPtr storePtrWithPatch(ImplicitAddress address) 2159 { 2160 return storePtrWithPatch(TrustedImmPtr(0), address); 2161 } 2162 tailRecursiveCall()2163 Call tailRecursiveCall() 2164 { 2165 // Like a normal call, but don't update the returned address register 2166 m_fixedWidth = true; 2167 move(TrustedImm32(0), MIPSRegisters::t9); 2168 m_assembler.jr(MIPSRegisters::t9); 2169 m_assembler.nop(); 2170 m_fixedWidth = false; 2171 return Call(m_assembler.label(), Call::Linkable); 2172 } 2173 makeTailRecursiveCall(Jump oldJump)2174 Call makeTailRecursiveCall(Jump oldJump) 2175 { 2176 oldJump.link(this); 2177 return tailRecursiveCall(); 2178 } 2179 loadFloat(BaseIndex address,FPRegisterID dest)2180 void loadFloat(BaseIndex address, FPRegisterID dest) 2181 { 2182 if (address.offset >= -32768 && address.offset <= 32767 2183 && !m_fixedWidth) { 2184 /* 2185 sll addrTemp, address.index, address.scale 2186 addu addrTemp, addrTemp, address.base 2187 lwc1 dest, address.offset(addrTemp) 2188 */ 2189 m_assembler.sll(addrTempRegister, address.index, address.scale); 2190 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2191 m_assembler.lwc1(dest, addrTempRegister, address.offset); 2192 } else { 2193 /* 2194 sll addrTemp, address.index, address.scale 2195 addu addrTemp, addrTemp, address.base 2196 lui immTemp, (address.offset + 0x8000) >> 16 2197 addu addrTemp, addrTemp, immTemp 2198 lwc1 dest, (address.offset & 0xffff)(at) 2199 */ 2200 m_assembler.sll(addrTempRegister, address.index, address.scale); 2201 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2202 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 2203 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 2204 m_assembler.lwc1(dest, addrTempRegister, address.offset); 2205 } 2206 } 2207 loadDouble(ImplicitAddress address,FPRegisterID dest)2208 void loadDouble(ImplicitAddress address, FPRegisterID dest) 2209 { 2210 #if WTF_MIPS_ISA(1) 2211 /* 2212 li addrTemp, address.offset 2213 addu addrTemp, addrTemp, base 2214 lwc1 dest, 0(addrTemp) 2215 lwc1 dest+1, 4(addrTemp) 2216 */ 2217 move(TrustedImm32(address.offset), addrTempRegister); 2218 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2219 m_assembler.lwc1(dest, addrTempRegister, 0); 2220 m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4); 2221 #else 2222 if (address.offset >= -32768 && address.offset <= 32767 2223 && !m_fixedWidth) { 2224 m_assembler.ldc1(dest, address.base, address.offset); 2225 } else { 2226 /* 2227 lui addrTemp, (offset + 0x8000) >> 16 2228 addu addrTemp, addrTemp, base 2229 ldc1 dest, (offset & 0xffff)(addrTemp) 2230 */ 2231 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 2232 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2233 m_assembler.ldc1(dest, addrTempRegister, address.offset); 2234 } 2235 #endif 2236 } 2237 loadDouble(BaseIndex address,FPRegisterID dest)2238 void loadDouble(BaseIndex address, FPRegisterID dest) 2239 { 2240 #if WTF_MIPS_ISA(1) 2241 if (address.offset >= -32768 && address.offset <= 32767 2242 && !m_fixedWidth) { 2243 /* 2244 sll addrTemp, address.index, address.scale 2245 addu addrTemp, addrTemp, address.base 2246 lwc1 dest, address.offset(addrTemp) 2247 lwc1 dest+1, (address.offset+4)(addrTemp) 2248 */ 2249 m_assembler.sll(addrTempRegister, address.index, address.scale); 2250 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2251 m_assembler.lwc1(dest, addrTempRegister, address.offset); 2252 m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, address.offset + 4); 2253 } else { 2254 /* 2255 sll addrTemp, address.index, address.scale 2256 addu addrTemp, addrTemp, address.base 2257 lui immTemp, (address.offset + 0x8000) >> 16 2258 addu addrTemp, addrTemp, immTemp 2259 lwc1 dest, (address.offset & 0xffff)(at) 2260 lwc1 dest+1, (address.offset & 0xffff + 4)(at) 2261 */ 2262 m_assembler.sll(addrTempRegister, address.index, address.scale); 2263 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2264 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 2265 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 2266 m_assembler.lwc1(dest, addrTempRegister, address.offset); 2267 m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, address.offset + 4); 2268 } 2269 #else 2270 if (address.offset >= -32768 && address.offset <= 32767 2271 && !m_fixedWidth) { 2272 /* 2273 sll addrTemp, address.index, address.scale 2274 addu addrTemp, addrTemp, address.base 2275 ldc1 dest, address.offset(addrTemp) 2276 */ 2277 m_assembler.sll(addrTempRegister, address.index, address.scale); 2278 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2279 m_assembler.ldc1(dest, addrTempRegister, address.offset); 2280 } else { 2281 /* 2282 sll addrTemp, address.index, address.scale 2283 addu addrTemp, addrTemp, address.base 2284 lui immTemp, (address.offset + 0x8000) >> 16 2285 addu addrTemp, addrTemp, immTemp 2286 ldc1 dest, (address.offset & 0xffff)(at) 2287 */ 2288 m_assembler.sll(addrTempRegister, address.index, address.scale); 2289 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2290 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 2291 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 2292 m_assembler.ldc1(dest, addrTempRegister, address.offset); 2293 } 2294 #endif 2295 } 2296 loadDouble(const void * address,FPRegisterID dest)2297 void loadDouble(const void* address, FPRegisterID dest) 2298 { 2299 #if WTF_MIPS_ISA(1) 2300 /* 2301 li addrTemp, address 2302 lwc1 dest, 0(addrTemp) 2303 lwc1 dest+1, 4(addrTemp) 2304 */ 2305 move(TrustedImmPtr(address), addrTempRegister); 2306 m_assembler.lwc1(dest, addrTempRegister, 0); 2307 m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4); 2308 #else 2309 /* 2310 li addrTemp, address 2311 ldc1 dest, 0(addrTemp) 2312 */ 2313 move(TrustedImmPtr(address), addrTempRegister); 2314 m_assembler.ldc1(dest, addrTempRegister, 0); 2315 #endif 2316 } 2317 storeFloat(FPRegisterID src,BaseIndex address)2318 void storeFloat(FPRegisterID src, BaseIndex address) 2319 { 2320 if (address.offset >= -32768 && address.offset <= 32767 2321 && !m_fixedWidth) { 2322 /* 2323 sll addrTemp, address.index, address.scale 2324 addu addrTemp, addrTemp, address.base 2325 swc1 src, address.offset(addrTemp) 2326 */ 2327 m_assembler.sll(addrTempRegister, address.index, address.scale); 2328 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2329 m_assembler.swc1(src, addrTempRegister, address.offset); 2330 } else { 2331 /* 2332 sll addrTemp, address.index, address.scale 2333 addu addrTemp, addrTemp, address.base 2334 lui immTemp, (address.offset + 0x8000) >> 16 2335 addu addrTemp, addrTemp, immTemp 2336 swc1 src, (address.offset & 0xffff)(at) 2337 */ 2338 m_assembler.sll(addrTempRegister, address.index, address.scale); 2339 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2340 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 2341 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 2342 m_assembler.swc1(src, addrTempRegister, address.offset); 2343 } 2344 } 2345 storeDouble(FPRegisterID src,ImplicitAddress address)2346 void storeDouble(FPRegisterID src, ImplicitAddress address) 2347 { 2348 #if WTF_MIPS_ISA(1) 2349 /* 2350 li addrTemp, address.offset 2351 addu addrTemp, addrTemp, base 2352 swc1 dest, 0(addrTemp) 2353 swc1 dest+1, 4(addrTemp) 2354 */ 2355 move(TrustedImm32(address.offset), addrTempRegister); 2356 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2357 m_assembler.swc1(src, addrTempRegister, 0); 2358 m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4); 2359 #else 2360 if (address.offset >= -32768 && address.offset <= 32767 2361 && !m_fixedWidth) 2362 m_assembler.sdc1(src, address.base, address.offset); 2363 else { 2364 /* 2365 lui addrTemp, (offset + 0x8000) >> 16 2366 addu addrTemp, addrTemp, base 2367 sdc1 src, (offset & 0xffff)(addrTemp) 2368 */ 2369 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 2370 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2371 m_assembler.sdc1(src, addrTempRegister, address.offset); 2372 } 2373 #endif 2374 } 2375 storeDouble(FPRegisterID src,BaseIndex address)2376 void storeDouble(FPRegisterID src, BaseIndex address) 2377 { 2378 #if WTF_MIPS_ISA(1) 2379 if (address.offset >= -32768 && address.offset <= 32767 2380 && !m_fixedWidth) { 2381 /* 2382 sll addrTemp, address.index, address.scale 2383 addu addrTemp, addrTemp, address.base 2384 swc1 src, address.offset(addrTemp) 2385 swc1 src+1, (address.offset + 4)(addrTemp) 2386 */ 2387 m_assembler.sll(addrTempRegister, address.index, address.scale); 2388 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2389 m_assembler.swc1(src, addrTempRegister, address.offset); 2390 m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, address.offset + 4); 2391 } else { 2392 /* 2393 sll addrTemp, address.index, address.scale 2394 addu addrTemp, addrTemp, address.base 2395 lui immTemp, (address.offset + 0x8000) >> 16 2396 addu addrTemp, addrTemp, immTemp 2397 swc1 src, (address.offset & 0xffff)(at) 2398 swc1 src+1, (address.offset & 0xffff + 4)(at) 2399 */ 2400 m_assembler.sll(addrTempRegister, address.index, address.scale); 2401 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2402 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 2403 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 2404 m_assembler.swc1(src, addrTempRegister, address.offset); 2405 m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, address.offset + 4); 2406 } 2407 #else 2408 if (address.offset >= -32768 && address.offset <= 32767 2409 && !m_fixedWidth) { 2410 /* 2411 sll addrTemp, address.index, address.scale 2412 addu addrTemp, addrTemp, address.base 2413 sdc1 src, address.offset(addrTemp) 2414 */ 2415 m_assembler.sll(addrTempRegister, address.index, address.scale); 2416 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2417 m_assembler.sdc1(src, addrTempRegister, address.offset); 2418 } else { 2419 /* 2420 sll addrTemp, address.index, address.scale 2421 addu addrTemp, addrTemp, address.base 2422 lui immTemp, (address.offset + 0x8000) >> 16 2423 addu addrTemp, addrTemp, immTemp 2424 sdc1 src, (address.offset & 0xffff)(at) 2425 */ 2426 m_assembler.sll(addrTempRegister, address.index, address.scale); 2427 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 2428 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 2429 m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); 2430 m_assembler.sdc1(src, addrTempRegister, address.offset); 2431 } 2432 #endif 2433 } 2434 storeDouble(FPRegisterID src,const void * address)2435 void storeDouble(FPRegisterID src, const void* address) 2436 { 2437 #if WTF_MIPS_ISA(1) 2438 move(TrustedImmPtr(address), addrTempRegister); 2439 m_assembler.swc1(src, addrTempRegister, 0); 2440 m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4); 2441 #else 2442 move(TrustedImmPtr(address), addrTempRegister); 2443 m_assembler.sdc1(src, addrTempRegister, 0); 2444 #endif 2445 } 2446 moveDouble(FPRegisterID src,FPRegisterID dest)2447 void moveDouble(FPRegisterID src, FPRegisterID dest) 2448 { 2449 if (src != dest || m_fixedWidth) 2450 m_assembler.movd(dest, src); 2451 } 2452 swapDouble(FPRegisterID fr1,FPRegisterID fr2)2453 void swapDouble(FPRegisterID fr1, FPRegisterID fr2) 2454 { 2455 moveDouble(fr1, fpTempRegister); 2456 moveDouble(fr2, fr1); 2457 moveDouble(fpTempRegister, fr2); 2458 } 2459 addDouble(FPRegisterID src,FPRegisterID dest)2460 void addDouble(FPRegisterID src, FPRegisterID dest) 2461 { 2462 m_assembler.addd(dest, dest, src); 2463 } 2464 addDouble(FPRegisterID op1,FPRegisterID op2,FPRegisterID dest)2465 void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) 2466 { 2467 m_assembler.addd(dest, op1, op2); 2468 } 2469 addDouble(Address src,FPRegisterID dest)2470 void addDouble(Address src, FPRegisterID dest) 2471 { 2472 loadDouble(src, fpTempRegister); 2473 m_assembler.addd(dest, dest, fpTempRegister); 2474 } 2475 addDouble(AbsoluteAddress address,FPRegisterID dest)2476 void addDouble(AbsoluteAddress address, FPRegisterID dest) 2477 { 2478 loadDouble(address.m_ptr, fpTempRegister); 2479 m_assembler.addd(dest, dest, fpTempRegister); 2480 } 2481 subDouble(FPRegisterID src,FPRegisterID dest)2482 void subDouble(FPRegisterID src, FPRegisterID dest) 2483 { 2484 m_assembler.subd(dest, dest, src); 2485 } 2486 subDouble(FPRegisterID op1,FPRegisterID op2,FPRegisterID dest)2487 void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) 2488 { 2489 m_assembler.subd(dest, op1, op2); 2490 } 2491 subDouble(Address src,FPRegisterID dest)2492 void subDouble(Address src, FPRegisterID dest) 2493 { 2494 loadDouble(src, fpTempRegister); 2495 m_assembler.subd(dest, dest, fpTempRegister); 2496 } 2497 mulDouble(FPRegisterID src,FPRegisterID dest)2498 void mulDouble(FPRegisterID src, FPRegisterID dest) 2499 { 2500 m_assembler.muld(dest, dest, src); 2501 } 2502 mulDouble(Address src,FPRegisterID dest)2503 void mulDouble(Address src, FPRegisterID dest) 2504 { 2505 loadDouble(src, fpTempRegister); 2506 m_assembler.muld(dest, dest, fpTempRegister); 2507 } 2508 mulDouble(FPRegisterID op1,FPRegisterID op2,FPRegisterID dest)2509 void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) 2510 { 2511 m_assembler.muld(dest, op1, op2); 2512 } 2513 divDouble(FPRegisterID src,FPRegisterID dest)2514 void divDouble(FPRegisterID src, FPRegisterID dest) 2515 { 2516 m_assembler.divd(dest, dest, src); 2517 } 2518 divDouble(FPRegisterID op1,FPRegisterID op2,FPRegisterID dest)2519 void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) 2520 { 2521 m_assembler.divd(dest, op1, op2); 2522 } 2523 divDouble(Address src,FPRegisterID dest)2524 void divDouble(Address src, FPRegisterID dest) 2525 { 2526 loadDouble(src, fpTempRegister); 2527 m_assembler.divd(dest, dest, fpTempRegister); 2528 } 2529 negateDouble(FPRegisterID src,FPRegisterID dest)2530 void negateDouble(FPRegisterID src, FPRegisterID dest) 2531 { 2532 m_assembler.negd(dest, src); 2533 } 2534 convertInt32ToDouble(RegisterID src,FPRegisterID dest)2535 void convertInt32ToDouble(RegisterID src, FPRegisterID dest) 2536 { 2537 m_assembler.mtc1(src, fpTempRegister); 2538 m_assembler.cvtdw(dest, fpTempRegister); 2539 } 2540 convertInt32ToDouble(Address src,FPRegisterID dest)2541 void convertInt32ToDouble(Address src, FPRegisterID dest) 2542 { 2543 load32(src, dataTempRegister); 2544 m_assembler.mtc1(dataTempRegister, fpTempRegister); 2545 m_assembler.cvtdw(dest, fpTempRegister); 2546 } 2547 convertInt32ToDouble(AbsoluteAddress src,FPRegisterID dest)2548 void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest) 2549 { 2550 load32(src.m_ptr, dataTempRegister); 2551 m_assembler.mtc1(dataTempRegister, fpTempRegister); 2552 m_assembler.cvtdw(dest, fpTempRegister); 2553 } 2554 convertUInt32ToDouble(RegisterID src,FPRegisterID dest,RegisterID scratch)2555 void convertUInt32ToDouble(RegisterID src, FPRegisterID dest, RegisterID scratch) 2556 { 2557 m_assembler.mtc1(src, fpTempRegister); 2558 m_assembler.bltz(src, 2); 2559 m_assembler.cvtdw(dest, fpTempRegister); 2560 m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 4); 2561 m_assembler.lui(scratch, 0x4f80); 2562 m_assembler.mtc1(scratch, fpTempRegister); 2563 m_assembler.cvtds(fpTempRegister, fpTempRegister); 2564 m_assembler.addd(dest, dest, fpTempRegister); 2565 } 2566 convertFloatToDouble(FPRegisterID src,FPRegisterID dst)2567 void convertFloatToDouble(FPRegisterID src, FPRegisterID dst) 2568 { 2569 m_assembler.cvtds(dst, src); 2570 } 2571 convertDoubleToFloat(FPRegisterID src,FPRegisterID dst)2572 void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst) 2573 { 2574 m_assembler.cvtsd(dst, src); 2575 } 2576 insertRelaxationWords()2577 void insertRelaxationWords() 2578 { 2579 /* We need four words for relaxation. */ 2580 m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 3); // Jump over nops; 2581 m_assembler.nop(); 2582 m_assembler.nop(); 2583 m_assembler.nop(); 2584 } 2585 branchTrue()2586 Jump branchTrue() 2587 { 2588 m_assembler.appendJump(); 2589 m_assembler.bc1t(); 2590 m_assembler.nop(); 2591 insertRelaxationWords(); 2592 return Jump(m_assembler.label()); 2593 } 2594 branchFalse()2595 Jump branchFalse() 2596 { 2597 m_assembler.appendJump(); 2598 m_assembler.bc1f(); 2599 m_assembler.nop(); 2600 insertRelaxationWords(); 2601 return Jump(m_assembler.label()); 2602 } 2603 branchEqual(RegisterID rs,RegisterID rt)2604 Jump branchEqual(RegisterID rs, RegisterID rt) 2605 { 2606 m_assembler.nop(); 2607 m_assembler.nop(); 2608 m_assembler.appendJump(); 2609 m_assembler.beq(rs, rt, 0); 2610 m_assembler.nop(); 2611 insertRelaxationWords(); 2612 return Jump(m_assembler.label()); 2613 } 2614 branchNotEqual(RegisterID rs,RegisterID rt)2615 Jump branchNotEqual(RegisterID rs, RegisterID rt) 2616 { 2617 m_assembler.nop(); 2618 m_assembler.nop(); 2619 m_assembler.appendJump(); 2620 m_assembler.bne(rs, rt, 0); 2621 m_assembler.nop(); 2622 insertRelaxationWords(); 2623 return Jump(m_assembler.label()); 2624 } 2625 branchDouble(DoubleCondition cond,FPRegisterID left,FPRegisterID right)2626 Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right) 2627 { 2628 if (cond == DoubleEqual) { 2629 m_assembler.ceqd(left, right); 2630 return branchTrue(); 2631 } 2632 if (cond == DoubleNotEqual) { 2633 m_assembler.cueqd(left, right); 2634 return branchFalse(); // false 2635 } 2636 if (cond == DoubleGreaterThan) { 2637 m_assembler.cngtd(left, right); 2638 return branchFalse(); // false 2639 } 2640 if (cond == DoubleGreaterThanOrEqual) { 2641 m_assembler.cnged(left, right); 2642 return branchFalse(); // false 2643 } 2644 if (cond == DoubleLessThan) { 2645 m_assembler.cltd(left, right); 2646 return branchTrue(); 2647 } 2648 if (cond == DoubleLessThanOrEqual) { 2649 m_assembler.cled(left, right); 2650 return branchTrue(); 2651 } 2652 if (cond == DoubleEqualOrUnordered) { 2653 m_assembler.cueqd(left, right); 2654 return branchTrue(); 2655 } 2656 if (cond == DoubleNotEqualOrUnordered) { 2657 m_assembler.ceqd(left, right); 2658 return branchFalse(); // false 2659 } 2660 if (cond == DoubleGreaterThanOrUnordered) { 2661 m_assembler.coled(left, right); 2662 return branchFalse(); // false 2663 } 2664 if (cond == DoubleGreaterThanOrEqualOrUnordered) { 2665 m_assembler.coltd(left, right); 2666 return branchFalse(); // false 2667 } 2668 if (cond == DoubleLessThanOrUnordered) { 2669 m_assembler.cultd(left, right); 2670 return branchTrue(); 2671 } 2672 if (cond == DoubleLessThanOrEqualOrUnordered) { 2673 m_assembler.culed(left, right); 2674 return branchTrue(); 2675 } 2676 ASSERT(0); 2677 2678 return Jump(); 2679 } 2680 2681 // Truncates 'src' to an integer, and places the resulting 'dest'. 2682 // If the result is not representable as a 32 bit value, branch. 2683 // May also branch for some values that are representable in 32 bits 2684 // (specifically, in this case, INT_MAX 0x7fffffff). 2685 enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful }; 2686 Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed) 2687 { 2688 m_assembler.truncwd(fpTempRegister, src); 2689 m_assembler.mfc1(dest, fpTempRegister); 2690 return branch32(branchType == BranchIfTruncateFailed ? Equal : NotEqual, dest, TrustedImm32(0x7fffffff)); 2691 } 2692 2693 Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed) 2694 { 2695 m_assembler.truncwd(fpTempRegister, src); 2696 m_assembler.mfc1(dest, fpTempRegister); 2697 return branch32(branchType == BranchIfTruncateFailed ? Equal : NotEqual, dest, TrustedImm32(0x7fffffff)); 2698 } 2699 2700 // Result is undefined if the value is outside of the integer range. truncateDoubleToInt32(FPRegisterID src,RegisterID dest)2701 void truncateDoubleToInt32(FPRegisterID src, RegisterID dest) 2702 { 2703 m_assembler.truncwd(fpTempRegister, src); 2704 m_assembler.mfc1(dest, fpTempRegister); 2705 } 2706 2707 // Result is undefined if src > 2^31 truncateDoubleToUint32(FPRegisterID src,RegisterID dest)2708 void truncateDoubleToUint32(FPRegisterID src, RegisterID dest) 2709 { 2710 m_assembler.truncwd(fpTempRegister, src); 2711 m_assembler.mfc1(dest, fpTempRegister); 2712 } 2713 2714 // Convert 'src' to an integer, and places the resulting 'dest'. 2715 // If the result is not representable as a 32 bit value, branch. 2716 // May also branch for some values that are representable in 32 bits 2717 // (specifically, in this case, 0). branchConvertDoubleToInt32(FPRegisterID src,RegisterID dest,JumpList & failureCases,FPRegisterID fpTemp)2718 void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp) 2719 { 2720 m_assembler.cvtwd(fpTempRegister, src); 2721 m_assembler.mfc1(dest, fpTempRegister); 2722 2723 // If the result is zero, it might have been -0.0, and the double comparison won't catch this! 2724 failureCases.append(branch32(Equal, dest, MIPSRegisters::zero)); 2725 2726 // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump. 2727 convertInt32ToDouble(dest, fpTemp); 2728 failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fpTemp, src)); 2729 } 2730 branchDoubleNonZero(FPRegisterID reg,FPRegisterID scratch)2731 Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch) 2732 { 2733 m_assembler.vmov(scratch, MIPSRegisters::zero, MIPSRegisters::zero); 2734 return branchDouble(DoubleNotEqual, reg, scratch); 2735 } 2736 branchDoubleZeroOrNaN(FPRegisterID reg,FPRegisterID scratch)2737 Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch) 2738 { 2739 m_assembler.vmov(scratch, MIPSRegisters::zero, MIPSRegisters::zero); 2740 return branchDouble(DoubleEqualOrUnordered, reg, scratch); 2741 } 2742 2743 // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc. invert(RelationalCondition cond)2744 static RelationalCondition invert(RelationalCondition cond) 2745 { 2746 RelationalCondition r; 2747 if (cond == Equal) 2748 r = NotEqual; 2749 else if (cond == NotEqual) 2750 r = Equal; 2751 else if (cond == Above) 2752 r = BelowOrEqual; 2753 else if (cond == AboveOrEqual) 2754 r = Below; 2755 else if (cond == Below) 2756 r = AboveOrEqual; 2757 else if (cond == BelowOrEqual) 2758 r = Above; 2759 else if (cond == GreaterThan) 2760 r = LessThanOrEqual; 2761 else if (cond == GreaterThanOrEqual) 2762 r = LessThan; 2763 else if (cond == LessThan) 2764 r = GreaterThanOrEqual; 2765 else if (cond == LessThanOrEqual) 2766 r = GreaterThan; 2767 return r; 2768 } 2769 nop()2770 void nop() 2771 { 2772 m_assembler.nop(); 2773 } 2774 readCallTarget(CodeLocationCall call)2775 static FunctionPtr readCallTarget(CodeLocationCall call) 2776 { 2777 return FunctionPtr(reinterpret_cast<void(*)()>(MIPSAssembler::readCallTarget(call.dataLocation()))); 2778 } 2779 replaceWithJump(CodeLocationLabel instructionStart,CodeLocationLabel destination)2780 static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination) 2781 { 2782 MIPSAssembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation()); 2783 } 2784 maxJumpReplacementSize()2785 static ptrdiff_t maxJumpReplacementSize() 2786 { 2787 MIPSAssembler::maxJumpReplacementSize(); 2788 return 0; 2789 } 2790 canJumpReplacePatchableBranchPtrWithPatch()2791 static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; } 2792 startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label)2793 static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label) 2794 { 2795 return label.labelAtOffset(0); 2796 } 2797 revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart,RegisterID,void * initialValue)2798 static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID, void* initialValue) 2799 { 2800 MIPSAssembler::revertJumpToMove(instructionStart.dataLocation(), immTempRegister, reinterpret_cast<int>(initialValue) & 0xffff); 2801 } 2802 startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr)2803 static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr) 2804 { 2805 UNREACHABLE_FOR_PLATFORM(); 2806 return CodeLocationLabel(); 2807 } 2808 revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel,Address,void *)2809 static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel, Address, void*) 2810 { 2811 UNREACHABLE_FOR_PLATFORM(); 2812 } 2813 2814 2815 private: 2816 // If m_fixedWidth is true, we will generate a fixed number of instructions. 2817 // Otherwise, we can emit any number of instructions. 2818 bool m_fixedWidth; 2819 2820 template <typename, template <typename> class> friend class LinkBufferBase; 2821 friend class RepatchBuffer; 2822 linkCall(void * code,Call call,FunctionPtr function)2823 static void linkCall(void* code, Call call, FunctionPtr function) 2824 { 2825 MIPSAssembler::linkCall(code, call.m_label, function.value()); 2826 } 2827 repatchCall(CodeLocationCall call,CodeLocationLabel destination)2828 static void repatchCall(CodeLocationCall call, CodeLocationLabel destination) 2829 { 2830 MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress()); 2831 } 2832 repatchCall(CodeLocationCall call,FunctionPtr destination)2833 static void repatchCall(CodeLocationCall call, FunctionPtr destination) 2834 { 2835 MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress()); 2836 } 2837 2838 }; 2839 2840 } 2841 2842 #endif // ENABLE(ASSEMBLER) && CPU(MIPS) 2843 2844 #endif // MacroAssemblerMIPS_h 2845