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 #if ENABLE(ASSEMBLER) && CPU(MIPS) 31 32 #include "MIPSAssembler.h" 33 #include "AbstractMacroAssembler.h" 34 35 namespace JSC { 36 37 class MacroAssemblerMIPS : public AbstractMacroAssembler<MIPSAssembler> { 38 public: 39 typedef MIPSRegisters::FPRegisterID FPRegisterID; 40 MacroAssemblerMIPS()41 MacroAssemblerMIPS() 42 : m_fixedWidth(false) 43 { 44 } 45 46 static const Scale ScalePtr = TimesFour; 47 48 // For storing immediate number 49 static const RegisterID immTempRegister = MIPSRegisters::t0; 50 // For storing data loaded from the memory 51 static const RegisterID dataTempRegister = MIPSRegisters::t1; 52 // For storing address base 53 static const RegisterID addrTempRegister = MIPSRegisters::t2; 54 // For storing compare result 55 static const RegisterID cmpTempRegister = MIPSRegisters::t3; 56 57 // FP temp register 58 static const FPRegisterID fpTempRegister = MIPSRegisters::f16; 59 60 enum RelationalCondition { 61 Equal, 62 NotEqual, 63 Above, 64 AboveOrEqual, 65 Below, 66 BelowOrEqual, 67 GreaterThan, 68 GreaterThanOrEqual, 69 LessThan, 70 LessThanOrEqual 71 }; 72 73 enum ResultCondition { 74 Overflow, 75 Signed, 76 Zero, 77 NonZero 78 }; 79 80 enum DoubleCondition { 81 DoubleEqual, 82 DoubleNotEqual, 83 DoubleGreaterThan, 84 DoubleGreaterThanOrEqual, 85 DoubleLessThan, 86 DoubleLessThanOrEqual, 87 DoubleEqualOrUnordered, 88 DoubleNotEqualOrUnordered, 89 DoubleGreaterThanOrUnordered, 90 DoubleGreaterThanOrEqualOrUnordered, 91 DoubleLessThanOrUnordered, 92 DoubleLessThanOrEqualOrUnordered 93 }; 94 95 static const RegisterID stackPointerRegister = MIPSRegisters::sp; 96 static const RegisterID returnAddressRegister = MIPSRegisters::ra; 97 98 // Integer arithmetic operations: 99 // 100 // Operations are typically two operand - operation(source, srcDst) 101 // For many operations the source may be an TrustedImm32, the srcDst operand 102 // may often be a memory location (explictly described using an Address 103 // object). 104 add32(RegisterID src,RegisterID dest)105 void add32(RegisterID src, RegisterID dest) 106 { 107 m_assembler.addu(dest, dest, src); 108 } 109 add32(TrustedImm32 imm,RegisterID dest)110 void add32(TrustedImm32 imm, RegisterID dest) 111 { 112 add32(imm, dest, dest); 113 } 114 add32(TrustedImm32 imm,RegisterID src,RegisterID dest)115 void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) 116 { 117 if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767 118 && !m_fixedWidth) { 119 /* 120 addiu dest, src, imm 121 */ 122 m_assembler.addiu(dest, src, imm.m_value); 123 } else { 124 /* 125 li immTemp, imm 126 addu dest, src, immTemp 127 */ 128 move(imm, immTempRegister); 129 m_assembler.addu(dest, src, immTempRegister); 130 } 131 } 132 add32(TrustedImm32 imm,Address address)133 void add32(TrustedImm32 imm, Address address) 134 { 135 if (address.offset >= -32768 && address.offset <= 32767 136 && !m_fixedWidth) { 137 /* 138 lw dataTemp, offset(base) 139 li immTemp, imm 140 addu dataTemp, dataTemp, immTemp 141 sw dataTemp, offset(base) 142 */ 143 m_assembler.lw(dataTempRegister, address.base, address.offset); 144 if (!imm.m_isPointer 145 && imm.m_value >= -32768 && imm.m_value <= 32767 146 && !m_fixedWidth) 147 m_assembler.addiu(dataTempRegister, dataTempRegister, 148 imm.m_value); 149 else { 150 move(imm, immTempRegister); 151 m_assembler.addu(dataTempRegister, dataTempRegister, 152 immTempRegister); 153 } 154 m_assembler.sw(dataTempRegister, address.base, address.offset); 155 } else { 156 /* 157 lui addrTemp, (offset + 0x8000) >> 16 158 addu addrTemp, addrTemp, base 159 lw dataTemp, (offset & 0xffff)(addrTemp) 160 li immtemp, imm 161 addu dataTemp, dataTemp, immTemp 162 sw dataTemp, (offset & 0xffff)(addrTemp) 163 */ 164 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 165 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 166 m_assembler.lw(dataTempRegister, addrTempRegister, address.offset); 167 168 if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) 169 m_assembler.addiu(dataTempRegister, dataTempRegister, 170 imm.m_value); 171 else { 172 move(imm, immTempRegister); 173 m_assembler.addu(dataTempRegister, dataTempRegister, 174 immTempRegister); 175 } 176 m_assembler.sw(dataTempRegister, addrTempRegister, address.offset); 177 } 178 } 179 add32(Address src,RegisterID dest)180 void add32(Address src, RegisterID dest) 181 { 182 load32(src, dataTempRegister); 183 add32(dataTempRegister, dest); 184 } 185 add32(RegisterID src,Address dest)186 void add32(RegisterID src, Address dest) 187 { 188 if (dest.offset >= -32768 && dest.offset <= 32767 && !m_fixedWidth) { 189 /* 190 lw dataTemp, offset(base) 191 addu dataTemp, dataTemp, src 192 sw dataTemp, offset(base) 193 */ 194 m_assembler.lw(dataTempRegister, dest.base, dest.offset); 195 m_assembler.addu(dataTempRegister, dataTempRegister, src); 196 m_assembler.sw(dataTempRegister, dest.base, dest.offset); 197 } else { 198 /* 199 lui addrTemp, (offset + 0x8000) >> 16 200 addu addrTemp, addrTemp, base 201 lw dataTemp, (offset & 0xffff)(addrTemp) 202 addu dataTemp, dataTemp, src 203 sw dataTemp, (offset & 0xffff)(addrTemp) 204 */ 205 m_assembler.lui(addrTempRegister, (dest.offset + 0x8000) >> 16); 206 m_assembler.addu(addrTempRegister, addrTempRegister, dest.base); 207 m_assembler.lw(dataTempRegister, addrTempRegister, dest.offset); 208 m_assembler.addu(dataTempRegister, dataTempRegister, src); 209 m_assembler.sw(dataTempRegister, addrTempRegister, dest.offset); 210 } 211 } 212 add32(TrustedImm32 imm,AbsoluteAddress address)213 void add32(TrustedImm32 imm, AbsoluteAddress address) 214 { 215 /* 216 li addrTemp, address 217 li immTemp, imm 218 lw dataTemp, 0(addrTemp) 219 addu dataTemp, dataTemp, immTemp 220 sw dataTemp, 0(addrTemp) 221 */ 222 move(TrustedImmPtr(address.m_ptr), addrTempRegister); 223 m_assembler.lw(dataTempRegister, addrTempRegister, 0); 224 if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767 225 && !m_fixedWidth) 226 m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value); 227 else { 228 move(imm, immTempRegister); 229 m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister); 230 } 231 m_assembler.sw(dataTempRegister, addrTempRegister, 0); 232 } 233 and32(RegisterID src,RegisterID dest)234 void and32(RegisterID src, RegisterID dest) 235 { 236 m_assembler.andInsn(dest, dest, src); 237 } 238 and32(TrustedImm32 imm,RegisterID dest)239 void and32(TrustedImm32 imm, RegisterID dest) 240 { 241 if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) 242 move(MIPSRegisters::zero, dest); 243 else if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535 244 && !m_fixedWidth) 245 m_assembler.andi(dest, dest, imm.m_value); 246 else { 247 /* 248 li immTemp, imm 249 and dest, dest, immTemp 250 */ 251 move(imm, immTempRegister); 252 m_assembler.andInsn(dest, dest, immTempRegister); 253 } 254 } 255 lshift32(TrustedImm32 imm,RegisterID dest)256 void lshift32(TrustedImm32 imm, RegisterID dest) 257 { 258 m_assembler.sll(dest, dest, imm.m_value); 259 } 260 lshift32(RegisterID shiftAmount,RegisterID dest)261 void lshift32(RegisterID shiftAmount, RegisterID dest) 262 { 263 m_assembler.sllv(dest, dest, shiftAmount); 264 } 265 mul32(RegisterID src,RegisterID dest)266 void mul32(RegisterID src, RegisterID dest) 267 { 268 m_assembler.mul(dest, dest, src); 269 } 270 mul32(TrustedImm32 imm,RegisterID src,RegisterID dest)271 void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest) 272 { 273 if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) 274 move(MIPSRegisters::zero, dest); 275 else if (!imm.m_isPointer && imm.m_value == 1 && !m_fixedWidth) 276 move(src, dest); 277 else { 278 /* 279 li dataTemp, imm 280 mul dest, src, dataTemp 281 */ 282 move(imm, dataTempRegister); 283 m_assembler.mul(dest, src, dataTempRegister); 284 } 285 } 286 neg32(RegisterID srcDest)287 void neg32(RegisterID srcDest) 288 { 289 m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest); 290 } 291 not32(RegisterID srcDest)292 void not32(RegisterID srcDest) 293 { 294 m_assembler.nor(srcDest, srcDest, MIPSRegisters::zero); 295 } 296 or32(RegisterID src,RegisterID dest)297 void or32(RegisterID src, RegisterID dest) 298 { 299 m_assembler.orInsn(dest, dest, src); 300 } 301 or32(TrustedImm32 imm,RegisterID dest)302 void or32(TrustedImm32 imm, RegisterID dest) 303 { 304 if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) 305 return; 306 307 if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535 308 && !m_fixedWidth) { 309 m_assembler.ori(dest, dest, imm.m_value); 310 return; 311 } 312 313 /* 314 li dataTemp, imm 315 or dest, dest, dataTemp 316 */ 317 move(imm, dataTempRegister); 318 m_assembler.orInsn(dest, dest, dataTempRegister); 319 } 320 rshift32(RegisterID shiftAmount,RegisterID dest)321 void rshift32(RegisterID shiftAmount, RegisterID dest) 322 { 323 m_assembler.srav(dest, dest, shiftAmount); 324 } 325 rshift32(TrustedImm32 imm,RegisterID dest)326 void rshift32(TrustedImm32 imm, RegisterID dest) 327 { 328 m_assembler.sra(dest, dest, imm.m_value); 329 } 330 urshift32(RegisterID shiftAmount,RegisterID dest)331 void urshift32(RegisterID shiftAmount, RegisterID dest) 332 { 333 m_assembler.srlv(dest, dest, shiftAmount); 334 } 335 urshift32(TrustedImm32 imm,RegisterID dest)336 void urshift32(TrustedImm32 imm, RegisterID dest) 337 { 338 m_assembler.srl(dest, dest, imm.m_value); 339 } 340 sub32(RegisterID src,RegisterID dest)341 void sub32(RegisterID src, RegisterID dest) 342 { 343 m_assembler.subu(dest, dest, src); 344 } 345 sub32(TrustedImm32 imm,RegisterID dest)346 void sub32(TrustedImm32 imm, RegisterID dest) 347 { 348 if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768 349 && !m_fixedWidth) { 350 /* 351 addiu dest, src, imm 352 */ 353 m_assembler.addiu(dest, dest, -imm.m_value); 354 } else { 355 /* 356 li immTemp, imm 357 subu dest, src, immTemp 358 */ 359 move(imm, immTempRegister); 360 m_assembler.subu(dest, dest, immTempRegister); 361 } 362 } 363 sub32(TrustedImm32 imm,Address address)364 void sub32(TrustedImm32 imm, Address address) 365 { 366 if (address.offset >= -32768 && address.offset <= 32767 367 && !m_fixedWidth) { 368 /* 369 lw dataTemp, offset(base) 370 li immTemp, imm 371 subu dataTemp, dataTemp, immTemp 372 sw dataTemp, offset(base) 373 */ 374 m_assembler.lw(dataTempRegister, address.base, address.offset); 375 if (!imm.m_isPointer 376 && imm.m_value >= -32767 && imm.m_value <= 32768 377 && !m_fixedWidth) 378 m_assembler.addiu(dataTempRegister, dataTempRegister, 379 -imm.m_value); 380 else { 381 move(imm, immTempRegister); 382 m_assembler.subu(dataTempRegister, dataTempRegister, 383 immTempRegister); 384 } 385 m_assembler.sw(dataTempRegister, address.base, address.offset); 386 } else { 387 /* 388 lui addrTemp, (offset + 0x8000) >> 16 389 addu addrTemp, addrTemp, base 390 lw dataTemp, (offset & 0xffff)(addrTemp) 391 li immtemp, imm 392 subu dataTemp, dataTemp, immTemp 393 sw dataTemp, (offset & 0xffff)(addrTemp) 394 */ 395 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 396 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 397 m_assembler.lw(dataTempRegister, addrTempRegister, address.offset); 398 399 if (!imm.m_isPointer 400 && imm.m_value >= -32767 && imm.m_value <= 32768 401 && !m_fixedWidth) 402 m_assembler.addiu(dataTempRegister, dataTempRegister, 403 -imm.m_value); 404 else { 405 move(imm, immTempRegister); 406 m_assembler.subu(dataTempRegister, dataTempRegister, 407 immTempRegister); 408 } 409 m_assembler.sw(dataTempRegister, addrTempRegister, address.offset); 410 } 411 } 412 sub32(Address src,RegisterID dest)413 void sub32(Address src, RegisterID dest) 414 { 415 load32(src, dataTempRegister); 416 sub32(dataTempRegister, dest); 417 } 418 sub32(TrustedImm32 imm,AbsoluteAddress address)419 void sub32(TrustedImm32 imm, AbsoluteAddress address) 420 { 421 /* 422 li addrTemp, address 423 li immTemp, imm 424 lw dataTemp, 0(addrTemp) 425 subu dataTemp, dataTemp, immTemp 426 sw dataTemp, 0(addrTemp) 427 */ 428 move(TrustedImmPtr(address.m_ptr), addrTempRegister); 429 m_assembler.lw(dataTempRegister, addrTempRegister, 0); 430 431 if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768 432 && !m_fixedWidth) { 433 m_assembler.addiu(dataTempRegister, dataTempRegister, 434 -imm.m_value); 435 } else { 436 move(imm, immTempRegister); 437 m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister); 438 } 439 m_assembler.sw(dataTempRegister, addrTempRegister, 0); 440 } 441 xor32(RegisterID src,RegisterID dest)442 void xor32(RegisterID src, RegisterID dest) 443 { 444 m_assembler.xorInsn(dest, dest, src); 445 } 446 xor32(TrustedImm32 imm,RegisterID dest)447 void xor32(TrustedImm32 imm, RegisterID dest) 448 { 449 /* 450 li immTemp, imm 451 xor dest, dest, immTemp 452 */ 453 move(imm, immTempRegister); 454 m_assembler.xorInsn(dest, dest, immTempRegister); 455 } 456 sqrtDouble(FPRegisterID src,FPRegisterID dst)457 void sqrtDouble(FPRegisterID src, FPRegisterID dst) 458 { 459 m_assembler.sqrtd(dst, src); 460 } 461 462 // Memory access operations: 463 // 464 // Loads are of the form load(address, destination) and stores of the form 465 // store(source, address). The source for a store may be an TrustedImm32. Address 466 // operand objects to loads and store will be implicitly constructed if a 467 // register is passed. 468 469 /* Need to use zero-extened load byte for load8. */ load8(ImplicitAddress address,RegisterID dest)470 void load8(ImplicitAddress address, RegisterID dest) 471 { 472 if (address.offset >= -32768 && address.offset <= 32767 473 && !m_fixedWidth) 474 m_assembler.lbu(dest, address.base, address.offset); 475 else { 476 /* 477 lui addrTemp, (offset + 0x8000) >> 16 478 addu addrTemp, addrTemp, base 479 lbu dest, (offset & 0xffff)(addrTemp) 480 */ 481 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 482 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 483 m_assembler.lbu(dest, addrTempRegister, address.offset); 484 } 485 } 486 load32(ImplicitAddress address,RegisterID dest)487 void load32(ImplicitAddress address, RegisterID dest) 488 { 489 if (address.offset >= -32768 && address.offset <= 32767 490 && !m_fixedWidth) 491 m_assembler.lw(dest, address.base, address.offset); 492 else { 493 /* 494 lui addrTemp, (offset + 0x8000) >> 16 495 addu addrTemp, addrTemp, base 496 lw dest, (offset & 0xffff)(addrTemp) 497 */ 498 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 499 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 500 m_assembler.lw(dest, addrTempRegister, address.offset); 501 } 502 } 503 load32(BaseIndex address,RegisterID dest)504 void load32(BaseIndex address, RegisterID dest) 505 { 506 if (address.offset >= -32768 && address.offset <= 32767 507 && !m_fixedWidth) { 508 /* 509 sll addrTemp, address.index, address.scale 510 addu addrTemp, addrTemp, address.base 511 lw dest, address.offset(addrTemp) 512 */ 513 m_assembler.sll(addrTempRegister, address.index, address.scale); 514 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 515 m_assembler.lw(dest, addrTempRegister, address.offset); 516 } else { 517 /* 518 sll addrTemp, address.index, address.scale 519 addu addrTemp, addrTemp, address.base 520 lui immTemp, (address.offset + 0x8000) >> 16 521 addu addrTemp, addrTemp, immTemp 522 lw dest, (address.offset & 0xffff)(at) 523 */ 524 m_assembler.sll(addrTempRegister, address.index, address.scale); 525 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 526 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 527 m_assembler.addu(addrTempRegister, addrTempRegister, 528 immTempRegister); 529 m_assembler.lw(dest, addrTempRegister, address.offset); 530 } 531 } 532 load32WithUnalignedHalfWords(BaseIndex address,RegisterID dest)533 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest) 534 { 535 if (address.offset >= -32768 && address.offset <= 32764 536 && !m_fixedWidth) { 537 /* 538 sll addrTemp, address.index, address.scale 539 addu addrTemp, addrTemp, address.base 540 (Big-Endian) 541 lwl dest, address.offset(addrTemp) 542 lwr dest, address.offset+3(addrTemp) 543 (Little-Endian) 544 lwl dest, address.offset+3(addrTemp) 545 lwr dest, address.offset(addrTemp) 546 */ 547 m_assembler.sll(addrTempRegister, address.index, address.scale); 548 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 549 #if CPU(BIG_ENDIAN) 550 m_assembler.lwl(dest, addrTempRegister, address.offset); 551 m_assembler.lwr(dest, addrTempRegister, address.offset + 3); 552 #else 553 m_assembler.lwl(dest, addrTempRegister, address.offset + 3); 554 m_assembler.lwr(dest, addrTempRegister, address.offset); 555 556 #endif 557 } else { 558 /* 559 sll addrTemp, address.index, address.scale 560 addu addrTemp, addrTemp, address.base 561 lui immTemp, address.offset >> 16 562 ori immTemp, immTemp, address.offset & 0xffff 563 addu addrTemp, addrTemp, immTemp 564 (Big-Endian) 565 lw dest, 0(at) 566 lw dest, 3(at) 567 (Little-Endian) 568 lw dest, 3(at) 569 lw dest, 0(at) 570 */ 571 m_assembler.sll(addrTempRegister, address.index, address.scale); 572 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 573 m_assembler.lui(immTempRegister, address.offset >> 16); 574 m_assembler.ori(immTempRegister, immTempRegister, address.offset); 575 m_assembler.addu(addrTempRegister, addrTempRegister, 576 immTempRegister); 577 #if CPU(BIG_ENDIAN) 578 m_assembler.lwl(dest, addrTempRegister, 0); 579 m_assembler.lwr(dest, addrTempRegister, 3); 580 #else 581 m_assembler.lwl(dest, addrTempRegister, 3); 582 m_assembler.lwr(dest, addrTempRegister, 0); 583 #endif 584 } 585 } 586 load32(const void * address,RegisterID dest)587 void load32(const void* address, RegisterID dest) 588 { 589 /* 590 li addrTemp, address 591 lw dest, 0(addrTemp) 592 */ 593 move(TrustedImmPtr(address), addrTempRegister); 594 m_assembler.lw(dest, addrTempRegister, 0); 595 } 596 load32WithAddressOffsetPatch(Address address,RegisterID dest)597 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest) 598 { 599 m_fixedWidth = true; 600 /* 601 lui addrTemp, address.offset >> 16 602 ori addrTemp, addrTemp, address.offset & 0xffff 603 addu addrTemp, addrTemp, address.base 604 lw dest, 0(addrTemp) 605 */ 606 DataLabel32 dataLabel(this); 607 move(TrustedImm32(address.offset), addrTempRegister); 608 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 609 m_assembler.lw(dest, addrTempRegister, 0); 610 m_fixedWidth = false; 611 return dataLabel; 612 } 613 614 /* Need to use zero-extened load half-word for load16. */ load16(ImplicitAddress address,RegisterID dest)615 void load16(ImplicitAddress address, RegisterID dest) 616 { 617 if (address.offset >= -32768 && address.offset <= 32767 618 && !m_fixedWidth) 619 m_assembler.lhu(dest, address.base, address.offset); 620 else { 621 /* 622 lui addrTemp, (offset + 0x8000) >> 16 623 addu addrTemp, addrTemp, base 624 lhu dest, (offset & 0xffff)(addrTemp) 625 */ 626 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 627 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 628 m_assembler.lhu(dest, addrTempRegister, address.offset); 629 } 630 } 631 632 /* Need to use zero-extened load half-word for load16. */ load16(BaseIndex address,RegisterID dest)633 void load16(BaseIndex address, RegisterID dest) 634 { 635 if (address.offset >= -32768 && address.offset <= 32767 636 && !m_fixedWidth) { 637 /* 638 sll addrTemp, address.index, address.scale 639 addu addrTemp, addrTemp, address.base 640 lhu dest, address.offset(addrTemp) 641 */ 642 m_assembler.sll(addrTempRegister, address.index, address.scale); 643 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 644 m_assembler.lhu(dest, addrTempRegister, address.offset); 645 } else { 646 /* 647 sll addrTemp, address.index, address.scale 648 addu addrTemp, addrTemp, address.base 649 lui immTemp, (address.offset + 0x8000) >> 16 650 addu addrTemp, addrTemp, immTemp 651 lhu dest, (address.offset & 0xffff)(addrTemp) 652 */ 653 m_assembler.sll(addrTempRegister, address.index, address.scale); 654 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 655 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 656 m_assembler.addu(addrTempRegister, addrTempRegister, 657 immTempRegister); 658 m_assembler.lhu(dest, addrTempRegister, address.offset); 659 } 660 } 661 store32WithAddressOffsetPatch(RegisterID src,Address address)662 DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address) 663 { 664 m_fixedWidth = true; 665 /* 666 lui addrTemp, address.offset >> 16 667 ori addrTemp, addrTemp, address.offset & 0xffff 668 addu addrTemp, addrTemp, address.base 669 sw src, 0(addrTemp) 670 */ 671 DataLabel32 dataLabel(this); 672 move(TrustedImm32(address.offset), addrTempRegister); 673 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 674 m_assembler.sw(src, addrTempRegister, 0); 675 m_fixedWidth = false; 676 return dataLabel; 677 } 678 store32(RegisterID src,ImplicitAddress address)679 void store32(RegisterID src, ImplicitAddress address) 680 { 681 if (address.offset >= -32768 && address.offset <= 32767 682 && !m_fixedWidth) 683 m_assembler.sw(src, address.base, address.offset); 684 else { 685 /* 686 lui addrTemp, (offset + 0x8000) >> 16 687 addu addrTemp, addrTemp, base 688 sw src, (offset & 0xffff)(addrTemp) 689 */ 690 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 691 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 692 m_assembler.sw(src, addrTempRegister, address.offset); 693 } 694 } 695 store32(RegisterID src,BaseIndex address)696 void store32(RegisterID src, BaseIndex address) 697 { 698 if (address.offset >= -32768 && address.offset <= 32767 699 && !m_fixedWidth) { 700 /* 701 sll addrTemp, address.index, address.scale 702 addu addrTemp, addrTemp, address.base 703 sw src, address.offset(addrTemp) 704 */ 705 m_assembler.sll(addrTempRegister, address.index, address.scale); 706 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 707 m_assembler.sw(src, addrTempRegister, address.offset); 708 } else { 709 /* 710 sll addrTemp, address.index, address.scale 711 addu addrTemp, addrTemp, address.base 712 lui immTemp, (address.offset + 0x8000) >> 16 713 addu addrTemp, addrTemp, immTemp 714 sw src, (address.offset & 0xffff)(at) 715 */ 716 m_assembler.sll(addrTempRegister, address.index, address.scale); 717 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 718 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); 719 m_assembler.addu(addrTempRegister, addrTempRegister, 720 immTempRegister); 721 m_assembler.sw(src, addrTempRegister, address.offset); 722 } 723 } 724 store32(TrustedImm32 imm,ImplicitAddress address)725 void store32(TrustedImm32 imm, ImplicitAddress address) 726 { 727 if (address.offset >= -32768 && address.offset <= 32767 728 && !m_fixedWidth) { 729 if (!imm.m_isPointer && !imm.m_value) 730 m_assembler.sw(MIPSRegisters::zero, address.base, 731 address.offset); 732 else { 733 move(imm, immTempRegister); 734 m_assembler.sw(immTempRegister, address.base, address.offset); 735 } 736 } else { 737 /* 738 lui addrTemp, (offset + 0x8000) >> 16 739 addu addrTemp, addrTemp, base 740 sw immTemp, (offset & 0xffff)(addrTemp) 741 */ 742 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 743 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 744 if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) 745 m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 746 address.offset); 747 else { 748 move(imm, immTempRegister); 749 m_assembler.sw(immTempRegister, addrTempRegister, 750 address.offset); 751 } 752 } 753 } 754 store32(RegisterID src,const void * address)755 void store32(RegisterID src, const void* address) 756 { 757 /* 758 li addrTemp, address 759 sw src, 0(addrTemp) 760 */ 761 move(TrustedImmPtr(address), addrTempRegister); 762 m_assembler.sw(src, addrTempRegister, 0); 763 } 764 store32(TrustedImm32 imm,const void * address)765 void store32(TrustedImm32 imm, const void* address) 766 { 767 /* 768 li immTemp, imm 769 li addrTemp, address 770 sw src, 0(addrTemp) 771 */ 772 if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) { 773 move(TrustedImmPtr(address), addrTempRegister); 774 m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0); 775 } else { 776 move(imm, immTempRegister); 777 move(TrustedImmPtr(address), addrTempRegister); 778 m_assembler.sw(immTempRegister, addrTempRegister, 0); 779 } 780 } 781 782 // Floating-point operations: 783 supportsFloatingPoint()784 bool supportsFloatingPoint() const 785 { 786 #if WTF_MIPS_DOUBLE_FLOAT 787 return true; 788 #else 789 return false; 790 #endif 791 } 792 supportsFloatingPointTruncate()793 bool supportsFloatingPointTruncate() const 794 { 795 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2) 796 return true; 797 #else 798 return false; 799 #endif 800 } 801 supportsFloatingPointSqrt()802 bool supportsFloatingPointSqrt() const 803 { 804 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2) 805 return true; 806 #else 807 return false; 808 #endif 809 } 810 811 // Stack manipulation operations: 812 // 813 // The ABI is assumed to provide a stack abstraction to memory, 814 // containing machine word sized units of data. Push and pop 815 // operations add and remove a single register sized unit of data 816 // to or from the stack. Peek and poke operations read or write 817 // values on the stack, without moving the current stack position. 818 pop(RegisterID dest)819 void pop(RegisterID dest) 820 { 821 m_assembler.lw(dest, MIPSRegisters::sp, 0); 822 m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, 4); 823 } 824 push(RegisterID src)825 void push(RegisterID src) 826 { 827 m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, -4); 828 m_assembler.sw(src, MIPSRegisters::sp, 0); 829 } 830 push(Address address)831 void push(Address address) 832 { 833 load32(address, dataTempRegister); 834 push(dataTempRegister); 835 } 836 push(TrustedImm32 imm)837 void push(TrustedImm32 imm) 838 { 839 move(imm, immTempRegister); 840 push(immTempRegister); 841 } 842 843 // Register move operations: 844 // 845 // Move values in registers. 846 move(TrustedImm32 imm,RegisterID dest)847 void move(TrustedImm32 imm, RegisterID dest) 848 { 849 if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) 850 move(MIPSRegisters::zero, dest); 851 else if (imm.m_isPointer || m_fixedWidth) { 852 m_assembler.lui(dest, imm.m_value >> 16); 853 m_assembler.ori(dest, dest, imm.m_value); 854 } else 855 m_assembler.li(dest, imm.m_value); 856 } 857 move(RegisterID src,RegisterID dest)858 void move(RegisterID src, RegisterID dest) 859 { 860 if (src != dest || m_fixedWidth) 861 m_assembler.move(dest, src); 862 } 863 move(TrustedImmPtr imm,RegisterID dest)864 void move(TrustedImmPtr imm, RegisterID dest) 865 { 866 move(TrustedImm32(imm), dest); 867 } 868 swap(RegisterID reg1,RegisterID reg2)869 void swap(RegisterID reg1, RegisterID reg2) 870 { 871 move(reg1, immTempRegister); 872 move(reg2, reg1); 873 move(immTempRegister, reg2); 874 } 875 signExtend32ToPtr(RegisterID src,RegisterID dest)876 void signExtend32ToPtr(RegisterID src, RegisterID dest) 877 { 878 if (src != dest || m_fixedWidth) 879 move(src, dest); 880 } 881 zeroExtend32ToPtr(RegisterID src,RegisterID dest)882 void zeroExtend32ToPtr(RegisterID src, RegisterID dest) 883 { 884 if (src != dest || m_fixedWidth) 885 move(src, dest); 886 } 887 888 // Forwards / external control flow operations: 889 // 890 // This set of jump and conditional branch operations return a Jump 891 // object which may linked at a later point, allow forwards jump, 892 // or jumps that will require external linkage (after the code has been 893 // relocated). 894 // 895 // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge 896 // respecitvely, for unsigned comparisons the names b, a, be, and ae are 897 // used (representing the names 'below' and 'above'). 898 // 899 // Operands to the comparision are provided in the expected order, e.g. 900 // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when 901 // treated as a signed 32bit value, is less than or equal to 5. 902 // 903 // jz and jnz test whether the first operand is equal to zero, and take 904 // an optional second operand of a mask under which to perform the test. 905 branch8(RelationalCondition cond,Address left,TrustedImm32 right)906 Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right) 907 { 908 // Make sure the immediate value is unsigned 8 bits. 909 ASSERT(!(right.m_value & 0xFFFFFF00)); 910 load8(left, dataTempRegister); 911 move(right, immTempRegister); 912 return branch32(cond, dataTempRegister, immTempRegister); 913 } 914 branch32(RelationalCondition cond,RegisterID left,RegisterID right)915 Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right) 916 { 917 if (cond == Equal) 918 return branchEqual(left, right); 919 if (cond == NotEqual) 920 return branchNotEqual(left, right); 921 if (cond == Above) { 922 m_assembler.sltu(cmpTempRegister, right, left); 923 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 924 } 925 if (cond == AboveOrEqual) { 926 m_assembler.sltu(cmpTempRegister, left, right); 927 return branchEqual(cmpTempRegister, MIPSRegisters::zero); 928 } 929 if (cond == Below) { 930 m_assembler.sltu(cmpTempRegister, left, right); 931 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 932 } 933 if (cond == BelowOrEqual) { 934 m_assembler.sltu(cmpTempRegister, right, left); 935 return branchEqual(cmpTempRegister, MIPSRegisters::zero); 936 } 937 if (cond == GreaterThan) { 938 m_assembler.slt(cmpTempRegister, right, left); 939 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 940 } 941 if (cond == GreaterThanOrEqual) { 942 m_assembler.slt(cmpTempRegister, left, right); 943 return branchEqual(cmpTempRegister, MIPSRegisters::zero); 944 } 945 if (cond == LessThan) { 946 m_assembler.slt(cmpTempRegister, left, right); 947 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 948 } 949 if (cond == LessThanOrEqual) { 950 m_assembler.slt(cmpTempRegister, right, left); 951 return branchEqual(cmpTempRegister, MIPSRegisters::zero); 952 } 953 ASSERT(0); 954 955 return Jump(); 956 } 957 branch32(RelationalCondition cond,RegisterID left,TrustedImm32 right)958 Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right) 959 { 960 move(right, immTempRegister); 961 return branch32(cond, left, immTempRegister); 962 } 963 branch32(RelationalCondition cond,RegisterID left,Address right)964 Jump branch32(RelationalCondition cond, RegisterID left, Address right) 965 { 966 load32(right, dataTempRegister); 967 return branch32(cond, left, dataTempRegister); 968 } 969 branch32(RelationalCondition cond,Address left,RegisterID right)970 Jump branch32(RelationalCondition cond, Address left, RegisterID right) 971 { 972 load32(left, dataTempRegister); 973 return branch32(cond, dataTempRegister, right); 974 } 975 branch32(RelationalCondition cond,Address left,TrustedImm32 right)976 Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right) 977 { 978 load32(left, dataTempRegister); 979 move(right, immTempRegister); 980 return branch32(cond, dataTempRegister, immTempRegister); 981 } 982 branch32(RelationalCondition cond,BaseIndex left,TrustedImm32 right)983 Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right) 984 { 985 load32(left, dataTempRegister); 986 // Be careful that the previous load32() uses immTempRegister. 987 // So, we need to put move() after load32(). 988 move(right, immTempRegister); 989 return branch32(cond, dataTempRegister, immTempRegister); 990 } 991 branch32WithUnalignedHalfWords(RelationalCondition cond,BaseIndex left,TrustedImm32 right)992 Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right) 993 { 994 load32WithUnalignedHalfWords(left, dataTempRegister); 995 // Be careful that the previous load32WithUnalignedHalfWords() 996 // uses immTempRegister. 997 // So, we need to put move() after load32WithUnalignedHalfWords(). 998 move(right, immTempRegister); 999 return branch32(cond, dataTempRegister, immTempRegister); 1000 } 1001 branch32(RelationalCondition cond,AbsoluteAddress left,RegisterID right)1002 Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right) 1003 { 1004 load32(left.m_ptr, dataTempRegister); 1005 return branch32(cond, dataTempRegister, right); 1006 } 1007 branch32(RelationalCondition cond,AbsoluteAddress left,TrustedImm32 right)1008 Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right) 1009 { 1010 load32(left.m_ptr, dataTempRegister); 1011 move(right, immTempRegister); 1012 return branch32(cond, dataTempRegister, immTempRegister); 1013 } 1014 branch16(RelationalCondition cond,BaseIndex left,RegisterID right)1015 Jump branch16(RelationalCondition cond, BaseIndex left, RegisterID right) 1016 { 1017 load16(left, dataTempRegister); 1018 return branch32(cond, dataTempRegister, right); 1019 } 1020 branch16(RelationalCondition cond,BaseIndex left,TrustedImm32 right)1021 Jump branch16(RelationalCondition cond, BaseIndex left, TrustedImm32 right) 1022 { 1023 ASSERT(!(right.m_value & 0xFFFF0000)); 1024 load16(left, dataTempRegister); 1025 // Be careful that the previous load16() uses immTempRegister. 1026 // So, we need to put move() after load16(). 1027 move(right, immTempRegister); 1028 return branch32(cond, dataTempRegister, immTempRegister); 1029 } 1030 branchTest32(ResultCondition cond,RegisterID reg,RegisterID mask)1031 Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask) 1032 { 1033 ASSERT((cond == Zero) || (cond == NonZero)); 1034 m_assembler.andInsn(cmpTempRegister, reg, mask); 1035 if (cond == Zero) 1036 return branchEqual(cmpTempRegister, MIPSRegisters::zero); 1037 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1038 } 1039 1040 Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) 1041 { 1042 ASSERT((cond == Zero) || (cond == NonZero)); 1043 if (mask.m_value == -1 && !m_fixedWidth) { 1044 if (cond == Zero) 1045 return branchEqual(reg, MIPSRegisters::zero); 1046 return branchNotEqual(reg, MIPSRegisters::zero); 1047 } 1048 move(mask, immTempRegister); 1049 return branchTest32(cond, reg, immTempRegister); 1050 } 1051 1052 Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) 1053 { 1054 load32(address, dataTempRegister); 1055 return branchTest32(cond, dataTempRegister, mask); 1056 } 1057 1058 Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) 1059 { 1060 load32(address, dataTempRegister); 1061 return branchTest32(cond, dataTempRegister, mask); 1062 } 1063 1064 Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) 1065 { 1066 load8(address, dataTempRegister); 1067 return branchTest32(cond, dataTempRegister, mask); 1068 } 1069 jump()1070 Jump jump() 1071 { 1072 return branchEqual(MIPSRegisters::zero, MIPSRegisters::zero); 1073 } 1074 jump(RegisterID target)1075 void jump(RegisterID target) 1076 { 1077 m_assembler.jr(target); 1078 m_assembler.nop(); 1079 } 1080 jump(Address address)1081 void jump(Address address) 1082 { 1083 m_fixedWidth = true; 1084 load32(address, MIPSRegisters::t9); 1085 m_assembler.jr(MIPSRegisters::t9); 1086 m_assembler.nop(); 1087 m_fixedWidth = false; 1088 } 1089 1090 // Arithmetic control flow operations: 1091 // 1092 // This set of conditional branch operations branch based 1093 // on the result of an arithmetic operation. The operation 1094 // is performed as normal, storing the result. 1095 // 1096 // * jz operations branch if the result is zero. 1097 // * jo operations branch if the (signed) arithmetic 1098 // operation caused an overflow to occur. 1099 branchAdd32(ResultCondition cond,RegisterID src,RegisterID dest)1100 Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest) 1101 { 1102 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1103 if (cond == Overflow) { 1104 /* 1105 move dest, dataTemp 1106 xor cmpTemp, dataTemp, src 1107 bltz cmpTemp, No_overflow # diff sign bit -> no overflow 1108 addu dest, dataTemp, src 1109 xor cmpTemp, dest, dataTemp 1110 bgez cmpTemp, No_overflow # same sign big -> no overflow 1111 nop 1112 b Overflow 1113 nop 1114 nop 1115 nop 1116 nop 1117 nop 1118 No_overflow: 1119 */ 1120 move(dest, dataTempRegister); 1121 m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src); 1122 m_assembler.bltz(cmpTempRegister, 10); 1123 m_assembler.addu(dest, dataTempRegister, src); 1124 m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister); 1125 m_assembler.bgez(cmpTempRegister, 7); 1126 m_assembler.nop(); 1127 return jump(); 1128 } 1129 if (cond == Signed) { 1130 add32(src, dest); 1131 // Check if dest is negative. 1132 m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); 1133 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1134 } 1135 if (cond == Zero) { 1136 add32(src, dest); 1137 return branchEqual(dest, MIPSRegisters::zero); 1138 } 1139 if (cond == NonZero) { 1140 add32(src, dest); 1141 return branchNotEqual(dest, MIPSRegisters::zero); 1142 } 1143 ASSERT(0); 1144 return Jump(); 1145 } 1146 branchAdd32(ResultCondition cond,TrustedImm32 imm,RegisterID dest)1147 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) 1148 { 1149 move(imm, immTempRegister); 1150 return branchAdd32(cond, immTempRegister, dest); 1151 } 1152 branchMul32(ResultCondition cond,RegisterID src,RegisterID dest)1153 Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest) 1154 { 1155 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1156 if (cond == Overflow) { 1157 /* 1158 mult src, dest 1159 mfhi dataTemp 1160 mflo dest 1161 sra addrTemp, dest, 31 1162 beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow 1163 nop 1164 b Overflow 1165 nop 1166 nop 1167 nop 1168 nop 1169 nop 1170 No_overflow: 1171 */ 1172 m_assembler.mult(src, dest); 1173 m_assembler.mfhi(dataTempRegister); 1174 m_assembler.mflo(dest); 1175 m_assembler.sra(addrTempRegister, dest, 31); 1176 m_assembler.beq(dataTempRegister, addrTempRegister, 7); 1177 m_assembler.nop(); 1178 return jump(); 1179 } 1180 if (cond == Signed) { 1181 mul32(src, dest); 1182 // Check if dest is negative. 1183 m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); 1184 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1185 } 1186 if (cond == Zero) { 1187 mul32(src, dest); 1188 return branchEqual(dest, MIPSRegisters::zero); 1189 } 1190 if (cond == NonZero) { 1191 mul32(src, dest); 1192 return branchNotEqual(dest, MIPSRegisters::zero); 1193 } 1194 ASSERT(0); 1195 return Jump(); 1196 } 1197 branchMul32(ResultCondition cond,TrustedImm32 imm,RegisterID src,RegisterID dest)1198 Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest) 1199 { 1200 move(imm, immTempRegister); 1201 move(src, dest); 1202 return branchMul32(cond, immTempRegister, dest); 1203 } 1204 branchSub32(ResultCondition cond,RegisterID src,RegisterID dest)1205 Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest) 1206 { 1207 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); 1208 if (cond == Overflow) { 1209 /* 1210 move dest, dataTemp 1211 xor cmpTemp, dataTemp, src 1212 bgez cmpTemp, No_overflow # same sign bit -> no overflow 1213 subu dest, dataTemp, src 1214 xor cmpTemp, dest, dataTemp 1215 bgez cmpTemp, No_overflow # same sign bit -> no overflow 1216 nop 1217 b Overflow 1218 nop 1219 nop 1220 nop 1221 nop 1222 nop 1223 No_overflow: 1224 */ 1225 move(dest, dataTempRegister); 1226 m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src); 1227 m_assembler.bgez(cmpTempRegister, 10); 1228 m_assembler.subu(dest, dataTempRegister, src); 1229 m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister); 1230 m_assembler.bgez(cmpTempRegister, 7); 1231 m_assembler.nop(); 1232 return jump(); 1233 } 1234 if (cond == Signed) { 1235 sub32(src, dest); 1236 // Check if dest is negative. 1237 m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); 1238 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1239 } 1240 if (cond == Zero) { 1241 sub32(src, dest); 1242 return branchEqual(dest, MIPSRegisters::zero); 1243 } 1244 if (cond == NonZero) { 1245 sub32(src, dest); 1246 return branchNotEqual(dest, MIPSRegisters::zero); 1247 } 1248 ASSERT(0); 1249 return Jump(); 1250 } 1251 branchSub32(ResultCondition cond,TrustedImm32 imm,RegisterID dest)1252 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) 1253 { 1254 move(imm, immTempRegister); 1255 return branchSub32(cond, immTempRegister, dest); 1256 } 1257 branchOr32(ResultCondition cond,RegisterID src,RegisterID dest)1258 Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest) 1259 { 1260 ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero)); 1261 if (cond == Signed) { 1262 or32(src, dest); 1263 // Check if dest is negative. 1264 m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); 1265 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); 1266 } 1267 if (cond == Zero) { 1268 or32(src, dest); 1269 return branchEqual(dest, MIPSRegisters::zero); 1270 } 1271 if (cond == NonZero) { 1272 or32(src, dest); 1273 return branchNotEqual(dest, MIPSRegisters::zero); 1274 } 1275 ASSERT(0); 1276 return Jump(); 1277 } 1278 1279 // Miscellaneous operations: 1280 breakpoint()1281 void breakpoint() 1282 { 1283 m_assembler.bkpt(); 1284 } 1285 nearCall()1286 Call nearCall() 1287 { 1288 /* We need two words for relaxation. */ 1289 m_assembler.nop(); 1290 m_assembler.nop(); 1291 m_assembler.jal(); 1292 m_assembler.nop(); 1293 return Call(m_assembler.label(), Call::LinkableNear); 1294 } 1295 call()1296 Call call() 1297 { 1298 m_assembler.lui(MIPSRegisters::t9, 0); 1299 m_assembler.ori(MIPSRegisters::t9, MIPSRegisters::t9, 0); 1300 m_assembler.jalr(MIPSRegisters::t9); 1301 m_assembler.nop(); 1302 return Call(m_assembler.label(), Call::Linkable); 1303 } 1304 call(RegisterID target)1305 Call call(RegisterID target) 1306 { 1307 m_assembler.jalr(target); 1308 m_assembler.nop(); 1309 return Call(m_assembler.label(), Call::None); 1310 } 1311 call(Address address)1312 Call call(Address address) 1313 { 1314 m_fixedWidth = true; 1315 load32(address, MIPSRegisters::t9); 1316 m_assembler.jalr(MIPSRegisters::t9); 1317 m_assembler.nop(); 1318 m_fixedWidth = false; 1319 return Call(m_assembler.label(), Call::None); 1320 } 1321 ret()1322 void ret() 1323 { 1324 m_assembler.jr(MIPSRegisters::ra); 1325 m_assembler.nop(); 1326 } 1327 compare32(RelationalCondition cond,RegisterID left,RegisterID right,RegisterID dest)1328 void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest) 1329 { 1330 if (cond == Equal) { 1331 m_assembler.xorInsn(dest, left, right); 1332 m_assembler.sltiu(dest, dest, 1); 1333 } else if (cond == NotEqual) { 1334 m_assembler.xorInsn(dest, left, right); 1335 m_assembler.sltu(dest, MIPSRegisters::zero, dest); 1336 } else if (cond == Above) 1337 m_assembler.sltu(dest, right, left); 1338 else if (cond == AboveOrEqual) { 1339 m_assembler.sltu(dest, left, right); 1340 m_assembler.xori(dest, dest, 1); 1341 } else if (cond == Below) 1342 m_assembler.sltu(dest, left, right); 1343 else if (cond == BelowOrEqual) { 1344 m_assembler.sltu(dest, right, left); 1345 m_assembler.xori(dest, dest, 1); 1346 } else if (cond == GreaterThan) 1347 m_assembler.slt(dest, right, left); 1348 else if (cond == GreaterThanOrEqual) { 1349 m_assembler.slt(dest, left, right); 1350 m_assembler.xori(dest, dest, 1); 1351 } else if (cond == LessThan) 1352 m_assembler.slt(dest, left, right); 1353 else if (cond == LessThanOrEqual) { 1354 m_assembler.slt(dest, right, left); 1355 m_assembler.xori(dest, dest, 1); 1356 } 1357 } 1358 compare32(RelationalCondition cond,RegisterID left,TrustedImm32 right,RegisterID dest)1359 void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest) 1360 { 1361 move(right, immTempRegister); 1362 compare32(cond, left, immTempRegister, dest); 1363 } 1364 test8(ResultCondition cond,Address address,TrustedImm32 mask,RegisterID dest)1365 void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest) 1366 { 1367 ASSERT((cond == Zero) || (cond == NonZero)); 1368 load8(address, dataTempRegister); 1369 if (mask.m_value == -1 && !m_fixedWidth) { 1370 if (cond == Zero) 1371 m_assembler.sltiu(dest, dataTempRegister, 1); 1372 else 1373 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister); 1374 } else { 1375 move(mask, immTempRegister); 1376 m_assembler.andInsn(cmpTempRegister, dataTempRegister, 1377 immTempRegister); 1378 if (cond == Zero) 1379 m_assembler.sltiu(dest, cmpTempRegister, 1); 1380 else 1381 m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister); 1382 } 1383 } 1384 test32(ResultCondition cond,Address address,TrustedImm32 mask,RegisterID dest)1385 void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest) 1386 { 1387 ASSERT((cond == Zero) || (cond == NonZero)); 1388 load32(address, dataTempRegister); 1389 if (mask.m_value == -1 && !m_fixedWidth) { 1390 if (cond == Zero) 1391 m_assembler.sltiu(dest, dataTempRegister, 1); 1392 else 1393 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister); 1394 } else { 1395 move(mask, immTempRegister); 1396 m_assembler.andInsn(cmpTempRegister, dataTempRegister, 1397 immTempRegister); 1398 if (cond == Zero) 1399 m_assembler.sltiu(dest, cmpTempRegister, 1); 1400 else 1401 m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister); 1402 } 1403 } 1404 moveWithPatch(TrustedImm32 imm,RegisterID dest)1405 DataLabel32 moveWithPatch(TrustedImm32 imm, RegisterID dest) 1406 { 1407 m_fixedWidth = true; 1408 DataLabel32 label(this); 1409 move(imm, dest); 1410 m_fixedWidth = false; 1411 return label; 1412 } 1413 moveWithPatch(TrustedImmPtr initialValue,RegisterID dest)1414 DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest) 1415 { 1416 m_fixedWidth = true; 1417 DataLabelPtr label(this); 1418 move(initialValue, dest); 1419 m_fixedWidth = false; 1420 return label; 1421 } 1422 1423 Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) 1424 { 1425 m_fixedWidth = true; 1426 dataLabel = moveWithPatch(initialRightValue, immTempRegister); 1427 Jump temp = branch32(cond, left, immTempRegister); 1428 m_fixedWidth = false; 1429 return temp; 1430 } 1431 1432 Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) 1433 { 1434 m_fixedWidth = true; 1435 load32(left, dataTempRegister); 1436 dataLabel = moveWithPatch(initialRightValue, immTempRegister); 1437 Jump temp = branch32(cond, dataTempRegister, immTempRegister); 1438 m_fixedWidth = false; 1439 return temp; 1440 } 1441 storePtrWithPatch(TrustedImmPtr initialValue,ImplicitAddress address)1442 DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address) 1443 { 1444 m_fixedWidth = true; 1445 DataLabelPtr dataLabel = moveWithPatch(initialValue, dataTempRegister); 1446 store32(dataTempRegister, address); 1447 m_fixedWidth = false; 1448 return dataLabel; 1449 } 1450 storePtrWithPatch(ImplicitAddress address)1451 DataLabelPtr storePtrWithPatch(ImplicitAddress address) 1452 { 1453 return storePtrWithPatch(TrustedImmPtr(0), address); 1454 } 1455 tailRecursiveCall()1456 Call tailRecursiveCall() 1457 { 1458 // Like a normal call, but don't update the returned address register 1459 m_fixedWidth = true; 1460 move(TrustedImm32(0), MIPSRegisters::t9); 1461 m_assembler.jr(MIPSRegisters::t9); 1462 m_assembler.nop(); 1463 m_fixedWidth = false; 1464 return Call(m_assembler.label(), Call::Linkable); 1465 } 1466 makeTailRecursiveCall(Jump oldJump)1467 Call makeTailRecursiveCall(Jump oldJump) 1468 { 1469 oldJump.link(this); 1470 return tailRecursiveCall(); 1471 } 1472 loadDouble(ImplicitAddress address,FPRegisterID dest)1473 void loadDouble(ImplicitAddress address, FPRegisterID dest) 1474 { 1475 #if WTF_MIPS_ISA(1) 1476 /* 1477 li addrTemp, address.offset 1478 addu addrTemp, addrTemp, base 1479 lwc1 dest, 0(addrTemp) 1480 lwc1 dest+1, 4(addrTemp) 1481 */ 1482 move(TrustedImm32(address.offset), addrTempRegister); 1483 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1484 m_assembler.lwc1(dest, addrTempRegister, 0); 1485 m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4); 1486 #else 1487 if (address.offset >= -32768 && address.offset <= 32767 1488 && !m_fixedWidth) { 1489 m_assembler.ldc1(dest, address.base, address.offset); 1490 } else { 1491 /* 1492 lui addrTemp, (offset + 0x8000) >> 16 1493 addu addrTemp, addrTemp, base 1494 ldc1 dest, (offset & 0xffff)(addrTemp) 1495 */ 1496 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 1497 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1498 m_assembler.ldc1(dest, addrTempRegister, address.offset); 1499 } 1500 #endif 1501 } 1502 loadDouble(const void * address,FPRegisterID dest)1503 void loadDouble(const void* address, FPRegisterID dest) 1504 { 1505 #if WTF_MIPS_ISA(1) 1506 /* 1507 li addrTemp, address 1508 lwc1 dest, 0(addrTemp) 1509 lwc1 dest+1, 4(addrTemp) 1510 */ 1511 move(TrustedImmPtr(address), addrTempRegister); 1512 m_assembler.lwc1(dest, addrTempRegister, 0); 1513 m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4); 1514 #else 1515 /* 1516 li addrTemp, address 1517 ldc1 dest, 0(addrTemp) 1518 */ 1519 move(TrustedImmPtr(address), addrTempRegister); 1520 m_assembler.ldc1(dest, addrTempRegister, 0); 1521 #endif 1522 } 1523 1524 storeDouble(FPRegisterID src,ImplicitAddress address)1525 void storeDouble(FPRegisterID src, ImplicitAddress address) 1526 { 1527 #if WTF_MIPS_ISA(1) 1528 /* 1529 li addrTemp, address.offset 1530 addu addrTemp, addrTemp, base 1531 swc1 dest, 0(addrTemp) 1532 swc1 dest+1, 4(addrTemp) 1533 */ 1534 move(TrustedImm32(address.offset), addrTempRegister); 1535 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1536 m_assembler.swc1(src, addrTempRegister, 0); 1537 m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4); 1538 #else 1539 if (address.offset >= -32768 && address.offset <= 32767 1540 && !m_fixedWidth) 1541 m_assembler.sdc1(src, address.base, address.offset); 1542 else { 1543 /* 1544 lui addrTemp, (offset + 0x8000) >> 16 1545 addu addrTemp, addrTemp, base 1546 sdc1 src, (offset & 0xffff)(addrTemp) 1547 */ 1548 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); 1549 m_assembler.addu(addrTempRegister, addrTempRegister, address.base); 1550 m_assembler.sdc1(src, addrTempRegister, address.offset); 1551 } 1552 #endif 1553 } 1554 addDouble(FPRegisterID src,FPRegisterID dest)1555 void addDouble(FPRegisterID src, FPRegisterID dest) 1556 { 1557 m_assembler.addd(dest, dest, src); 1558 } 1559 addDouble(Address src,FPRegisterID dest)1560 void addDouble(Address src, FPRegisterID dest) 1561 { 1562 loadDouble(src, fpTempRegister); 1563 m_assembler.addd(dest, dest, fpTempRegister); 1564 } 1565 subDouble(FPRegisterID src,FPRegisterID dest)1566 void subDouble(FPRegisterID src, FPRegisterID dest) 1567 { 1568 m_assembler.subd(dest, dest, src); 1569 } 1570 subDouble(Address src,FPRegisterID dest)1571 void subDouble(Address src, FPRegisterID dest) 1572 { 1573 loadDouble(src, fpTempRegister); 1574 m_assembler.subd(dest, dest, fpTempRegister); 1575 } 1576 mulDouble(FPRegisterID src,FPRegisterID dest)1577 void mulDouble(FPRegisterID src, FPRegisterID dest) 1578 { 1579 m_assembler.muld(dest, dest, src); 1580 } 1581 mulDouble(Address src,FPRegisterID dest)1582 void mulDouble(Address src, FPRegisterID dest) 1583 { 1584 loadDouble(src, fpTempRegister); 1585 m_assembler.muld(dest, dest, fpTempRegister); 1586 } 1587 divDouble(FPRegisterID src,FPRegisterID dest)1588 void divDouble(FPRegisterID src, FPRegisterID dest) 1589 { 1590 m_assembler.divd(dest, dest, src); 1591 } 1592 convertInt32ToDouble(RegisterID src,FPRegisterID dest)1593 void convertInt32ToDouble(RegisterID src, FPRegisterID dest) 1594 { 1595 m_assembler.mtc1(src, fpTempRegister); 1596 m_assembler.cvtdw(dest, fpTempRegister); 1597 } 1598 convertInt32ToDouble(Address src,FPRegisterID dest)1599 void convertInt32ToDouble(Address src, FPRegisterID dest) 1600 { 1601 load32(src, dataTempRegister); 1602 m_assembler.mtc1(dataTempRegister, fpTempRegister); 1603 m_assembler.cvtdw(dest, fpTempRegister); 1604 } 1605 convertInt32ToDouble(AbsoluteAddress src,FPRegisterID dest)1606 void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest) 1607 { 1608 load32(src.m_ptr, dataTempRegister); 1609 m_assembler.mtc1(dataTempRegister, fpTempRegister); 1610 m_assembler.cvtdw(dest, fpTempRegister); 1611 } 1612 insertRelaxationWords()1613 void insertRelaxationWords() 1614 { 1615 /* We need four words for relaxation. */ 1616 m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 3); // Jump over nops; 1617 m_assembler.nop(); 1618 m_assembler.nop(); 1619 m_assembler.nop(); 1620 } 1621 branchTrue()1622 Jump branchTrue() 1623 { 1624 m_assembler.appendJump(); 1625 m_assembler.bc1t(); 1626 m_assembler.nop(); 1627 insertRelaxationWords(); 1628 return Jump(m_assembler.label()); 1629 } 1630 branchFalse()1631 Jump branchFalse() 1632 { 1633 m_assembler.appendJump(); 1634 m_assembler.bc1f(); 1635 m_assembler.nop(); 1636 insertRelaxationWords(); 1637 return Jump(m_assembler.label()); 1638 } 1639 branchEqual(RegisterID rs,RegisterID rt)1640 Jump branchEqual(RegisterID rs, RegisterID rt) 1641 { 1642 m_assembler.appendJump(); 1643 m_assembler.beq(rs, rt, 0); 1644 m_assembler.nop(); 1645 insertRelaxationWords(); 1646 return Jump(m_assembler.label()); 1647 } 1648 branchNotEqual(RegisterID rs,RegisterID rt)1649 Jump branchNotEqual(RegisterID rs, RegisterID rt) 1650 { 1651 m_assembler.appendJump(); 1652 m_assembler.bne(rs, rt, 0); 1653 m_assembler.nop(); 1654 insertRelaxationWords(); 1655 return Jump(m_assembler.label()); 1656 } 1657 branchDouble(DoubleCondition cond,FPRegisterID left,FPRegisterID right)1658 Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right) 1659 { 1660 if (cond == DoubleEqual) { 1661 m_assembler.ceqd(left, right); 1662 return branchTrue(); 1663 } 1664 if (cond == DoubleNotEqual) { 1665 m_assembler.cueqd(left, right); 1666 return branchFalse(); // false 1667 } 1668 if (cond == DoubleGreaterThan) { 1669 m_assembler.cngtd(left, right); 1670 return branchFalse(); // false 1671 } 1672 if (cond == DoubleGreaterThanOrEqual) { 1673 m_assembler.cnged(left, right); 1674 return branchFalse(); // false 1675 } 1676 if (cond == DoubleLessThan) { 1677 m_assembler.cltd(left, right); 1678 return branchTrue(); 1679 } 1680 if (cond == DoubleLessThanOrEqual) { 1681 m_assembler.cled(left, right); 1682 return branchTrue(); 1683 } 1684 if (cond == DoubleEqualOrUnordered) { 1685 m_assembler.cueqd(left, right); 1686 return branchTrue(); 1687 } 1688 if (cond == DoubleNotEqualOrUnordered) { 1689 m_assembler.ceqd(left, right); 1690 return branchFalse(); // false 1691 } 1692 if (cond == DoubleGreaterThanOrUnordered) { 1693 m_assembler.coled(left, right); 1694 return branchFalse(); // false 1695 } 1696 if (cond == DoubleGreaterThanOrEqualOrUnordered) { 1697 m_assembler.coltd(left, right); 1698 return branchFalse(); // false 1699 } 1700 if (cond == DoubleLessThanOrUnordered) { 1701 m_assembler.cultd(left, right); 1702 return branchTrue(); 1703 } 1704 if (cond == DoubleLessThanOrEqualOrUnordered) { 1705 m_assembler.culed(left, right); 1706 return branchTrue(); 1707 } 1708 ASSERT(0); 1709 1710 return Jump(); 1711 } 1712 1713 // Truncates 'src' to an integer, and places the resulting 'dest'. 1714 // If the result is not representable as a 32 bit value, branch. 1715 // May also branch for some values that are representable in 32 bits 1716 // (specifically, in this case, INT_MAX 0x7fffffff). branchTruncateDoubleToInt32(FPRegisterID src,RegisterID dest)1717 Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest) 1718 { 1719 m_assembler.truncwd(fpTempRegister, src); 1720 m_assembler.mfc1(dest, fpTempRegister); 1721 return branch32(Equal, dest, TrustedImm32(0x7fffffff)); 1722 } 1723 1724 // Convert 'src' to an integer, and places the resulting 'dest'. 1725 // If the result is not representable as a 32 bit value, branch. 1726 // May also branch for some values that are representable in 32 bits 1727 // (specifically, in this case, 0). branchConvertDoubleToInt32(FPRegisterID src,RegisterID dest,JumpList & failureCases,FPRegisterID fpTemp)1728 void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp) 1729 { 1730 m_assembler.cvtwd(fpTempRegister, src); 1731 m_assembler.mfc1(dest, fpTempRegister); 1732 1733 // If the result is zero, it might have been -0.0, and the double comparison won't catch this! 1734 failureCases.append(branch32(Equal, dest, MIPSRegisters::zero)); 1735 1736 // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump. 1737 convertInt32ToDouble(dest, fpTemp); 1738 failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fpTemp, src)); 1739 } 1740 branchDoubleNonZero(FPRegisterID reg,FPRegisterID scratch)1741 Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch) 1742 { 1743 #if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64 1744 m_assembler.mtc1(MIPSRegisters::zero, scratch); 1745 m_assembler.mthc1(MIPSRegisters::zero, scratch); 1746 #else 1747 m_assembler.mtc1(MIPSRegisters::zero, scratch); 1748 m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1)); 1749 #endif 1750 return branchDouble(DoubleNotEqual, reg, scratch); 1751 } 1752 branchDoubleZeroOrNaN(FPRegisterID reg,FPRegisterID scratch)1753 Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch) 1754 { 1755 #if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64 1756 m_assembler.mtc1(MIPSRegisters::zero, scratch); 1757 m_assembler.mthc1(MIPSRegisters::zero, scratch); 1758 #else 1759 m_assembler.mtc1(MIPSRegisters::zero, scratch); 1760 m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1)); 1761 #endif 1762 return branchDouble(DoubleEqualOrUnordered, reg, scratch); 1763 } 1764 1765 1766 private: 1767 // If m_fixedWidth is true, we will generate a fixed number of instructions. 1768 // Otherwise, we can emit any number of instructions. 1769 bool m_fixedWidth; 1770 1771 friend class LinkBuffer; 1772 friend class RepatchBuffer; 1773 linkCall(void * code,Call call,FunctionPtr function)1774 static void linkCall(void* code, Call call, FunctionPtr function) 1775 { 1776 MIPSAssembler::linkCall(code, call.m_jmp, function.value()); 1777 } 1778 repatchCall(CodeLocationCall call,CodeLocationLabel destination)1779 static void repatchCall(CodeLocationCall call, CodeLocationLabel destination) 1780 { 1781 MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress()); 1782 } 1783 repatchCall(CodeLocationCall call,FunctionPtr destination)1784 static void repatchCall(CodeLocationCall call, FunctionPtr destination) 1785 { 1786 MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress()); 1787 } 1788 1789 }; 1790 1791 } 1792 1793 #endif // ENABLE(ASSEMBLER) && CPU(MIPS) 1794 1795 #endif // MacroAssemblerMIPS_h 1796