2 * Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 MIPS Technologies, Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
27 #ifndef MacroAssemblerMIPS_h
28 #define MacroAssemblerMIPS_h
30 #if ENABLE(ASSEMBLER) && CPU(MIPS)
32 #include "AbstractMacroAssembler.h"
33 #include "MIPSAssembler.h"
37 class MacroAssemblerMIPS
: public AbstractMacroAssembler
<MIPSAssembler
, MacroAssemblerMIPS
> {
39 typedef MIPSRegisters::FPRegisterID FPRegisterID
;
46 static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value
)
48 return value
>= -2147483647 - 1 && value
<= 2147483647;
51 static const Scale ScalePtr
= TimesFour
;
53 // For storing immediate number
54 static const RegisterID immTempRegister
= MIPSRegisters::t0
;
55 // For storing data loaded from the memory
56 static const RegisterID dataTempRegister
= MIPSRegisters::t1
;
57 // For storing address base
58 static const RegisterID addrTempRegister
= MIPSRegisters::t2
;
59 // For storing compare result
60 static const RegisterID cmpTempRegister
= MIPSRegisters::t3
;
63 static const FPRegisterID fpTempRegister
= MIPSRegisters::f16
;
65 static const int MaximumCompactPtrAlignedAddressOffset
= 0x7FFFFFFF;
67 enum RelationalCondition
{
80 enum ResultCondition
{
88 enum DoubleCondition
{
92 DoubleGreaterThanOrEqual
,
94 DoubleLessThanOrEqual
,
95 DoubleEqualOrUnordered
,
96 DoubleNotEqualOrUnordered
,
97 DoubleGreaterThanOrUnordered
,
98 DoubleGreaterThanOrEqualOrUnordered
,
99 DoubleLessThanOrUnordered
,
100 DoubleLessThanOrEqualOrUnordered
103 static const RegisterID stackPointerRegister
= MIPSRegisters::sp
;
104 static const RegisterID framePointerRegister
= MIPSRegisters::fp
;
105 static const RegisterID returnAddressRegister
= MIPSRegisters::ra
;
107 // Integer arithmetic operations:
109 // Operations are typically two operand - operation(source, srcDst)
110 // For many operations the source may be an TrustedImm32, the srcDst operand
111 // may often be a memory location (explictly described using an Address
114 void add32(RegisterID src
, RegisterID dest
)
116 m_assembler
.addu(dest
, dest
, src
);
119 void add32(RegisterID op1
, RegisterID op2
, RegisterID dest
)
121 m_assembler
.addu(dest
, op1
, op2
);
124 void add32(TrustedImm32 imm
, RegisterID dest
)
126 add32(imm
, dest
, dest
);
129 void add32(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
131 if (imm
.m_value
>= -32768 && imm
.m_value
<= 32767
136 m_assembler
.addiu(dest
, src
, imm
.m_value
);
140 addu dest, src, immTemp
142 move(imm
, immTempRegister
);
143 m_assembler
.addu(dest
, src
, immTempRegister
);
147 void add32(RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
149 add32(imm
, src
, dest
);
152 void add32(TrustedImm32 imm
, Address address
)
154 if (address
.offset
>= -32768 && address
.offset
<= 32767
157 lw dataTemp, offset(base)
159 addu dataTemp, dataTemp, immTemp
160 sw dataTemp, offset(base)
162 m_assembler
.lw(dataTempRegister
, address
.base
, address
.offset
);
163 if (imm
.m_value
>= -32768 && imm
.m_value
<= 32767
165 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, imm
.m_value
);
167 move(imm
, immTempRegister
);
168 m_assembler
.addu(dataTempRegister
, dataTempRegister
, immTempRegister
);
170 m_assembler
.sw(dataTempRegister
, address
.base
, address
.offset
);
173 lui addrTemp, (offset + 0x8000) >> 16
174 addu addrTemp, addrTemp, base
175 lw dataTemp, (offset & 0xffff)(addrTemp)
177 addu dataTemp, dataTemp, immTemp
178 sw dataTemp, (offset & 0xffff)(addrTemp)
180 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
181 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
182 m_assembler
.lw(dataTempRegister
, addrTempRegister
, address
.offset
);
184 if (imm
.m_value
>= -32768 && imm
.m_value
<= 32767 && !m_fixedWidth
)
185 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, imm
.m_value
);
187 move(imm
, immTempRegister
);
188 m_assembler
.addu(dataTempRegister
, dataTempRegister
, immTempRegister
);
190 m_assembler
.sw(dataTempRegister
, addrTempRegister
, address
.offset
);
194 void add32(Address src
, RegisterID dest
)
196 load32(src
, dataTempRegister
);
197 add32(dataTempRegister
, dest
);
200 void add32(AbsoluteAddress src
, RegisterID dest
)
202 load32(src
.m_ptr
, dataTempRegister
);
203 add32(dataTempRegister
, dest
);
206 void add32(RegisterID src
, Address dest
)
208 if (dest
.offset
>= -32768 && dest
.offset
<= 32767 && !m_fixedWidth
) {
210 lw dataTemp, offset(base)
211 addu dataTemp, dataTemp, src
212 sw dataTemp, offset(base)
214 m_assembler
.lw(dataTempRegister
, dest
.base
, dest
.offset
);
215 m_assembler
.addu(dataTempRegister
, dataTempRegister
, src
);
216 m_assembler
.sw(dataTempRegister
, dest
.base
, dest
.offset
);
219 lui addrTemp, (offset + 0x8000) >> 16
220 addu addrTemp, addrTemp, base
221 lw dataTemp, (offset & 0xffff)(addrTemp)
222 addu dataTemp, dataTemp, src
223 sw dataTemp, (offset & 0xffff)(addrTemp)
225 m_assembler
.lui(addrTempRegister
, (dest
.offset
+ 0x8000) >> 16);
226 m_assembler
.addu(addrTempRegister
, addrTempRegister
, dest
.base
);
227 m_assembler
.lw(dataTempRegister
, addrTempRegister
, dest
.offset
);
228 m_assembler
.addu(dataTempRegister
, dataTempRegister
, src
);
229 m_assembler
.sw(dataTempRegister
, addrTempRegister
, dest
.offset
);
233 void add32(TrustedImm32 imm
, AbsoluteAddress address
)
238 lw cmpTemp, 0(addrTemp)
239 addu dataTemp, cmpTemp, immTemp
240 sw dataTemp, 0(addrTemp)
242 move(TrustedImmPtr(address
.m_ptr
), addrTempRegister
);
243 m_assembler
.lw(cmpTempRegister
, addrTempRegister
, 0);
244 if (imm
.m_value
>= -32768 && imm
.m_value
<= 32767 && !m_fixedWidth
)
245 m_assembler
.addiu(dataTempRegister
, cmpTempRegister
, imm
.m_value
);
247 move(imm
, immTempRegister
);
248 m_assembler
.addu(dataTempRegister
, cmpTempRegister
, immTempRegister
);
250 m_assembler
.sw(dataTempRegister
, addrTempRegister
, 0);
253 void add64(TrustedImm32 imm
, AbsoluteAddress address
)
257 sltu immTemp, dataTemp, cmpTemp # set carry-in bit
258 lw dataTemp, 4(addrTemp)
259 addiu dataTemp, imm.m_value >> 31 ? -1 : 0
260 addu dataTemp, dataTemp, immTemp
261 sw dataTemp, 4(addrTemp)
264 m_assembler
.sltu(immTempRegister
, dataTempRegister
, cmpTempRegister
);
265 m_assembler
.lw(dataTempRegister
, addrTempRegister
, 4);
266 if (imm
.m_value
>> 31)
267 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, -1);
268 m_assembler
.addu(dataTempRegister
, dataTempRegister
, immTempRegister
);
269 m_assembler
.sw(dataTempRegister
, addrTempRegister
, 4);
272 void and32(Address src
, RegisterID dest
)
274 load32(src
, dataTempRegister
);
275 and32(dataTempRegister
, dest
);
278 void and32(RegisterID src
, RegisterID dest
)
280 m_assembler
.andInsn(dest
, dest
, src
);
283 void and32(RegisterID op1
, RegisterID op2
, RegisterID dest
)
285 m_assembler
.andInsn(dest
, op1
, op2
);
288 void and32(TrustedImm32 imm
, RegisterID dest
)
290 if (!imm
.m_value
&& !m_fixedWidth
)
291 move(MIPSRegisters::zero
, dest
);
292 else if (imm
.m_value
> 0 && imm
.m_value
< 65535 && !m_fixedWidth
)
293 m_assembler
.andi(dest
, dest
, imm
.m_value
);
297 and dest, dest, immTemp
299 move(imm
, immTempRegister
);
300 m_assembler
.andInsn(dest
, dest
, immTempRegister
);
304 void and32(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
306 if (!imm
.m_value
&& !m_fixedWidth
)
307 move(MIPSRegisters::zero
, dest
);
308 else if (imm
.m_value
> 0 && imm
.m_value
< 65535 && !m_fixedWidth
)
309 m_assembler
.andi(dest
, src
, imm
.m_value
);
311 move(imm
, immTempRegister
);
312 m_assembler
.andInsn(dest
, src
, immTempRegister
);
316 void lshift32(RegisterID shiftAmount
, RegisterID dest
)
318 m_assembler
.sllv(dest
, dest
, shiftAmount
);
321 void lshift32(RegisterID src
, RegisterID shiftAmount
, RegisterID dest
)
323 m_assembler
.sllv(dest
, src
, shiftAmount
);
326 void lshift32(TrustedImm32 imm
, RegisterID dest
)
328 move(imm
, immTempRegister
);
329 m_assembler
.sllv(dest
, dest
, immTempRegister
);
332 void lshift32(RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
334 move(imm
, immTempRegister
);
335 m_assembler
.sllv(dest
, src
, immTempRegister
);
338 void mul32(RegisterID src
, RegisterID dest
)
340 m_assembler
.mul(dest
, dest
, src
);
343 void mul32(RegisterID op1
, RegisterID op2
, RegisterID dest
)
345 m_assembler
.mul(dest
, op1
, op2
);
348 void mul32(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
350 if (!imm
.m_value
&& !m_fixedWidth
)
351 move(MIPSRegisters::zero
, dest
);
352 else if (imm
.m_value
== 1 && !m_fixedWidth
)
357 mul dest, src, dataTemp
359 move(imm
, dataTempRegister
);
360 m_assembler
.mul(dest
, src
, dataTempRegister
);
364 void neg32(RegisterID srcDest
)
366 m_assembler
.subu(srcDest
, MIPSRegisters::zero
, srcDest
);
369 void or32(RegisterID src
, RegisterID dest
)
371 m_assembler
.orInsn(dest
, dest
, src
);
374 void or32(RegisterID op1
, RegisterID op2
, RegisterID dest
)
376 m_assembler
.orInsn(dest
, op1
, op2
);
379 void or32(TrustedImm32 imm
, RegisterID dest
)
381 if (!imm
.m_value
&& !m_fixedWidth
)
384 if (imm
.m_value
> 0 && imm
.m_value
< 65535
386 m_assembler
.ori(dest
, dest
, imm
.m_value
);
392 or dest, dest, dataTemp
394 move(imm
, dataTempRegister
);
395 m_assembler
.orInsn(dest
, dest
, dataTempRegister
);
398 void or32(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
400 if (!imm
.m_value
&& !m_fixedWidth
)
403 if (imm
.m_value
> 0 && imm
.m_value
< 65535 && !m_fixedWidth
) {
404 m_assembler
.ori(dest
, src
, imm
.m_value
);
410 or dest, src, dataTemp
412 move(imm
, dataTempRegister
);
413 m_assembler
.orInsn(dest
, src
, dataTempRegister
);
416 void or32(RegisterID src
, AbsoluteAddress dest
)
418 load32(dest
.m_ptr
, dataTempRegister
);
419 m_assembler
.orInsn(dataTempRegister
, dataTempRegister
, src
);
420 store32(dataTempRegister
, dest
.m_ptr
);
423 void rshift32(RegisterID shiftAmount
, RegisterID dest
)
425 m_assembler
.srav(dest
, dest
, shiftAmount
);
428 void rshift32(RegisterID src
, RegisterID shiftAmount
, RegisterID dest
)
430 m_assembler
.srav(dest
, src
, shiftAmount
);
433 void rshift32(TrustedImm32 imm
, RegisterID dest
)
435 m_assembler
.sra(dest
, dest
, imm
.m_value
);
438 void rshift32(RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
440 m_assembler
.sra(dest
, src
, imm
.m_value
);
443 void urshift32(RegisterID shiftAmount
, RegisterID dest
)
445 m_assembler
.srlv(dest
, dest
, shiftAmount
);
448 void urshift32(RegisterID src
, RegisterID shiftAmount
, RegisterID dest
)
450 m_assembler
.srlv(dest
, src
, shiftAmount
);
453 void urshift32(TrustedImm32 imm
, RegisterID dest
)
455 m_assembler
.srl(dest
, dest
, imm
.m_value
);
458 void urshift32(RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
460 m_assembler
.srl(dest
, src
, imm
.m_value
);
463 void sub32(RegisterID src
, RegisterID dest
)
465 m_assembler
.subu(dest
, dest
, src
);
468 void sub32(RegisterID op1
, RegisterID op2
, RegisterID dest
)
470 m_assembler
.subu(dest
, op1
, op2
);
473 void sub32(TrustedImm32 imm
, RegisterID dest
)
475 if (imm
.m_value
>= -32767 && imm
.m_value
<= 32768
480 m_assembler
.addiu(dest
, dest
, -imm
.m_value
);
484 subu dest, src, immTemp
486 move(imm
, immTempRegister
);
487 m_assembler
.subu(dest
, dest
, immTempRegister
);
491 void sub32(RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
493 if (imm
.m_value
>= -32767 && imm
.m_value
<= 32768
498 m_assembler
.addiu(dest
, src
, -imm
.m_value
);
502 subu dest, src, immTemp
504 move(imm
, immTempRegister
);
505 m_assembler
.subu(dest
, src
, immTempRegister
);
509 void sub32(TrustedImm32 imm
, Address address
)
511 if (address
.offset
>= -32768 && address
.offset
<= 32767
514 lw dataTemp, offset(base)
516 subu dataTemp, dataTemp, immTemp
517 sw dataTemp, offset(base)
519 m_assembler
.lw(dataTempRegister
, address
.base
, address
.offset
);
520 if (imm
.m_value
>= -32767 && imm
.m_value
<= 32768 && !m_fixedWidth
)
521 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, -imm
.m_value
);
523 move(imm
, immTempRegister
);
524 m_assembler
.subu(dataTempRegister
, dataTempRegister
, immTempRegister
);
526 m_assembler
.sw(dataTempRegister
, address
.base
, address
.offset
);
529 lui addrTemp, (offset + 0x8000) >> 16
530 addu addrTemp, addrTemp, base
531 lw dataTemp, (offset & 0xffff)(addrTemp)
533 subu dataTemp, dataTemp, immTemp
534 sw dataTemp, (offset & 0xffff)(addrTemp)
536 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
537 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
538 m_assembler
.lw(dataTempRegister
, addrTempRegister
, address
.offset
);
540 if (imm
.m_value
>= -32767 && imm
.m_value
<= 32768
542 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, -imm
.m_value
);
544 move(imm
, immTempRegister
);
545 m_assembler
.subu(dataTempRegister
, dataTempRegister
, immTempRegister
);
547 m_assembler
.sw(dataTempRegister
, addrTempRegister
, address
.offset
);
551 void sub32(Address src
, RegisterID dest
)
553 load32(src
, dataTempRegister
);
554 sub32(dataTempRegister
, dest
);
557 void sub32(TrustedImm32 imm
, AbsoluteAddress address
)
562 lw dataTemp, 0(addrTemp)
563 subu dataTemp, dataTemp, immTemp
564 sw dataTemp, 0(addrTemp)
566 move(TrustedImmPtr(address
.m_ptr
), addrTempRegister
);
567 m_assembler
.lw(dataTempRegister
, addrTempRegister
, 0);
569 if (imm
.m_value
>= -32767 && imm
.m_value
<= 32768 && !m_fixedWidth
)
570 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, -imm
.m_value
);
572 move(imm
, immTempRegister
);
573 m_assembler
.subu(dataTempRegister
, dataTempRegister
, immTempRegister
);
575 m_assembler
.sw(dataTempRegister
, addrTempRegister
, 0);
578 void xor32(RegisterID src
, RegisterID dest
)
580 m_assembler
.xorInsn(dest
, dest
, src
);
583 void xor32(RegisterID op1
, RegisterID op2
, RegisterID dest
)
585 m_assembler
.xorInsn(dest
, op1
, op2
);
588 void xor32(TrustedImm32 imm
, RegisterID dest
)
590 if (imm
.m_value
== -1) {
591 m_assembler
.nor(dest
, dest
, MIPSRegisters::zero
);
597 xor dest, dest, immTemp
599 move(imm
, immTempRegister
);
600 m_assembler
.xorInsn(dest
, dest
, immTempRegister
);
603 void xor32(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
605 if (imm
.m_value
== -1) {
606 m_assembler
.nor(dest
, src
, MIPSRegisters::zero
);
612 xor dest, dest, immTemp
614 move(imm
, immTempRegister
);
615 m_assembler
.xorInsn(dest
, src
, immTempRegister
);
618 void sqrtDouble(FPRegisterID src
, FPRegisterID dst
)
620 m_assembler
.sqrtd(dst
, src
);
623 void absDouble(FPRegisterID
, FPRegisterID
)
625 RELEASE_ASSERT_NOT_REACHED();
628 ConvertibleLoadLabel
convertibleLoadPtr(Address address
, RegisterID dest
)
630 ConvertibleLoadLabel
result(this);
632 lui addrTemp, (offset + 0x8000) >> 16
633 addu addrTemp, addrTemp, base
634 lw dest, (offset & 0xffff)(addrTemp)
636 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
637 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
638 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
642 // Memory access operations:
644 // Loads are of the form load(address, destination) and stores of the form
645 // store(source, address). The source for a store may be an TrustedImm32. Address
646 // operand objects to loads and store will be implicitly constructed if a
647 // register is passed.
649 /* Need to use zero-extened load byte for load8. */
650 void load8(ImplicitAddress address
, RegisterID dest
)
652 if (address
.offset
>= -32768 && address
.offset
<= 32767
654 m_assembler
.lbu(dest
, address
.base
, address
.offset
);
657 lui addrTemp, (offset + 0x8000) >> 16
658 addu addrTemp, addrTemp, base
659 lbu dest, (offset & 0xffff)(addrTemp)
661 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
662 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
663 m_assembler
.lbu(dest
, addrTempRegister
, address
.offset
);
667 void load8(BaseIndex address
, RegisterID dest
)
669 if (address
.offset
>= -32768 && address
.offset
<= 32767
672 sll addrTemp, address.index, address.scale
673 addu addrTemp, addrTemp, address.base
674 lbu dest, address.offset(addrTemp)
676 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
677 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
678 m_assembler
.lbu(dest
, addrTempRegister
, address
.offset
);
681 sll addrTemp, address.index, address.scale
682 addu addrTemp, addrTemp, address.base
683 lui immTemp, (address.offset + 0x8000) >> 16
684 addu addrTemp, addrTemp, immTemp
685 lbu dest, (address.offset & 0xffff)(at)
687 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
688 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
689 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
690 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
691 m_assembler
.lbu(dest
, addrTempRegister
, address
.offset
);
695 ALWAYS_INLINE
void load8(AbsoluteAddress address
, RegisterID dest
)
697 load8(address
.m_ptr
, dest
);
700 void load8(const void* address
, RegisterID dest
)
704 lbu dest, 0(addrTemp)
706 move(TrustedImmPtr(address
), addrTempRegister
);
707 m_assembler
.lbu(dest
, addrTempRegister
, 0);
710 void load8SignedExtendTo32(BaseIndex address
, RegisterID dest
)
712 if (address
.offset
>= -32768 && address
.offset
<= 32767
715 sll addrTemp, address.index, address.scale
716 addu addrTemp, addrTemp, address.base
717 lb dest, address.offset(addrTemp)
719 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
720 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
721 m_assembler
.lb(dest
, addrTempRegister
, address
.offset
);
724 sll addrTemp, address.index, address.scale
725 addu addrTemp, addrTemp, address.base
726 lui immTemp, (address.offset + 0x8000) >> 16
727 addu addrTemp, addrTemp, immTemp
728 lb dest, (address.offset & 0xffff)(at)
730 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
731 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
732 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
733 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
734 m_assembler
.lb(dest
, addrTempRegister
, address
.offset
);
738 void load32(ImplicitAddress address
, RegisterID dest
)
740 if (address
.offset
>= -32768 && address
.offset
<= 32767
742 m_assembler
.lw(dest
, address
.base
, address
.offset
);
745 lui addrTemp, (offset + 0x8000) >> 16
746 addu addrTemp, addrTemp, base
747 lw dest, (offset & 0xffff)(addrTemp)
749 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
750 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
751 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
755 void load32(BaseIndex address
, RegisterID dest
)
757 if (address
.offset
>= -32768 && address
.offset
<= 32767
760 sll addrTemp, address.index, address.scale
761 addu addrTemp, addrTemp, address.base
762 lw dest, address.offset(addrTemp)
764 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
765 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
766 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
769 sll addrTemp, address.index, address.scale
770 addu addrTemp, addrTemp, address.base
771 lui immTemp, (address.offset + 0x8000) >> 16
772 addu addrTemp, addrTemp, immTemp
773 lw dest, (address.offset & 0xffff)(at)
775 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
776 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
777 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
778 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
779 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
783 void load16Unaligned(BaseIndex address
, RegisterID dest
)
785 load16(address
, dest
);
788 void load32WithUnalignedHalfWords(BaseIndex address
, RegisterID dest
)
790 if (address
.offset
>= -32768 && address
.offset
<= 32764
793 sll addrTemp, address.index, address.scale
794 addu addrTemp, addrTemp, address.base
796 lwl dest, address.offset(addrTemp)
797 lwr dest, address.offset+3(addrTemp)
799 lwl dest, address.offset+3(addrTemp)
800 lwr dest, address.offset(addrTemp)
802 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
803 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
805 m_assembler
.lwl(dest
, addrTempRegister
, address
.offset
);
806 m_assembler
.lwr(dest
, addrTempRegister
, address
.offset
+ 3);
808 m_assembler
.lwl(dest
, addrTempRegister
, address
.offset
+ 3);
809 m_assembler
.lwr(dest
, addrTempRegister
, address
.offset
);
814 sll addrTemp, address.index, address.scale
815 addu addrTemp, addrTemp, address.base
816 lui immTemp, address.offset >> 16
817 ori immTemp, immTemp, address.offset & 0xffff
818 addu addrTemp, addrTemp, immTemp
826 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
827 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
828 m_assembler
.lui(immTempRegister
, address
.offset
>> 16);
829 m_assembler
.ori(immTempRegister
, immTempRegister
, address
.offset
);
830 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
832 m_assembler
.lwl(dest
, addrTempRegister
, 0);
833 m_assembler
.lwr(dest
, addrTempRegister
, 3);
835 m_assembler
.lwl(dest
, addrTempRegister
, 3);
836 m_assembler
.lwr(dest
, addrTempRegister
, 0);
841 void load32(const void* address
, RegisterID dest
)
847 move(TrustedImmPtr(address
), addrTempRegister
);
848 m_assembler
.lw(dest
, addrTempRegister
, 0);
851 DataLabel32
load32WithAddressOffsetPatch(Address address
, RegisterID dest
)
855 lui addrTemp, address.offset >> 16
856 ori addrTemp, addrTemp, address.offset & 0xffff
857 addu addrTemp, addrTemp, address.base
860 DataLabel32
dataLabel(this);
861 move(TrustedImm32(address
.offset
), addrTempRegister
);
862 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
863 m_assembler
.lw(dest
, addrTempRegister
, 0);
864 m_fixedWidth
= false;
868 DataLabelCompact
load32WithCompactAddressOffsetPatch(Address address
, RegisterID dest
)
870 DataLabelCompact
dataLabel(this);
871 load32WithAddressOffsetPatch(address
, dest
);
875 /* Need to use zero-extened load half-word for load16. */
876 void load16(ImplicitAddress address
, RegisterID dest
)
878 if (address
.offset
>= -32768 && address
.offset
<= 32767
880 m_assembler
.lhu(dest
, address
.base
, address
.offset
);
883 lui addrTemp, (offset + 0x8000) >> 16
884 addu addrTemp, addrTemp, base
885 lhu dest, (offset & 0xffff)(addrTemp)
887 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
888 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
889 m_assembler
.lhu(dest
, addrTempRegister
, address
.offset
);
893 /* Need to use zero-extened load half-word for load16. */
894 void load16(BaseIndex address
, RegisterID dest
)
896 if (address
.offset
>= -32768 && address
.offset
<= 32767
899 sll addrTemp, address.index, address.scale
900 addu addrTemp, addrTemp, address.base
901 lhu dest, address.offset(addrTemp)
903 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
904 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
905 m_assembler
.lhu(dest
, addrTempRegister
, address
.offset
);
908 sll addrTemp, address.index, address.scale
909 addu addrTemp, addrTemp, address.base
910 lui immTemp, (address.offset + 0x8000) >> 16
911 addu addrTemp, addrTemp, immTemp
912 lhu dest, (address.offset & 0xffff)(addrTemp)
914 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
915 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
916 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
917 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
918 m_assembler
.lhu(dest
, addrTempRegister
, address
.offset
);
922 void load16SignedExtendTo32(BaseIndex address
, RegisterID dest
)
924 if (address
.offset
>= -32768 && address
.offset
<= 32767
927 sll addrTemp, address.index, address.scale
928 addu addrTemp, addrTemp, address.base
929 lh dest, address.offset(addrTemp)
931 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
932 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
933 m_assembler
.lh(dest
, addrTempRegister
, address
.offset
);
936 sll addrTemp, address.index, address.scale
937 addu addrTemp, addrTemp, address.base
938 lui immTemp, (address.offset + 0x8000) >> 16
939 addu addrTemp, addrTemp, immTemp
940 lh dest, (address.offset & 0xffff)(addrTemp)
942 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
943 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
944 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
945 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
946 m_assembler
.lh(dest
, addrTempRegister
, address
.offset
);
950 DataLabel32
store32WithAddressOffsetPatch(RegisterID src
, Address address
)
954 lui addrTemp, address.offset >> 16
955 ori addrTemp, addrTemp, address.offset & 0xffff
956 addu addrTemp, addrTemp, address.base
959 DataLabel32
dataLabel(this);
960 move(TrustedImm32(address
.offset
), addrTempRegister
);
961 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
962 m_assembler
.sw(src
, addrTempRegister
, 0);
963 m_fixedWidth
= false;
967 void store8(RegisterID src
, BaseIndex address
)
969 if (address
.offset
>= -32768 && address
.offset
<= 32767
972 sll addrTemp, address.index, address.scale
973 addu addrTemp, addrTemp, address.base
974 sb src, address.offset(addrTemp)
976 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
977 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
978 m_assembler
.sb(src
, addrTempRegister
, address
.offset
);
981 sll addrTemp, address.index, address.scale
982 addu addrTemp, addrTemp, address.base
983 lui immTemp, (address.offset + 0x8000) >> 16
984 addu addrTemp, addrTemp, immTemp
985 sb src, (address.offset & 0xffff)(at)
987 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
988 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
989 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
990 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
991 m_assembler
.sb(src
, addrTempRegister
, address
.offset
);
995 void store8(RegisterID src
, void* address
)
997 move(TrustedImmPtr(address
), addrTempRegister
);
998 m_assembler
.sb(src
, addrTempRegister
, 0);
1001 void store8(TrustedImm32 imm
, void* address
)
1005 li addrTemp, address
1008 if (!imm
.m_value
&& !m_fixedWidth
) {
1009 move(TrustedImmPtr(address
), addrTempRegister
);
1010 m_assembler
.sb(MIPSRegisters::zero
, addrTempRegister
, 0);
1012 move(imm
, immTempRegister
);
1013 move(TrustedImmPtr(address
), addrTempRegister
);
1014 m_assembler
.sb(immTempRegister
, addrTempRegister
, 0);
1018 void store16(RegisterID src
, BaseIndex address
)
1020 if (address
.offset
>= -32768 && address
.offset
<= 32767
1023 sll addrTemp, address.index, address.scale
1024 addu addrTemp, addrTemp, address.base
1025 sh src, address.offset(addrTemp)
1027 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
1028 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1029 m_assembler
.sh(src
, addrTempRegister
, address
.offset
);
1032 sll addrTemp, address.index, address.scale
1033 addu addrTemp, addrTemp, address.base
1034 lui immTemp, (address.offset + 0x8000) >> 16
1035 addu addrTemp, addrTemp, immTemp
1036 sh src, (address.offset & 0xffff)(at)
1038 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
1039 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1040 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
1041 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
1042 m_assembler
.sh(src
, addrTempRegister
, address
.offset
);
1046 void store32(RegisterID src
, ImplicitAddress address
)
1048 if (address
.offset
>= -32768 && address
.offset
<= 32767
1050 m_assembler
.sw(src
, address
.base
, address
.offset
);
1053 lui addrTemp, (offset + 0x8000) >> 16
1054 addu addrTemp, addrTemp, base
1055 sw src, (offset & 0xffff)(addrTemp)
1057 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
1058 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1059 m_assembler
.sw(src
, addrTempRegister
, address
.offset
);
1063 void store32(RegisterID src
, BaseIndex address
)
1065 if (address
.offset
>= -32768 && address
.offset
<= 32767
1068 sll addrTemp, address.index, address.scale
1069 addu addrTemp, addrTemp, address.base
1070 sw src, address.offset(addrTemp)
1072 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
1073 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1074 m_assembler
.sw(src
, addrTempRegister
, address
.offset
);
1077 sll addrTemp, address.index, address.scale
1078 addu addrTemp, addrTemp, address.base
1079 lui immTemp, (address.offset + 0x8000) >> 16
1080 addu addrTemp, addrTemp, immTemp
1081 sw src, (address.offset & 0xffff)(at)
1083 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
1084 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1085 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
1086 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
1087 m_assembler
.sw(src
, addrTempRegister
, address
.offset
);
1091 void store32(TrustedImm32 imm
, ImplicitAddress address
)
1093 if (address
.offset
>= -32768 && address
.offset
<= 32767
1096 m_assembler
.sw(MIPSRegisters::zero
, address
.base
, address
.offset
);
1098 move(imm
, immTempRegister
);
1099 m_assembler
.sw(immTempRegister
, address
.base
, address
.offset
);
1103 lui addrTemp, (offset + 0x8000) >> 16
1104 addu addrTemp, addrTemp, base
1105 sw immTemp, (offset & 0xffff)(addrTemp)
1107 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
1108 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1109 if (!imm
.m_value
&& !m_fixedWidth
)
1110 m_assembler
.sw(MIPSRegisters::zero
, addrTempRegister
, address
.offset
);
1112 move(imm
, immTempRegister
);
1113 m_assembler
.sw(immTempRegister
, addrTempRegister
, address
.offset
);
1118 void store32(TrustedImm32 imm
, BaseIndex address
)
1120 if (address
.offset
>= -32768 && address
.offset
<= 32767 && !m_fixedWidth
) {
1122 sll addrTemp, address.index, address.scale
1123 addu addrTemp, addrTemp, address.base
1124 sw src, address.offset(addrTemp)
1126 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
1127 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1129 m_assembler
.sw(MIPSRegisters::zero
, addrTempRegister
, address
.offset
);
1131 move(imm
, immTempRegister
);
1132 m_assembler
.sw(immTempRegister
, addrTempRegister
, address
.offset
);
1136 sll addrTemp, address.index, address.scale
1137 addu addrTemp, addrTemp, address.base
1138 lui immTemp, (address.offset + 0x8000) >> 16
1139 addu addrTemp, addrTemp, immTemp
1140 sw src, (address.offset & 0xffff)(at)
1142 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
1143 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1144 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
1145 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
1146 if (!imm
.m_value
&& !m_fixedWidth
)
1147 m_assembler
.sw(MIPSRegisters::zero
, addrTempRegister
, address
.offset
);
1149 move(imm
, immTempRegister
);
1150 m_assembler
.sw(immTempRegister
, addrTempRegister
, address
.offset
);
1156 void store32(RegisterID src
, const void* address
)
1159 li addrTemp, address
1162 move(TrustedImmPtr(address
), addrTempRegister
);
1163 m_assembler
.sw(src
, addrTempRegister
, 0);
1166 void store32(TrustedImm32 imm
, const void* address
)
1170 li addrTemp, address
1173 if (!imm
.m_value
&& !m_fixedWidth
) {
1174 move(TrustedImmPtr(address
), addrTempRegister
);
1175 m_assembler
.sw(MIPSRegisters::zero
, addrTempRegister
, 0);
1177 move(imm
, immTempRegister
);
1178 move(TrustedImmPtr(address
), addrTempRegister
);
1179 m_assembler
.sw(immTempRegister
, addrTempRegister
, 0);
1183 // Floating-point operations:
1185 static bool supportsFloatingPoint()
1187 #if WTF_MIPS_DOUBLE_FLOAT
1194 static bool supportsFloatingPointTruncate()
1196 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
1203 static bool supportsFloatingPointSqrt()
1205 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
1211 static bool supportsFloatingPointAbs() { return false; }
1213 // Stack manipulation operations:
1215 // The ABI is assumed to provide a stack abstraction to memory,
1216 // containing machine word sized units of data. Push and pop
1217 // operations add and remove a single register sized unit of data
1218 // to or from the stack. Peek and poke operations read or write
1219 // values on the stack, without moving the current stack position.
1221 void pop(RegisterID dest
)
1223 m_assembler
.lw(dest
, MIPSRegisters::sp
, 0);
1224 m_assembler
.addiu(MIPSRegisters::sp
, MIPSRegisters::sp
, 4);
1227 void push(RegisterID src
)
1229 m_assembler
.addiu(MIPSRegisters::sp
, MIPSRegisters::sp
, -4);
1230 m_assembler
.sw(src
, MIPSRegisters::sp
, 0);
1233 void push(Address address
)
1235 load32(address
, dataTempRegister
);
1236 push(dataTempRegister
);
1239 void push(TrustedImm32 imm
)
1241 move(imm
, immTempRegister
);
1242 push(immTempRegister
);
1245 // Register move operations:
1247 // Move values in registers.
1249 void move(TrustedImm32 imm
, RegisterID dest
)
1251 if (!imm
.m_value
&& !m_fixedWidth
)
1252 move(MIPSRegisters::zero
, dest
);
1253 else if (m_fixedWidth
) {
1254 m_assembler
.lui(dest
, imm
.m_value
>> 16);
1255 m_assembler
.ori(dest
, dest
, imm
.m_value
);
1257 m_assembler
.li(dest
, imm
.m_value
);
1260 void move(RegisterID src
, RegisterID dest
)
1262 if (src
!= dest
|| m_fixedWidth
)
1263 m_assembler
.move(dest
, src
);
1266 void move(TrustedImmPtr imm
, RegisterID dest
)
1268 move(TrustedImm32(imm
), dest
);
1271 void swap(RegisterID reg1
, RegisterID reg2
)
1273 move(reg1
, immTempRegister
);
1275 move(immTempRegister
, reg2
);
1278 void signExtend32ToPtr(RegisterID src
, RegisterID dest
)
1280 if (src
!= dest
|| m_fixedWidth
)
1284 void zeroExtend32ToPtr(RegisterID src
, RegisterID dest
)
1286 if (src
!= dest
|| m_fixedWidth
)
1290 // Forwards / external control flow operations:
1292 // This set of jump and conditional branch operations return a Jump
1293 // object which may linked at a later point, allow forwards jump,
1294 // or jumps that will require external linkage (after the code has been
1297 // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
1298 // respecitvely, for unsigned comparisons the names b, a, be, and ae are
1299 // used (representing the names 'below' and 'above').
1301 // Operands to the comparision are provided in the expected order, e.g.
1302 // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when
1303 // treated as a signed 32bit value, is less than or equal to 5.
1305 // jz and jnz test whether the first operand is equal to zero, and take
1306 // an optional second operand of a mask under which to perform the test.
1308 Jump
branch8(RelationalCondition cond
, Address left
, TrustedImm32 right
)
1310 // Make sure the immediate value is unsigned 8 bits.
1311 ASSERT(!(right
.m_value
& 0xFFFFFF00));
1312 load8(left
, dataTempRegister
);
1313 move(right
, immTempRegister
);
1314 return branch32(cond
, dataTempRegister
, immTempRegister
);
1317 Jump
branch8(RelationalCondition cond
, AbsoluteAddress left
, TrustedImm32 right
)
1319 // Make sure the immediate value is unsigned 8 bits.
1320 ASSERT(!(right
.m_value
& 0xFFFFFF00));
1321 load8(left
, dataTempRegister
);
1322 move(right
, immTempRegister
);
1323 return branch32(cond
, dataTempRegister
, immTempRegister
);
1326 void compare8(RelationalCondition cond
, Address left
, TrustedImm32 right
, RegisterID dest
)
1328 // Make sure the immediate value is unsigned 8 bits.
1329 ASSERT(!(right
.m_value
& 0xFFFFFF00));
1330 load8(left
, dataTempRegister
);
1331 move(right
, immTempRegister
);
1332 compare32(cond
, dataTempRegister
, immTempRegister
, dest
);
1335 Jump
branch8(RelationalCondition cond
, BaseIndex left
, TrustedImm32 right
)
1337 ASSERT(!(right
.m_value
& 0xFFFFFF00));
1338 load8(left
, dataTempRegister
);
1339 // Be careful that the previous load8() uses immTempRegister.
1340 // So, we need to put move() after load8().
1341 move(right
, immTempRegister
);
1342 return branch32(cond
, dataTempRegister
, immTempRegister
);
1345 Jump
branch32(RelationalCondition cond
, RegisterID left
, RegisterID right
)
1348 return branchEqual(left
, right
);
1349 if (cond
== NotEqual
)
1350 return branchNotEqual(left
, right
);
1351 if (cond
== Above
) {
1352 m_assembler
.sltu(cmpTempRegister
, right
, left
);
1353 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1355 if (cond
== AboveOrEqual
) {
1356 m_assembler
.sltu(cmpTempRegister
, left
, right
);
1357 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1359 if (cond
== Below
) {
1360 m_assembler
.sltu(cmpTempRegister
, left
, right
);
1361 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1363 if (cond
== BelowOrEqual
) {
1364 m_assembler
.sltu(cmpTempRegister
, right
, left
);
1365 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1367 if (cond
== GreaterThan
) {
1368 m_assembler
.slt(cmpTempRegister
, right
, left
);
1369 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1371 if (cond
== GreaterThanOrEqual
) {
1372 m_assembler
.slt(cmpTempRegister
, left
, right
);
1373 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1375 if (cond
== LessThan
) {
1376 m_assembler
.slt(cmpTempRegister
, left
, right
);
1377 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1379 if (cond
== LessThanOrEqual
) {
1380 m_assembler
.slt(cmpTempRegister
, right
, left
);
1381 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1388 Jump
branch32(RelationalCondition cond
, RegisterID left
, TrustedImm32 right
)
1390 move(right
, immTempRegister
);
1391 return branch32(cond
, left
, immTempRegister
);
1394 Jump
branch32(RelationalCondition cond
, RegisterID left
, Address right
)
1396 load32(right
, dataTempRegister
);
1397 return branch32(cond
, left
, dataTempRegister
);
1400 Jump
branch32(RelationalCondition cond
, Address left
, RegisterID right
)
1402 load32(left
, dataTempRegister
);
1403 return branch32(cond
, dataTempRegister
, right
);
1406 Jump
branch32(RelationalCondition cond
, Address left
, TrustedImm32 right
)
1408 load32(left
, dataTempRegister
);
1409 move(right
, immTempRegister
);
1410 return branch32(cond
, dataTempRegister
, immTempRegister
);
1413 Jump
branch32(RelationalCondition cond
, BaseIndex left
, TrustedImm32 right
)
1415 load32(left
, dataTempRegister
);
1416 // Be careful that the previous load32() uses immTempRegister.
1417 // So, we need to put move() after load32().
1418 move(right
, immTempRegister
);
1419 return branch32(cond
, dataTempRegister
, immTempRegister
);
1422 Jump
branch32WithUnalignedHalfWords(RelationalCondition cond
, BaseIndex left
, TrustedImm32 right
)
1424 load32WithUnalignedHalfWords(left
, dataTempRegister
);
1425 // Be careful that the previous load32WithUnalignedHalfWords()
1426 // uses immTempRegister.
1427 // So, we need to put move() after load32WithUnalignedHalfWords().
1428 move(right
, immTempRegister
);
1429 return branch32(cond
, dataTempRegister
, immTempRegister
);
1432 Jump
branch32(RelationalCondition cond
, AbsoluteAddress left
, RegisterID right
)
1434 load32(left
.m_ptr
, dataTempRegister
);
1435 return branch32(cond
, dataTempRegister
, right
);
1438 Jump
branch32(RelationalCondition cond
, AbsoluteAddress left
, TrustedImm32 right
)
1440 load32(left
.m_ptr
, dataTempRegister
);
1441 move(right
, immTempRegister
);
1442 return branch32(cond
, dataTempRegister
, immTempRegister
);
1445 Jump
branchTest32(ResultCondition cond
, RegisterID reg
, RegisterID mask
)
1447 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1448 m_assembler
.andInsn(cmpTempRegister
, reg
, mask
);
1450 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1451 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1454 Jump
branchTest32(ResultCondition cond
, RegisterID reg
, TrustedImm32 mask
= TrustedImm32(-1))
1456 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1457 if (mask
.m_value
== -1 && !m_fixedWidth
) {
1459 return branchEqual(reg
, MIPSRegisters::zero
);
1460 return branchNotEqual(reg
, MIPSRegisters::zero
);
1462 move(mask
, immTempRegister
);
1463 return branchTest32(cond
, reg
, immTempRegister
);
1466 Jump
branchTest32(ResultCondition cond
, Address address
, TrustedImm32 mask
= TrustedImm32(-1))
1468 load32(address
, dataTempRegister
);
1469 return branchTest32(cond
, dataTempRegister
, mask
);
1472 Jump
branchTest32(ResultCondition cond
, BaseIndex address
, TrustedImm32 mask
= TrustedImm32(-1))
1474 load32(address
, dataTempRegister
);
1475 return branchTest32(cond
, dataTempRegister
, mask
);
1478 Jump
branchTest8(ResultCondition cond
, BaseIndex address
, TrustedImm32 mask
= TrustedImm32(-1))
1480 load8(address
, dataTempRegister
);
1481 return branchTest32(cond
, dataTempRegister
, mask
);
1484 Jump
branchTest8(ResultCondition cond
, Address address
, TrustedImm32 mask
= TrustedImm32(-1))
1486 load8(address
, dataTempRegister
);
1487 return branchTest32(cond
, dataTempRegister
, mask
);
1490 Jump
branchTest8(ResultCondition cond
, AbsoluteAddress address
, TrustedImm32 mask
= TrustedImm32(-1))
1492 move(TrustedImmPtr(address
.m_ptr
), dataTempRegister
);
1493 load8(Address(dataTempRegister
), dataTempRegister
);
1494 return branchTest32(cond
, dataTempRegister
, mask
);
1499 return branchEqual(MIPSRegisters::zero
, MIPSRegisters::zero
);
1502 void jump(RegisterID target
)
1504 move(target
, MIPSRegisters::t9
);
1505 m_assembler
.jr(MIPSRegisters::t9
);
1509 void jump(Address address
)
1511 m_fixedWidth
= true;
1512 load32(address
, MIPSRegisters::t9
);
1513 m_assembler
.jr(MIPSRegisters::t9
);
1515 m_fixedWidth
= false;
1518 void jump(AbsoluteAddress address
)
1520 m_fixedWidth
= true;
1521 load32(address
.m_ptr
, MIPSRegisters::t9
);
1522 m_assembler
.jr(MIPSRegisters::t9
);
1524 m_fixedWidth
= false;
1527 void moveDoubleToInts(FPRegisterID src
, RegisterID dest1
, RegisterID dest2
)
1529 m_assembler
.vmov(dest1
, dest2
, src
);
1532 void moveIntsToDouble(RegisterID src1
, RegisterID src2
, FPRegisterID dest
, FPRegisterID scratch
)
1534 UNUSED_PARAM(scratch
);
1535 m_assembler
.vmov(dest
, src1
, src2
);
1538 // Arithmetic control flow operations:
1540 // This set of conditional branch operations branch based
1541 // on the result of an arithmetic operation. The operation
1542 // is performed as normal, storing the result.
1544 // * jz operations branch if the result is zero.
1545 // * jo operations branch if the (signed) arithmetic
1546 // operation caused an overflow to occur.
1548 Jump
branchAdd32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1550 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== PositiveOrZero
) || (cond
== Zero
) || (cond
== NonZero
));
1551 if (cond
== Overflow
) {
1554 xor cmpTemp, dataTemp, src
1555 bltz cmpTemp, No_overflow # diff sign bit -> no overflow
1556 addu dest, dataTemp, src
1557 xor cmpTemp, dest, dataTemp
1558 bgez cmpTemp, No_overflow # same sign big -> no overflow
1568 move(dest
, dataTempRegister
);
1569 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, src
);
1570 m_assembler
.bltz(cmpTempRegister
, 10);
1571 m_assembler
.addu(dest
, dataTempRegister
, src
);
1572 m_assembler
.xorInsn(cmpTempRegister
, dest
, dataTempRegister
);
1573 m_assembler
.bgez(cmpTempRegister
, 7);
1577 if (cond
== Signed
) {
1579 // Check if dest is negative.
1580 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1581 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1583 if (cond
== PositiveOrZero
) {
1585 // Check if dest is not negative.
1586 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1587 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1591 return branchEqual(dest
, MIPSRegisters::zero
);
1593 if (cond
== NonZero
) {
1595 return branchNotEqual(dest
, MIPSRegisters::zero
);
1601 Jump
branchAdd32(ResultCondition cond
, RegisterID op1
, RegisterID op2
, RegisterID dest
)
1603 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== PositiveOrZero
) || (cond
== Zero
) || (cond
== NonZero
));
1604 if (cond
== Overflow
) {
1607 xor cmpTemp, dataTemp, op2
1608 bltz cmpTemp, No_overflow # diff sign bit -> no overflow
1609 addu dest, dataTemp, op2
1610 xor cmpTemp, dest, dataTemp
1611 bgez cmpTemp, No_overflow # same sign big -> no overflow
1621 move(op1
, dataTempRegister
);
1622 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, op2
);
1623 m_assembler
.bltz(cmpTempRegister
, 10);
1624 m_assembler
.addu(dest
, dataTempRegister
, op2
);
1625 m_assembler
.xorInsn(cmpTempRegister
, dest
, dataTempRegister
);
1626 m_assembler
.bgez(cmpTempRegister
, 7);
1630 if (cond
== Signed
) {
1631 add32(op1
, op2
, dest
);
1632 // Check if dest is negative.
1633 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1634 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1636 if (cond
== PositiveOrZero
) {
1637 add32(op1
, op2
, dest
);
1638 // Check if dest is not negative.
1639 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1640 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1643 add32(op1
, op2
, dest
);
1644 return branchEqual(dest
, MIPSRegisters::zero
);
1646 if (cond
== NonZero
) {
1647 add32(op1
, op2
, dest
);
1648 return branchNotEqual(dest
, MIPSRegisters::zero
);
1654 Jump
branchAdd32(ResultCondition cond
, TrustedImm32 imm
, RegisterID dest
)
1656 move(imm
, immTempRegister
);
1657 return branchAdd32(cond
, immTempRegister
, dest
);
1660 Jump
branchAdd32(ResultCondition cond
, RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
1662 move(imm
, immTempRegister
);
1664 return branchAdd32(cond
, immTempRegister
, dest
);
1667 Jump
branchAdd32(ResultCondition cond
, TrustedImm32 imm
, AbsoluteAddress dest
)
1669 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== PositiveOrZero
) || (cond
== Zero
) || (cond
== NonZero
));
1670 if (cond
== Overflow
) {
1673 xori cmpTemp, dataTemp, imm
1674 bltz cmpTemp, No_overflow # diff sign bit -> no overflow
1675 addiu dataTemp, dataTemp, imm
1677 xori cmpTemp, dataTemp, imm
1678 bgez cmpTemp, No_overflow # same sign big -> no overflow
1688 if (imm
.m_value
>= -32768 && imm
.m_value
<= 32767 && !m_fixedWidth
) {
1689 load32(dest
.m_ptr
, dataTempRegister
);
1690 m_assembler
.xori(cmpTempRegister
, dataTempRegister
, imm
.m_value
);
1691 m_assembler
.bltz(cmpTempRegister
, 10);
1692 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, imm
.m_value
);
1693 store32(dataTempRegister
, dest
.m_ptr
);
1694 m_assembler
.xori(cmpTempRegister
, dataTempRegister
, imm
.m_value
);
1695 m_assembler
.bgez(cmpTempRegister
, 7);
1698 load32(dest
.m_ptr
, dataTempRegister
);
1699 move(imm
, immTempRegister
);
1700 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, immTempRegister
);
1701 m_assembler
.bltz(cmpTempRegister
, 10);
1702 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, immTempRegister
);
1703 store32(dataTempRegister
, dest
.m_ptr
);
1704 m_assembler
.xori(cmpTempRegister
, dataTempRegister
, immTempRegister
);
1705 m_assembler
.bgez(cmpTempRegister
, 7);
1710 move(imm
, immTempRegister
);
1711 load32(dest
.m_ptr
, dataTempRegister
);
1712 add32(immTempRegister
, dataTempRegister
);
1713 store32(dataTempRegister
, dest
.m_ptr
);
1714 if (cond
== Signed
) {
1715 // Check if dest is negative.
1716 m_assembler
.slt(cmpTempRegister
, dataTempRegister
, MIPSRegisters::zero
);
1717 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1719 if (cond
== PositiveOrZero
) {
1720 // Check if dest is not negative.
1721 m_assembler
.slt(cmpTempRegister
, dataTempRegister
, MIPSRegisters::zero
);
1722 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1725 return branchEqual(dataTempRegister
, MIPSRegisters::zero
);
1726 if (cond
== NonZero
)
1727 return branchNotEqual(dataTempRegister
, MIPSRegisters::zero
);
1732 Jump
branchMul32(ResultCondition cond
, RegisterID src1
, RegisterID src2
, RegisterID dest
)
1734 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1735 if (cond
== Overflow
) {
1740 sra addrTemp, dest, 31
1741 beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow
1751 m_assembler
.mult(src1
, src2
);
1752 m_assembler
.mfhi(dataTempRegister
);
1753 m_assembler
.mflo(dest
);
1754 m_assembler
.sra(addrTempRegister
, dest
, 31);
1755 m_assembler
.beq(dataTempRegister
, addrTempRegister
, 7);
1759 if (cond
== Signed
) {
1760 mul32(src1
, src2
, dest
);
1761 // Check if dest is negative.
1762 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1763 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1766 mul32(src1
, src2
, dest
);
1767 return branchEqual(dest
, MIPSRegisters::zero
);
1769 if (cond
== NonZero
) {
1770 mul32(src1
, src2
, dest
);
1771 return branchNotEqual(dest
, MIPSRegisters::zero
);
1777 Jump
branchMul32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1779 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1780 if (cond
== Overflow
) {
1785 sra addrTemp, dest, 31
1786 beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow
1796 m_assembler
.mult(src
, dest
);
1797 m_assembler
.mfhi(dataTempRegister
);
1798 m_assembler
.mflo(dest
);
1799 m_assembler
.sra(addrTempRegister
, dest
, 31);
1800 m_assembler
.beq(dataTempRegister
, addrTempRegister
, 7);
1804 if (cond
== Signed
) {
1806 // Check if dest is negative.
1807 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1808 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1812 return branchEqual(dest
, MIPSRegisters::zero
);
1814 if (cond
== NonZero
) {
1816 return branchNotEqual(dest
, MIPSRegisters::zero
);
1822 Jump
branchMul32(ResultCondition cond
, TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
1824 move(imm
, immTempRegister
);
1825 return branchMul32(cond
, immTempRegister
, src
, dest
);
1828 Jump
branchSub32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1830 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1831 if (cond
== Overflow
) {
1834 xor cmpTemp, dataTemp, src
1835 bgez cmpTemp, No_overflow # same sign bit -> no overflow
1836 subu dest, dataTemp, src
1837 xor cmpTemp, dest, dataTemp
1838 bgez cmpTemp, No_overflow # same sign bit -> no overflow
1848 move(dest
, dataTempRegister
);
1849 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, src
);
1850 m_assembler
.bgez(cmpTempRegister
, 10);
1851 m_assembler
.subu(dest
, dataTempRegister
, src
);
1852 m_assembler
.xorInsn(cmpTempRegister
, dest
, dataTempRegister
);
1853 m_assembler
.bgez(cmpTempRegister
, 7);
1857 if (cond
== Signed
) {
1859 // Check if dest is negative.
1860 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1861 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1865 return branchEqual(dest
, MIPSRegisters::zero
);
1867 if (cond
== NonZero
) {
1869 return branchNotEqual(dest
, MIPSRegisters::zero
);
1875 Jump
branchSub32(ResultCondition cond
, TrustedImm32 imm
, RegisterID dest
)
1877 move(imm
, immTempRegister
);
1878 return branchSub32(cond
, immTempRegister
, dest
);
1881 Jump
branchSub32(ResultCondition cond
, RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
1883 move(imm
, immTempRegister
);
1884 return branchSub32(cond
, src
, immTempRegister
, dest
);
1887 Jump
branchSub32(ResultCondition cond
, RegisterID op1
, RegisterID op2
, RegisterID dest
)
1889 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1890 if (cond
== Overflow
) {
1893 xor cmpTemp, dataTemp, op2
1894 bgez cmpTemp, No_overflow # same sign bit -> no overflow
1895 subu dest, dataTemp, op2
1896 xor cmpTemp, dest, dataTemp
1897 bgez cmpTemp, No_overflow # same sign bit -> no overflow
1907 move(op1
, dataTempRegister
);
1908 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, op2
);
1909 m_assembler
.bgez(cmpTempRegister
, 10);
1910 m_assembler
.subu(dest
, dataTempRegister
, op2
);
1911 m_assembler
.xorInsn(cmpTempRegister
, dest
, dataTempRegister
);
1912 m_assembler
.bgez(cmpTempRegister
, 7);
1916 if (cond
== Signed
) {
1917 sub32(op1
, op2
, dest
);
1918 // Check if dest is negative.
1919 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1920 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1923 sub32(op1
, op2
, dest
);
1924 return branchEqual(dest
, MIPSRegisters::zero
);
1926 if (cond
== NonZero
) {
1927 sub32(op1
, op2
, dest
);
1928 return branchNotEqual(dest
, MIPSRegisters::zero
);
1934 Jump
branchNeg32(ResultCondition cond
, RegisterID srcDest
)
1936 m_assembler
.li(dataTempRegister
, -1);
1937 return branchMul32(cond
, dataTempRegister
, srcDest
);
1940 Jump
branchOr32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1942 ASSERT((cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1943 if (cond
== Signed
) {
1945 // Check if dest is negative.
1946 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1947 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1951 return branchEqual(dest
, MIPSRegisters::zero
);
1953 if (cond
== NonZero
) {
1955 return branchNotEqual(dest
, MIPSRegisters::zero
);
1961 // Miscellaneous operations:
1970 /* We need two words for relaxation. */
1975 return Call(m_assembler
.label(), Call::LinkableNear
);
1980 m_assembler
.lui(MIPSRegisters::t9
, 0);
1981 m_assembler
.ori(MIPSRegisters::t9
, MIPSRegisters::t9
, 0);
1982 m_assembler
.jalr(MIPSRegisters::t9
);
1984 return Call(m_assembler
.label(), Call::Linkable
);
1987 Call
call(RegisterID target
)
1989 move(target
, MIPSRegisters::t9
);
1990 m_assembler
.jalr(MIPSRegisters::t9
);
1992 return Call(m_assembler
.label(), Call::None
);
1995 Call
call(Address address
)
1997 m_fixedWidth
= true;
1998 load32(address
, MIPSRegisters::t9
);
1999 m_assembler
.jalr(MIPSRegisters::t9
);
2001 m_fixedWidth
= false;
2002 return Call(m_assembler
.label(), Call::None
);
2007 m_assembler
.jr(MIPSRegisters::ra
);
2011 void compare32(RelationalCondition cond
, RegisterID left
, RegisterID right
, RegisterID dest
)
2013 if (cond
== Equal
) {
2014 m_assembler
.xorInsn(dest
, left
, right
);
2015 m_assembler
.sltiu(dest
, dest
, 1);
2016 } else if (cond
== NotEqual
) {
2017 m_assembler
.xorInsn(dest
, left
, right
);
2018 m_assembler
.sltu(dest
, MIPSRegisters::zero
, dest
);
2019 } else if (cond
== Above
)
2020 m_assembler
.sltu(dest
, right
, left
);
2021 else if (cond
== AboveOrEqual
) {
2022 m_assembler
.sltu(dest
, left
, right
);
2023 m_assembler
.xori(dest
, dest
, 1);
2024 } else if (cond
== Below
)
2025 m_assembler
.sltu(dest
, left
, right
);
2026 else if (cond
== BelowOrEqual
) {
2027 m_assembler
.sltu(dest
, right
, left
);
2028 m_assembler
.xori(dest
, dest
, 1);
2029 } else if (cond
== GreaterThan
)
2030 m_assembler
.slt(dest
, right
, left
);
2031 else if (cond
== GreaterThanOrEqual
) {
2032 m_assembler
.slt(dest
, left
, right
);
2033 m_assembler
.xori(dest
, dest
, 1);
2034 } else if (cond
== LessThan
)
2035 m_assembler
.slt(dest
, left
, right
);
2036 else if (cond
== LessThanOrEqual
) {
2037 m_assembler
.slt(dest
, right
, left
);
2038 m_assembler
.xori(dest
, dest
, 1);
2042 void compare32(RelationalCondition cond
, RegisterID left
, TrustedImm32 right
, RegisterID dest
)
2044 move(right
, immTempRegister
);
2045 compare32(cond
, left
, immTempRegister
, dest
);
2048 void test8(ResultCondition cond
, Address address
, TrustedImm32 mask
, RegisterID dest
)
2050 ASSERT((cond
== Zero
) || (cond
== NonZero
));
2051 load8(address
, dataTempRegister
);
2052 if (mask
.m_value
== -1 && !m_fixedWidth
) {
2054 m_assembler
.sltiu(dest
, dataTempRegister
, 1);
2056 m_assembler
.sltu(dest
, MIPSRegisters::zero
, dataTempRegister
);
2058 move(mask
, immTempRegister
);
2059 m_assembler
.andInsn(cmpTempRegister
, dataTempRegister
, immTempRegister
);
2061 m_assembler
.sltiu(dest
, cmpTempRegister
, 1);
2063 m_assembler
.sltu(dest
, MIPSRegisters::zero
, cmpTempRegister
);
2067 void test32(ResultCondition cond
, Address address
, TrustedImm32 mask
, RegisterID dest
)
2069 ASSERT((cond
== Zero
) || (cond
== NonZero
));
2070 load32(address
, dataTempRegister
);
2071 if (mask
.m_value
== -1 && !m_fixedWidth
) {
2073 m_assembler
.sltiu(dest
, dataTempRegister
, 1);
2075 m_assembler
.sltu(dest
, MIPSRegisters::zero
, dataTempRegister
);
2077 move(mask
, immTempRegister
);
2078 m_assembler
.andInsn(cmpTempRegister
, dataTempRegister
, immTempRegister
);
2080 m_assembler
.sltiu(dest
, cmpTempRegister
, 1);
2082 m_assembler
.sltu(dest
, MIPSRegisters::zero
, cmpTempRegister
);
2086 DataLabel32
moveWithPatch(TrustedImm32 imm
, RegisterID dest
)
2088 m_fixedWidth
= true;
2089 DataLabel32
label(this);
2091 m_fixedWidth
= false;
2095 DataLabelPtr
moveWithPatch(TrustedImmPtr initialValue
, RegisterID dest
)
2097 m_fixedWidth
= true;
2098 DataLabelPtr
label(this);
2099 move(initialValue
, dest
);
2100 m_fixedWidth
= false;
2104 Jump
branchPtrWithPatch(RelationalCondition cond
, RegisterID left
, DataLabelPtr
& dataLabel
, TrustedImmPtr initialRightValue
= TrustedImmPtr(0))
2106 m_fixedWidth
= true;
2107 dataLabel
= moveWithPatch(initialRightValue
, immTempRegister
);
2108 Jump temp
= branch32(cond
, left
, immTempRegister
);
2109 m_fixedWidth
= false;
2113 Jump
branchPtrWithPatch(RelationalCondition cond
, Address left
, DataLabelPtr
& dataLabel
, TrustedImmPtr initialRightValue
= TrustedImmPtr(0))
2115 m_fixedWidth
= true;
2116 load32(left
, dataTempRegister
);
2117 dataLabel
= moveWithPatch(initialRightValue
, immTempRegister
);
2118 Jump temp
= branch32(cond
, dataTempRegister
, immTempRegister
);
2119 m_fixedWidth
= false;
2123 Jump
branch32WithPatch(RelationalCondition cond
, Address left
, DataLabel32
& dataLabel
, TrustedImm32 initialRightValue
= TrustedImm32(0))
2125 m_fixedWidth
= true;
2126 load32(left
, dataTempRegister
);
2127 dataLabel
= moveWithPatch(initialRightValue
, immTempRegister
);
2128 Jump temp
= branch32(cond
, dataTempRegister
, immTempRegister
);
2129 m_fixedWidth
= false;
2133 DataLabelPtr
storePtrWithPatch(TrustedImmPtr initialValue
, ImplicitAddress address
)
2135 m_fixedWidth
= true;
2136 DataLabelPtr dataLabel
= moveWithPatch(initialValue
, dataTempRegister
);
2137 store32(dataTempRegister
, address
);
2138 m_fixedWidth
= false;
2142 DataLabelPtr
storePtrWithPatch(ImplicitAddress address
)
2144 return storePtrWithPatch(TrustedImmPtr(0), address
);
2147 Call
tailRecursiveCall()
2149 // Like a normal call, but don't update the returned address register
2150 m_fixedWidth
= true;
2151 move(TrustedImm32(0), MIPSRegisters::t9
);
2152 m_assembler
.jr(MIPSRegisters::t9
);
2154 m_fixedWidth
= false;
2155 return Call(m_assembler
.label(), Call::Linkable
);
2158 Call
makeTailRecursiveCall(Jump oldJump
)
2161 return tailRecursiveCall();
2164 void loadFloat(BaseIndex address
, FPRegisterID dest
)
2166 if (address
.offset
>= -32768 && address
.offset
<= 32767
2169 sll addrTemp, address.index, address.scale
2170 addu addrTemp, addrTemp, address.base
2171 lwc1 dest, address.offset(addrTemp)
2173 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2174 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2175 m_assembler
.lwc1(dest
, addrTempRegister
, address
.offset
);
2178 sll addrTemp, address.index, address.scale
2179 addu addrTemp, addrTemp, address.base
2180 lui immTemp, (address.offset + 0x8000) >> 16
2181 addu addrTemp, addrTemp, immTemp
2182 lwc1 dest, (address.offset & 0xffff)(at)
2184 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2185 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2186 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
2187 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
2188 m_assembler
.lwc1(dest
, addrTempRegister
, address
.offset
);
2192 void loadDouble(ImplicitAddress address
, FPRegisterID dest
)
2196 li addrTemp, address.offset
2197 addu addrTemp, addrTemp, base
2198 lwc1 dest, 0(addrTemp)
2199 lwc1 dest+1, 4(addrTemp)
2201 move(TrustedImm32(address
.offset
), addrTempRegister
);
2202 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2203 m_assembler
.lwc1(dest
, addrTempRegister
, 0);
2204 m_assembler
.lwc1(FPRegisterID(dest
+ 1), addrTempRegister
, 4);
2206 if (address
.offset
>= -32768 && address
.offset
<= 32767
2208 m_assembler
.ldc1(dest
, address
.base
, address
.offset
);
2211 lui addrTemp, (offset + 0x8000) >> 16
2212 addu addrTemp, addrTemp, base
2213 ldc1 dest, (offset & 0xffff)(addrTemp)
2215 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
2216 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2217 m_assembler
.ldc1(dest
, addrTempRegister
, address
.offset
);
2222 void loadDouble(BaseIndex address
, FPRegisterID dest
)
2225 if (address
.offset
>= -32768 && address
.offset
<= 32767
2228 sll addrTemp, address.index, address.scale
2229 addu addrTemp, addrTemp, address.base
2230 lwc1 dest, address.offset(addrTemp)
2231 lwc1 dest+1, (address.offset+4)(addrTemp)
2233 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2234 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2235 m_assembler
.lwc1(dest
, addrTempRegister
, address
.offset
);
2236 m_assembler
.lwc1(FPRegisterID(dest
+ 1), addrTempRegister
, address
.offset
+ 4);
2239 sll addrTemp, address.index, address.scale
2240 addu addrTemp, addrTemp, address.base
2241 lui immTemp, (address.offset + 0x8000) >> 16
2242 addu addrTemp, addrTemp, immTemp
2243 lwc1 dest, (address.offset & 0xffff)(at)
2244 lwc1 dest+1, (address.offset & 0xffff + 4)(at)
2246 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2247 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2248 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
2249 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
2250 m_assembler
.lwc1(dest
, addrTempRegister
, address
.offset
);
2251 m_assembler
.lwc1(FPRegisterID(dest
+ 1), addrTempRegister
, address
.offset
+ 4);
2254 if (address
.offset
>= -32768 && address
.offset
<= 32767
2257 sll addrTemp, address.index, address.scale
2258 addu addrTemp, addrTemp, address.base
2259 ldc1 dest, address.offset(addrTemp)
2261 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2262 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2263 m_assembler
.ldc1(dest
, addrTempRegister
, address
.offset
);
2266 sll addrTemp, address.index, address.scale
2267 addu addrTemp, addrTemp, address.base
2268 lui immTemp, (address.offset + 0x8000) >> 16
2269 addu addrTemp, addrTemp, immTemp
2270 ldc1 dest, (address.offset & 0xffff)(at)
2272 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2273 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2274 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
2275 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
2276 m_assembler
.ldc1(dest
, addrTempRegister
, address
.offset
);
2281 void loadDouble(TrustedImmPtr address
, FPRegisterID dest
)
2285 li addrTemp, address
2286 lwc1 dest, 0(addrTemp)
2287 lwc1 dest+1, 4(addrTemp)
2289 move(address
, addrTempRegister
);
2290 m_assembler
.lwc1(dest
, addrTempRegister
, 0);
2291 m_assembler
.lwc1(FPRegisterID(dest
+ 1), addrTempRegister
, 4);
2294 li addrTemp, address
2295 ldc1 dest, 0(addrTemp)
2297 move(address
, addrTempRegister
);
2298 m_assembler
.ldc1(dest
, addrTempRegister
, 0);
2302 void storeFloat(FPRegisterID src
, BaseIndex address
)
2304 if (address
.offset
>= -32768 && address
.offset
<= 32767
2307 sll addrTemp, address.index, address.scale
2308 addu addrTemp, addrTemp, address.base
2309 swc1 src, address.offset(addrTemp)
2311 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2312 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2313 m_assembler
.swc1(src
, addrTempRegister
, address
.offset
);
2316 sll addrTemp, address.index, address.scale
2317 addu addrTemp, addrTemp, address.base
2318 lui immTemp, (address.offset + 0x8000) >> 16
2319 addu addrTemp, addrTemp, immTemp
2320 swc1 src, (address.offset & 0xffff)(at)
2322 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2323 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2324 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
2325 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
2326 m_assembler
.swc1(src
, addrTempRegister
, address
.offset
);
2330 void storeDouble(FPRegisterID src
, ImplicitAddress address
)
2334 li addrTemp, address.offset
2335 addu addrTemp, addrTemp, base
2336 swc1 dest, 0(addrTemp)
2337 swc1 dest+1, 4(addrTemp)
2339 move(TrustedImm32(address
.offset
), addrTempRegister
);
2340 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2341 m_assembler
.swc1(src
, addrTempRegister
, 0);
2342 m_assembler
.swc1(FPRegisterID(src
+ 1), addrTempRegister
, 4);
2344 if (address
.offset
>= -32768 && address
.offset
<= 32767
2346 m_assembler
.sdc1(src
, address
.base
, address
.offset
);
2349 lui addrTemp, (offset + 0x8000) >> 16
2350 addu addrTemp, addrTemp, base
2351 sdc1 src, (offset & 0xffff)(addrTemp)
2353 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
2354 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2355 m_assembler
.sdc1(src
, addrTempRegister
, address
.offset
);
2360 void storeDouble(FPRegisterID src
, BaseIndex address
)
2363 if (address
.offset
>= -32768 && address
.offset
<= 32767
2366 sll addrTemp, address.index, address.scale
2367 addu addrTemp, addrTemp, address.base
2368 swc1 src, address.offset(addrTemp)
2369 swc1 src+1, (address.offset + 4)(addrTemp)
2371 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2372 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2373 m_assembler
.swc1(src
, addrTempRegister
, address
.offset
);
2374 m_assembler
.swc1(FPRegisterID(src
+ 1), addrTempRegister
, address
.offset
+ 4);
2377 sll addrTemp, address.index, address.scale
2378 addu addrTemp, addrTemp, address.base
2379 lui immTemp, (address.offset + 0x8000) >> 16
2380 addu addrTemp, addrTemp, immTemp
2381 swc1 src, (address.offset & 0xffff)(at)
2382 swc1 src+1, (address.offset & 0xffff + 4)(at)
2384 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2385 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2386 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
2387 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
2388 m_assembler
.swc1(src
, addrTempRegister
, address
.offset
);
2389 m_assembler
.swc1(FPRegisterID(src
+ 1), addrTempRegister
, address
.offset
+ 4);
2392 if (address
.offset
>= -32768 && address
.offset
<= 32767
2395 sll addrTemp, address.index, address.scale
2396 addu addrTemp, addrTemp, address.base
2397 sdc1 src, address.offset(addrTemp)
2399 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2400 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2401 m_assembler
.sdc1(src
, addrTempRegister
, address
.offset
);
2404 sll addrTemp, address.index, address.scale
2405 addu addrTemp, addrTemp, address.base
2406 lui immTemp, (address.offset + 0x8000) >> 16
2407 addu addrTemp, addrTemp, immTemp
2408 sdc1 src, (address.offset & 0xffff)(at)
2410 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2411 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2412 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
2413 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
2414 m_assembler
.sdc1(src
, addrTempRegister
, address
.offset
);
2419 void storeDouble(FPRegisterID src
, TrustedImmPtr address
)
2422 move(address
, addrTempRegister
);
2423 m_assembler
.swc1(src
, addrTempRegister
, 0);
2424 m_assembler
.swc1(FPRegisterID(src
+ 1), addrTempRegister
, 4);
2426 move(address
, addrTempRegister
);
2427 m_assembler
.sdc1(src
, addrTempRegister
, 0);
2431 void moveDouble(FPRegisterID src
, FPRegisterID dest
)
2433 if (src
!= dest
|| m_fixedWidth
)
2434 m_assembler
.movd(dest
, src
);
2437 void swapDouble(FPRegisterID fr1
, FPRegisterID fr2
)
2439 moveDouble(fr1
, fpTempRegister
);
2440 moveDouble(fr2
, fr1
);
2441 moveDouble(fpTempRegister
, fr2
);
2444 void addDouble(FPRegisterID src
, FPRegisterID dest
)
2446 m_assembler
.addd(dest
, dest
, src
);
2449 void addDouble(FPRegisterID op1
, FPRegisterID op2
, FPRegisterID dest
)
2451 m_assembler
.addd(dest
, op1
, op2
);
2454 void addDouble(Address src
, FPRegisterID dest
)
2456 loadDouble(src
, fpTempRegister
);
2457 m_assembler
.addd(dest
, dest
, fpTempRegister
);
2460 void addDouble(AbsoluteAddress address
, FPRegisterID dest
)
2462 loadDouble(TrustedImmPtr(address
.m_ptr
), fpTempRegister
);
2463 m_assembler
.addd(dest
, dest
, fpTempRegister
);
2466 void subDouble(FPRegisterID src
, FPRegisterID dest
)
2468 m_assembler
.subd(dest
, dest
, src
);
2471 void subDouble(FPRegisterID op1
, FPRegisterID op2
, FPRegisterID dest
)
2473 m_assembler
.subd(dest
, op1
, op2
);
2476 void subDouble(Address src
, FPRegisterID dest
)
2478 loadDouble(src
, fpTempRegister
);
2479 m_assembler
.subd(dest
, dest
, fpTempRegister
);
2482 void mulDouble(FPRegisterID src
, FPRegisterID dest
)
2484 m_assembler
.muld(dest
, dest
, src
);
2487 void mulDouble(Address src
, FPRegisterID dest
)
2489 loadDouble(src
, fpTempRegister
);
2490 m_assembler
.muld(dest
, dest
, fpTempRegister
);
2493 void mulDouble(FPRegisterID op1
, FPRegisterID op2
, FPRegisterID dest
)
2495 m_assembler
.muld(dest
, op1
, op2
);
2498 void divDouble(FPRegisterID src
, FPRegisterID dest
)
2500 m_assembler
.divd(dest
, dest
, src
);
2503 void divDouble(FPRegisterID op1
, FPRegisterID op2
, FPRegisterID dest
)
2505 m_assembler
.divd(dest
, op1
, op2
);
2508 void divDouble(Address src
, FPRegisterID dest
)
2510 loadDouble(src
, fpTempRegister
);
2511 m_assembler
.divd(dest
, dest
, fpTempRegister
);
2514 void negateDouble(FPRegisterID src
, FPRegisterID dest
)
2516 m_assembler
.negd(dest
, src
);
2519 void convertInt32ToDouble(RegisterID src
, FPRegisterID dest
)
2521 m_assembler
.mtc1(src
, fpTempRegister
);
2522 m_assembler
.cvtdw(dest
, fpTempRegister
);
2525 void convertInt32ToDouble(Address src
, FPRegisterID dest
)
2527 load32(src
, dataTempRegister
);
2528 m_assembler
.mtc1(dataTempRegister
, fpTempRegister
);
2529 m_assembler
.cvtdw(dest
, fpTempRegister
);
2532 void convertInt32ToDouble(AbsoluteAddress src
, FPRegisterID dest
)
2534 load32(src
.m_ptr
, dataTempRegister
);
2535 m_assembler
.mtc1(dataTempRegister
, fpTempRegister
);
2536 m_assembler
.cvtdw(dest
, fpTempRegister
);
2539 void convertFloatToDouble(FPRegisterID src
, FPRegisterID dst
)
2541 m_assembler
.cvtds(dst
, src
);
2544 void convertDoubleToFloat(FPRegisterID src
, FPRegisterID dst
)
2546 m_assembler
.cvtsd(dst
, src
);
2549 void insertRelaxationWords()
2551 /* We need four words for relaxation. */
2552 m_assembler
.beq(MIPSRegisters::zero
, MIPSRegisters::zero
, 3); // Jump over nops;
2560 m_assembler
.appendJump();
2563 insertRelaxationWords();
2564 return Jump(m_assembler
.label());
2569 m_assembler
.appendJump();
2572 insertRelaxationWords();
2573 return Jump(m_assembler
.label());
2576 Jump
branchEqual(RegisterID rs
, RegisterID rt
)
2580 m_assembler
.appendJump();
2581 m_assembler
.beq(rs
, rt
, 0);
2583 insertRelaxationWords();
2584 return Jump(m_assembler
.label());
2587 Jump
branchNotEqual(RegisterID rs
, RegisterID rt
)
2591 m_assembler
.appendJump();
2592 m_assembler
.bne(rs
, rt
, 0);
2594 insertRelaxationWords();
2595 return Jump(m_assembler
.label());
2598 Jump
branchDouble(DoubleCondition cond
, FPRegisterID left
, FPRegisterID right
)
2600 if (cond
== DoubleEqual
) {
2601 m_assembler
.ceqd(left
, right
);
2602 return branchTrue();
2604 if (cond
== DoubleNotEqual
) {
2605 m_assembler
.cueqd(left
, right
);
2606 return branchFalse(); // false
2608 if (cond
== DoubleGreaterThan
) {
2609 m_assembler
.cngtd(left
, right
);
2610 return branchFalse(); // false
2612 if (cond
== DoubleGreaterThanOrEqual
) {
2613 m_assembler
.cnged(left
, right
);
2614 return branchFalse(); // false
2616 if (cond
== DoubleLessThan
) {
2617 m_assembler
.cltd(left
, right
);
2618 return branchTrue();
2620 if (cond
== DoubleLessThanOrEqual
) {
2621 m_assembler
.cled(left
, right
);
2622 return branchTrue();
2624 if (cond
== DoubleEqualOrUnordered
) {
2625 m_assembler
.cueqd(left
, right
);
2626 return branchTrue();
2628 if (cond
== DoubleNotEqualOrUnordered
) {
2629 m_assembler
.ceqd(left
, right
);
2630 return branchFalse(); // false
2632 if (cond
== DoubleGreaterThanOrUnordered
) {
2633 m_assembler
.coled(left
, right
);
2634 return branchFalse(); // false
2636 if (cond
== DoubleGreaterThanOrEqualOrUnordered
) {
2637 m_assembler
.coltd(left
, right
);
2638 return branchFalse(); // false
2640 if (cond
== DoubleLessThanOrUnordered
) {
2641 m_assembler
.cultd(left
, right
);
2642 return branchTrue();
2644 if (cond
== DoubleLessThanOrEqualOrUnordered
) {
2645 m_assembler
.culed(left
, right
);
2646 return branchTrue();
2653 // Truncates 'src' to an integer, and places the resulting 'dest'.
2654 // If the result is not representable as a 32 bit value, branch.
2655 // May also branch for some values that are representable in 32 bits
2656 // (specifically, in this case, INT_MAX 0x7fffffff).
2657 enum BranchTruncateType
{ BranchIfTruncateFailed
, BranchIfTruncateSuccessful
};
2658 Jump
branchTruncateDoubleToInt32(FPRegisterID src
, RegisterID dest
, BranchTruncateType branchType
= BranchIfTruncateFailed
)
2660 m_assembler
.truncwd(fpTempRegister
, src
);
2661 m_assembler
.mfc1(dest
, fpTempRegister
);
2662 return branch32(branchType
== BranchIfTruncateFailed
? Equal
: NotEqual
, dest
, TrustedImm32(0x7fffffff));
2665 Jump
branchTruncateDoubleToUint32(FPRegisterID src
, RegisterID dest
, BranchTruncateType branchType
= BranchIfTruncateFailed
)
2667 m_assembler
.truncwd(fpTempRegister
, src
);
2668 m_assembler
.mfc1(dest
, fpTempRegister
);
2669 return branch32(branchType
== BranchIfTruncateFailed
? Equal
: NotEqual
, dest
, TrustedImm32(0));
2672 // Result is undefined if the value is outside of the integer range.
2673 void truncateDoubleToInt32(FPRegisterID src
, RegisterID dest
)
2675 m_assembler
.truncwd(fpTempRegister
, src
);
2676 m_assembler
.mfc1(dest
, fpTempRegister
);
2679 // Result is undefined if src > 2^31
2680 void truncateDoubleToUint32(FPRegisterID src
, RegisterID dest
)
2682 m_assembler
.truncwd(fpTempRegister
, src
);
2683 m_assembler
.mfc1(dest
, fpTempRegister
);
2686 // Convert 'src' to an integer, and places the resulting 'dest'.
2687 // If the result is not representable as a 32 bit value, branch.
2688 // May also branch for some values that are representable in 32 bits
2689 // (specifically, in this case, 0).
2690 void branchConvertDoubleToInt32(FPRegisterID src
, RegisterID dest
, JumpList
& failureCases
, FPRegisterID fpTemp
, bool negZeroCheck
= true)
2692 m_assembler
.cvtwd(fpTempRegister
, src
);
2693 m_assembler
.mfc1(dest
, fpTempRegister
);
2695 // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
2697 failureCases
.append(branch32(Equal
, dest
, MIPSRegisters::zero
));
2699 // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
2700 convertInt32ToDouble(dest
, fpTemp
);
2701 failureCases
.append(branchDouble(DoubleNotEqualOrUnordered
, fpTemp
, src
));
2704 Jump
branchDoubleNonZero(FPRegisterID reg
, FPRegisterID scratch
)
2706 m_assembler
.vmov(scratch
, MIPSRegisters::zero
, MIPSRegisters::zero
);
2707 return branchDouble(DoubleNotEqual
, reg
, scratch
);
2710 Jump
branchDoubleZeroOrNaN(FPRegisterID reg
, FPRegisterID scratch
)
2712 m_assembler
.vmov(scratch
, MIPSRegisters::zero
, MIPSRegisters::zero
);
2713 return branchDouble(DoubleEqualOrUnordered
, reg
, scratch
);
2716 // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc.
2717 static RelationalCondition
invert(RelationalCondition cond
)
2719 RelationalCondition r
;
2722 else if (cond
== NotEqual
)
2724 else if (cond
== Above
)
2726 else if (cond
== AboveOrEqual
)
2728 else if (cond
== Below
)
2730 else if (cond
== BelowOrEqual
)
2732 else if (cond
== GreaterThan
)
2733 r
= LessThanOrEqual
;
2734 else if (cond
== GreaterThanOrEqual
)
2736 else if (cond
== LessThan
)
2737 r
= GreaterThanOrEqual
;
2738 else if (cond
== LessThanOrEqual
)
2753 static FunctionPtr
readCallTarget(CodeLocationCall call
)
2755 return FunctionPtr(reinterpret_cast<void(*)()>(MIPSAssembler::readCallTarget(call
.dataLocation())));
2758 static void replaceWithJump(CodeLocationLabel instructionStart
, CodeLocationLabel destination
)
2760 MIPSAssembler::replaceWithJump(instructionStart
.dataLocation(), destination
.dataLocation());
2763 static ptrdiff_t maxJumpReplacementSize()
2765 MIPSAssembler::maxJumpReplacementSize();
2769 static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; }
2771 static CodeLocationLabel
startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label
)
2773 return label
.labelAtOffset(0);
2776 static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart
, RegisterID
, void* initialValue
)
2778 MIPSAssembler::revertJumpToMove(instructionStart
.dataLocation(), immTempRegister
, reinterpret_cast<int>(initialValue
) & 0xffff);
2781 static CodeLocationLabel
startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr
)
2783 UNREACHABLE_FOR_PLATFORM();
2784 return CodeLocationLabel();
2787 static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel
, Address
, void*)
2789 UNREACHABLE_FOR_PLATFORM();
2794 // If m_fixedWidth is true, we will generate a fixed number of instructions.
2795 // Otherwise, we can emit any number of instructions.
2798 friend class LinkBuffer
;
2799 friend class RepatchBuffer
;
2801 static void linkCall(void* code
, Call call
, FunctionPtr function
)
2803 MIPSAssembler::linkCall(code
, call
.m_label
, function
.value());
2806 static void repatchCall(CodeLocationCall call
, CodeLocationLabel destination
)
2808 MIPSAssembler::relinkCall(call
.dataLocation(), destination
.executableAddress());
2811 static void repatchCall(CodeLocationCall call
, FunctionPtr destination
)
2813 MIPSAssembler::relinkCall(call
.dataLocation(), destination
.executableAddress());
2820 #endif // ENABLE(ASSEMBLER) && CPU(MIPS)
2822 #endif // MacroAssemblerMIPS_h