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