2 * Copyright (C) 2008 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
> {
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 returnAddressRegister
= MIPSRegisters::ra
;
106 // Integer arithmetic operations:
108 // Operations are typically two operand - operation(source, srcDst)
109 // For many operations the source may be an TrustedImm32, the srcDst operand
110 // may often be a memory location (explictly described using an Address
113 void add32(RegisterID src
, RegisterID dest
)
115 m_assembler
.addu(dest
, dest
, src
);
118 void add32(RegisterID op1
, RegisterID op2
, RegisterID dest
)
120 m_assembler
.addu(dest
, op1
, op2
);
123 void add32(TrustedImm32 imm
, RegisterID dest
)
125 add32(imm
, dest
, dest
);
128 void add32(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
130 if (imm
.m_value
>= -32768 && imm
.m_value
<= 32767
135 m_assembler
.addiu(dest
, src
, imm
.m_value
);
139 addu dest, src, immTemp
141 move(imm
, immTempRegister
);
142 m_assembler
.addu(dest
, src
, immTempRegister
);
146 void add32(RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
148 add32(imm
, src
, dest
);
151 void add32(TrustedImm32 imm
, Address address
)
153 if (address
.offset
>= -32768 && address
.offset
<= 32767
156 lw dataTemp, offset(base)
158 addu dataTemp, dataTemp, immTemp
159 sw dataTemp, offset(base)
161 m_assembler
.lw(dataTempRegister
, address
.base
, address
.offset
);
162 if (imm
.m_value
>= -32768 && imm
.m_value
<= 32767
164 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, imm
.m_value
);
166 move(imm
, immTempRegister
);
167 m_assembler
.addu(dataTempRegister
, dataTempRegister
, immTempRegister
);
169 m_assembler
.sw(dataTempRegister
, address
.base
, address
.offset
);
172 lui addrTemp, (offset + 0x8000) >> 16
173 addu addrTemp, addrTemp, base
174 lw dataTemp, (offset & 0xffff)(addrTemp)
176 addu dataTemp, dataTemp, immTemp
177 sw dataTemp, (offset & 0xffff)(addrTemp)
179 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
180 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
181 m_assembler
.lw(dataTempRegister
, addrTempRegister
, address
.offset
);
183 if (imm
.m_value
>= -32768 && imm
.m_value
<= 32767 && !m_fixedWidth
)
184 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, imm
.m_value
);
186 move(imm
, immTempRegister
);
187 m_assembler
.addu(dataTempRegister
, dataTempRegister
, immTempRegister
);
189 m_assembler
.sw(dataTempRegister
, addrTempRegister
, address
.offset
);
193 void add32(Address src
, RegisterID dest
)
195 load32(src
, dataTempRegister
);
196 add32(dataTempRegister
, dest
);
199 void add32(AbsoluteAddress src
, RegisterID dest
)
201 load32(src
.m_ptr
, dataTempRegister
);
202 add32(dataTempRegister
, dest
);
205 void add32(RegisterID src
, Address dest
)
207 if (dest
.offset
>= -32768 && dest
.offset
<= 32767 && !m_fixedWidth
) {
209 lw dataTemp, offset(base)
210 addu dataTemp, dataTemp, src
211 sw dataTemp, offset(base)
213 m_assembler
.lw(dataTempRegister
, dest
.base
, dest
.offset
);
214 m_assembler
.addu(dataTempRegister
, dataTempRegister
, src
);
215 m_assembler
.sw(dataTempRegister
, dest
.base
, dest
.offset
);
218 lui addrTemp, (offset + 0x8000) >> 16
219 addu addrTemp, addrTemp, base
220 lw dataTemp, (offset & 0xffff)(addrTemp)
221 addu dataTemp, dataTemp, src
222 sw dataTemp, (offset & 0xffff)(addrTemp)
224 m_assembler
.lui(addrTempRegister
, (dest
.offset
+ 0x8000) >> 16);
225 m_assembler
.addu(addrTempRegister
, addrTempRegister
, dest
.base
);
226 m_assembler
.lw(dataTempRegister
, addrTempRegister
, dest
.offset
);
227 m_assembler
.addu(dataTempRegister
, dataTempRegister
, src
);
228 m_assembler
.sw(dataTempRegister
, addrTempRegister
, dest
.offset
);
232 void add32(TrustedImm32 imm
, AbsoluteAddress address
)
237 lw cmpTemp, 0(addrTemp)
238 addu dataTemp, cmpTemp, immTemp
239 sw dataTemp, 0(addrTemp)
241 move(TrustedImmPtr(address
.m_ptr
), addrTempRegister
);
242 m_assembler
.lw(cmpTempRegister
, addrTempRegister
, 0);
243 if (imm
.m_value
>= -32768 && imm
.m_value
<= 32767 && !m_fixedWidth
)
244 m_assembler
.addiu(dataTempRegister
, cmpTempRegister
, imm
.m_value
);
246 move(imm
, immTempRegister
);
247 m_assembler
.addu(dataTempRegister
, cmpTempRegister
, immTempRegister
);
249 m_assembler
.sw(dataTempRegister
, addrTempRegister
, 0);
252 void add64(TrustedImm32 imm
, AbsoluteAddress address
)
256 sltu immTemp, dataTemp, cmpTemp # set carry-in bit
257 lw dataTemp, 4(addrTemp)
258 addiu dataTemp, imm.m_value >> 31 ? -1 : 0
259 addu dataTemp, dataTemp, immTemp
260 sw dataTemp, 4(addrTemp)
263 m_assembler
.sltu(immTempRegister
, dataTempRegister
, cmpTempRegister
);
264 m_assembler
.lw(dataTempRegister
, addrTempRegister
, 4);
265 if (imm
.m_value
>> 31)
266 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, -1);
267 m_assembler
.addu(dataTempRegister
, dataTempRegister
, immTempRegister
);
268 m_assembler
.sw(dataTempRegister
, addrTempRegister
, 4);
271 void and32(Address src
, RegisterID dest
)
273 load32(src
, dataTempRegister
);
274 and32(dataTempRegister
, dest
);
277 void and32(RegisterID src
, RegisterID dest
)
279 m_assembler
.andInsn(dest
, dest
, src
);
282 void and32(RegisterID op1
, RegisterID op2
, RegisterID dest
)
284 m_assembler
.andInsn(dest
, op1
, op2
);
287 void and32(TrustedImm32 imm
, RegisterID dest
)
289 if (!imm
.m_value
&& !m_fixedWidth
)
290 move(MIPSRegisters::zero
, dest
);
291 else if (imm
.m_value
> 0 && imm
.m_value
< 65535 && !m_fixedWidth
)
292 m_assembler
.andi(dest
, dest
, imm
.m_value
);
296 and dest, dest, immTemp
298 move(imm
, immTempRegister
);
299 m_assembler
.andInsn(dest
, dest
, immTempRegister
);
303 void and32(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
305 if (!imm
.m_value
&& !m_fixedWidth
)
306 move(MIPSRegisters::zero
, dest
);
307 else if (imm
.m_value
> 0 && imm
.m_value
< 65535 && !m_fixedWidth
)
308 m_assembler
.andi(dest
, src
, imm
.m_value
);
310 move(imm
, immTempRegister
);
311 m_assembler
.andInsn(dest
, src
, immTempRegister
);
315 void lshift32(RegisterID shiftAmount
, RegisterID dest
)
317 m_assembler
.sllv(dest
, dest
, shiftAmount
);
320 void lshift32(RegisterID src
, RegisterID shiftAmount
, RegisterID dest
)
322 m_assembler
.sllv(dest
, src
, shiftAmount
);
325 void lshift32(TrustedImm32 imm
, RegisterID dest
)
327 move(imm
, immTempRegister
);
328 m_assembler
.sllv(dest
, dest
, immTempRegister
);
331 void lshift32(RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
333 move(imm
, immTempRegister
);
334 m_assembler
.sllv(dest
, src
, immTempRegister
);
337 void mul32(RegisterID src
, RegisterID dest
)
339 m_assembler
.mul(dest
, dest
, src
);
342 void mul32(RegisterID op1
, RegisterID op2
, RegisterID dest
)
344 m_assembler
.mul(dest
, op1
, op2
);
347 void mul32(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
349 if (!imm
.m_value
&& !m_fixedWidth
)
350 move(MIPSRegisters::zero
, dest
);
351 else if (imm
.m_value
== 1 && !m_fixedWidth
)
356 mul dest, src, dataTemp
358 move(imm
, dataTempRegister
);
359 m_assembler
.mul(dest
, src
, dataTempRegister
);
363 void neg32(RegisterID srcDest
)
365 m_assembler
.subu(srcDest
, MIPSRegisters::zero
, srcDest
);
368 void or32(RegisterID src
, RegisterID dest
)
370 m_assembler
.orInsn(dest
, dest
, src
);
373 void or32(RegisterID op1
, RegisterID op2
, RegisterID dest
)
375 m_assembler
.orInsn(dest
, op1
, op2
);
378 void or32(TrustedImm32 imm
, RegisterID dest
)
380 if (!imm
.m_value
&& !m_fixedWidth
)
383 if (imm
.m_value
> 0 && imm
.m_value
< 65535
385 m_assembler
.ori(dest
, dest
, imm
.m_value
);
391 or dest, dest, dataTemp
393 move(imm
, dataTempRegister
);
394 m_assembler
.orInsn(dest
, dest
, dataTempRegister
);
397 void or32(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
399 if (!imm
.m_value
&& !m_fixedWidth
)
402 if (imm
.m_value
> 0 && imm
.m_value
< 65535 && !m_fixedWidth
) {
403 m_assembler
.ori(dest
, src
, imm
.m_value
);
409 or dest, src, dataTemp
411 move(imm
, dataTempRegister
);
412 m_assembler
.orInsn(dest
, src
, dataTempRegister
);
415 void or32(RegisterID src
, AbsoluteAddress dest
)
417 load32(dest
.m_ptr
, dataTempRegister
);
418 m_assembler
.orInsn(dataTempRegister
, dataTempRegister
, src
);
419 store32(dataTempRegister
, dest
.m_ptr
);
422 void rshift32(RegisterID shiftAmount
, RegisterID dest
)
424 m_assembler
.srav(dest
, dest
, shiftAmount
);
427 void rshift32(RegisterID src
, RegisterID shiftAmount
, RegisterID dest
)
429 m_assembler
.srav(dest
, src
, shiftAmount
);
432 void rshift32(TrustedImm32 imm
, RegisterID dest
)
434 m_assembler
.sra(dest
, dest
, imm
.m_value
);
437 void rshift32(RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
439 m_assembler
.sra(dest
, src
, imm
.m_value
);
442 void urshift32(RegisterID shiftAmount
, RegisterID dest
)
444 m_assembler
.srlv(dest
, dest
, shiftAmount
);
447 void urshift32(RegisterID src
, RegisterID shiftAmount
, RegisterID dest
)
449 m_assembler
.srlv(dest
, src
, shiftAmount
);
452 void urshift32(TrustedImm32 imm
, RegisterID dest
)
454 m_assembler
.srl(dest
, dest
, imm
.m_value
);
457 void urshift32(RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
459 m_assembler
.srl(dest
, src
, imm
.m_value
);
462 void sub32(RegisterID src
, RegisterID dest
)
464 m_assembler
.subu(dest
, dest
, src
);
467 void sub32(RegisterID op1
, RegisterID op2
, RegisterID dest
)
469 m_assembler
.subu(dest
, op1
, op2
);
472 void sub32(TrustedImm32 imm
, RegisterID dest
)
474 if (imm
.m_value
>= -32767 && imm
.m_value
<= 32768
479 m_assembler
.addiu(dest
, dest
, -imm
.m_value
);
483 subu dest, src, immTemp
485 move(imm
, immTempRegister
);
486 m_assembler
.subu(dest
, dest
, immTempRegister
);
490 void sub32(RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
492 if (imm
.m_value
>= -32767 && imm
.m_value
<= 32768
497 m_assembler
.addiu(dest
, src
, -imm
.m_value
);
501 subu dest, src, immTemp
503 move(imm
, immTempRegister
);
504 m_assembler
.subu(dest
, src
, immTempRegister
);
508 void sub32(TrustedImm32 imm
, Address address
)
510 if (address
.offset
>= -32768 && address
.offset
<= 32767
513 lw dataTemp, offset(base)
515 subu dataTemp, dataTemp, immTemp
516 sw dataTemp, offset(base)
518 m_assembler
.lw(dataTempRegister
, address
.base
, address
.offset
);
519 if (imm
.m_value
>= -32767 && imm
.m_value
<= 32768 && !m_fixedWidth
)
520 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, -imm
.m_value
);
522 move(imm
, immTempRegister
);
523 m_assembler
.subu(dataTempRegister
, dataTempRegister
, immTempRegister
);
525 m_assembler
.sw(dataTempRegister
, address
.base
, address
.offset
);
528 lui addrTemp, (offset + 0x8000) >> 16
529 addu addrTemp, addrTemp, base
530 lw dataTemp, (offset & 0xffff)(addrTemp)
532 subu dataTemp, dataTemp, immTemp
533 sw dataTemp, (offset & 0xffff)(addrTemp)
535 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
536 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
537 m_assembler
.lw(dataTempRegister
, addrTempRegister
, address
.offset
);
539 if (imm
.m_value
>= -32767 && imm
.m_value
<= 32768
541 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, -imm
.m_value
);
543 move(imm
, immTempRegister
);
544 m_assembler
.subu(dataTempRegister
, dataTempRegister
, immTempRegister
);
546 m_assembler
.sw(dataTempRegister
, addrTempRegister
, address
.offset
);
550 void sub32(Address src
, RegisterID dest
)
552 load32(src
, dataTempRegister
);
553 sub32(dataTempRegister
, dest
);
556 void sub32(TrustedImm32 imm
, AbsoluteAddress address
)
561 lw dataTemp, 0(addrTemp)
562 subu dataTemp, dataTemp, immTemp
563 sw dataTemp, 0(addrTemp)
565 move(TrustedImmPtr(address
.m_ptr
), addrTempRegister
);
566 m_assembler
.lw(dataTempRegister
, addrTempRegister
, 0);
568 if (imm
.m_value
>= -32767 && imm
.m_value
<= 32768 && !m_fixedWidth
)
569 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, -imm
.m_value
);
571 move(imm
, immTempRegister
);
572 m_assembler
.subu(dataTempRegister
, dataTempRegister
, immTempRegister
);
574 m_assembler
.sw(dataTempRegister
, addrTempRegister
, 0);
577 void xor32(RegisterID src
, RegisterID dest
)
579 m_assembler
.xorInsn(dest
, dest
, src
);
582 void xor32(RegisterID op1
, RegisterID op2
, RegisterID dest
)
584 m_assembler
.xorInsn(dest
, op1
, op2
);
587 void xor32(TrustedImm32 imm
, RegisterID dest
)
589 if (imm
.m_value
== -1) {
590 m_assembler
.nor(dest
, dest
, MIPSRegisters::zero
);
596 xor dest, dest, immTemp
598 move(imm
, immTempRegister
);
599 m_assembler
.xorInsn(dest
, dest
, immTempRegister
);
602 void xor32(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
604 if (imm
.m_value
== -1) {
605 m_assembler
.nor(dest
, src
, MIPSRegisters::zero
);
611 xor dest, dest, immTemp
613 move(imm
, immTempRegister
);
614 m_assembler
.xorInsn(dest
, src
, immTempRegister
);
617 void sqrtDouble(FPRegisterID src
, FPRegisterID dst
)
619 m_assembler
.sqrtd(dst
, src
);
622 void absDouble(FPRegisterID
, FPRegisterID
)
624 RELEASE_ASSERT_NOT_REACHED();
627 ConvertibleLoadLabel
convertibleLoadPtr(Address address
, RegisterID dest
)
629 ConvertibleLoadLabel
result(this);
631 lui addrTemp, (offset + 0x8000) >> 16
632 addu addrTemp, addrTemp, base
633 lw dest, (offset & 0xffff)(addrTemp)
635 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
636 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
637 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
641 // Memory access operations:
643 // Loads are of the form load(address, destination) and stores of the form
644 // store(source, address). The source for a store may be an TrustedImm32. Address
645 // operand objects to loads and store will be implicitly constructed if a
646 // register is passed.
648 /* Need to use zero-extened load byte for load8. */
649 void load8(ImplicitAddress address
, RegisterID dest
)
651 if (address
.offset
>= -32768 && address
.offset
<= 32767
653 m_assembler
.lbu(dest
, address
.base
, address
.offset
);
656 lui addrTemp, (offset + 0x8000) >> 16
657 addu addrTemp, addrTemp, base
658 lbu dest, (offset & 0xffff)(addrTemp)
660 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
661 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
662 m_assembler
.lbu(dest
, addrTempRegister
, address
.offset
);
666 void load8(BaseIndex address
, RegisterID dest
)
668 if (address
.offset
>= -32768 && address
.offset
<= 32767
671 sll addrTemp, address.index, address.scale
672 addu addrTemp, addrTemp, address.base
673 lbu dest, address.offset(addrTemp)
675 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
676 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
677 m_assembler
.lbu(dest
, addrTempRegister
, address
.offset
);
680 sll addrTemp, address.index, address.scale
681 addu addrTemp, addrTemp, address.base
682 lui immTemp, (address.offset + 0x8000) >> 16
683 addu addrTemp, addrTemp, immTemp
684 lbu dest, (address.offset & 0xffff)(at)
686 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
687 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
688 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
689 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
690 m_assembler
.lbu(dest
, addrTempRegister
, address
.offset
);
694 void load8Signed(BaseIndex address
, RegisterID dest
)
696 if (address
.offset
>= -32768 && address
.offset
<= 32767
699 sll addrTemp, address.index, address.scale
700 addu addrTemp, addrTemp, address.base
701 lb dest, address.offset(addrTemp)
703 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
704 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
705 m_assembler
.lb(dest
, addrTempRegister
, address
.offset
);
708 sll addrTemp, address.index, address.scale
709 addu addrTemp, addrTemp, address.base
710 lui immTemp, (address.offset + 0x8000) >> 16
711 addu addrTemp, addrTemp, immTemp
712 lb dest, (address.offset & 0xffff)(at)
714 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
715 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
716 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
717 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
718 m_assembler
.lb(dest
, addrTempRegister
, address
.offset
);
722 void load32(ImplicitAddress address
, RegisterID dest
)
724 if (address
.offset
>= -32768 && address
.offset
<= 32767
726 m_assembler
.lw(dest
, address
.base
, address
.offset
);
729 lui addrTemp, (offset + 0x8000) >> 16
730 addu addrTemp, addrTemp, base
731 lw dest, (offset & 0xffff)(addrTemp)
733 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
734 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
735 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
739 void load32(BaseIndex address
, RegisterID dest
)
741 if (address
.offset
>= -32768 && address
.offset
<= 32767
744 sll addrTemp, address.index, address.scale
745 addu addrTemp, addrTemp, address.base
746 lw dest, address.offset(addrTemp)
748 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
749 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
750 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
753 sll addrTemp, address.index, address.scale
754 addu addrTemp, addrTemp, address.base
755 lui immTemp, (address.offset + 0x8000) >> 16
756 addu addrTemp, addrTemp, immTemp
757 lw dest, (address.offset & 0xffff)(at)
759 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
760 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
761 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
762 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
763 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
767 void load16Unaligned(BaseIndex address
, RegisterID dest
)
769 load16(address
, dest
);
772 void load32WithUnalignedHalfWords(BaseIndex address
, RegisterID dest
)
774 if (address
.offset
>= -32768 && address
.offset
<= 32764
777 sll addrTemp, address.index, address.scale
778 addu addrTemp, addrTemp, address.base
780 lwl dest, address.offset(addrTemp)
781 lwr dest, address.offset+3(addrTemp)
783 lwl dest, address.offset+3(addrTemp)
784 lwr dest, address.offset(addrTemp)
786 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
787 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
789 m_assembler
.lwl(dest
, addrTempRegister
, address
.offset
);
790 m_assembler
.lwr(dest
, addrTempRegister
, address
.offset
+ 3);
792 m_assembler
.lwl(dest
, addrTempRegister
, address
.offset
+ 3);
793 m_assembler
.lwr(dest
, addrTempRegister
, address
.offset
);
798 sll addrTemp, address.index, address.scale
799 addu addrTemp, addrTemp, address.base
800 lui immTemp, address.offset >> 16
801 ori immTemp, immTemp, address.offset & 0xffff
802 addu addrTemp, addrTemp, immTemp
810 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
811 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
812 m_assembler
.lui(immTempRegister
, address
.offset
>> 16);
813 m_assembler
.ori(immTempRegister
, immTempRegister
, address
.offset
);
814 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
816 m_assembler
.lwl(dest
, addrTempRegister
, 0);
817 m_assembler
.lwr(dest
, addrTempRegister
, 3);
819 m_assembler
.lwl(dest
, addrTempRegister
, 3);
820 m_assembler
.lwr(dest
, addrTempRegister
, 0);
825 void load32(const void* address
, RegisterID dest
)
831 move(TrustedImmPtr(address
), addrTempRegister
);
832 m_assembler
.lw(dest
, addrTempRegister
, 0);
835 DataLabel32
load32WithAddressOffsetPatch(Address address
, RegisterID dest
)
839 lui addrTemp, address.offset >> 16
840 ori addrTemp, addrTemp, address.offset & 0xffff
841 addu addrTemp, addrTemp, address.base
844 DataLabel32
dataLabel(this);
845 move(TrustedImm32(address
.offset
), addrTempRegister
);
846 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
847 m_assembler
.lw(dest
, addrTempRegister
, 0);
848 m_fixedWidth
= false;
852 DataLabelCompact
load32WithCompactAddressOffsetPatch(Address address
, RegisterID dest
)
854 DataLabelCompact
dataLabel(this);
855 load32WithAddressOffsetPatch(address
, dest
);
859 /* Need to use zero-extened load half-word for load16. */
860 void load16(ImplicitAddress address
, RegisterID dest
)
862 if (address
.offset
>= -32768 && address
.offset
<= 32767
864 m_assembler
.lhu(dest
, address
.base
, address
.offset
);
867 lui addrTemp, (offset + 0x8000) >> 16
868 addu addrTemp, addrTemp, base
869 lhu dest, (offset & 0xffff)(addrTemp)
871 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
872 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
873 m_assembler
.lhu(dest
, addrTempRegister
, address
.offset
);
877 /* Need to use zero-extened load half-word for load16. */
878 void load16(BaseIndex address
, RegisterID dest
)
880 if (address
.offset
>= -32768 && address
.offset
<= 32767
883 sll addrTemp, address.index, address.scale
884 addu addrTemp, addrTemp, address.base
885 lhu dest, address.offset(addrTemp)
887 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
888 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
889 m_assembler
.lhu(dest
, addrTempRegister
, address
.offset
);
892 sll addrTemp, address.index, address.scale
893 addu addrTemp, addrTemp, address.base
894 lui immTemp, (address.offset + 0x8000) >> 16
895 addu addrTemp, addrTemp, immTemp
896 lhu dest, (address.offset & 0xffff)(addrTemp)
898 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
899 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
900 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
901 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
902 m_assembler
.lhu(dest
, addrTempRegister
, address
.offset
);
906 void load16Signed(BaseIndex address
, RegisterID dest
)
908 if (address
.offset
>= -32768 && address
.offset
<= 32767
911 sll addrTemp, address.index, address.scale
912 addu addrTemp, addrTemp, address.base
913 lh dest, address.offset(addrTemp)
915 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
916 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
917 m_assembler
.lh(dest
, addrTempRegister
, address
.offset
);
920 sll addrTemp, address.index, address.scale
921 addu addrTemp, addrTemp, address.base
922 lui immTemp, (address.offset + 0x8000) >> 16
923 addu addrTemp, addrTemp, immTemp
924 lh dest, (address.offset & 0xffff)(addrTemp)
926 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
927 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
928 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
929 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
930 m_assembler
.lh(dest
, addrTempRegister
, address
.offset
);
934 DataLabel32
store32WithAddressOffsetPatch(RegisterID src
, Address address
)
938 lui addrTemp, address.offset >> 16
939 ori addrTemp, addrTemp, address.offset & 0xffff
940 addu addrTemp, addrTemp, address.base
943 DataLabel32
dataLabel(this);
944 move(TrustedImm32(address
.offset
), addrTempRegister
);
945 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
946 m_assembler
.sw(src
, addrTempRegister
, 0);
947 m_fixedWidth
= false;
951 void store8(RegisterID src
, BaseIndex address
)
953 if (address
.offset
>= -32768 && address
.offset
<= 32767
956 sll addrTemp, address.index, address.scale
957 addu addrTemp, addrTemp, address.base
958 sb src, address.offset(addrTemp)
960 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
961 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
962 m_assembler
.sb(src
, addrTempRegister
, address
.offset
);
965 sll addrTemp, address.index, address.scale
966 addu addrTemp, addrTemp, address.base
967 lui immTemp, (address.offset + 0x8000) >> 16
968 addu addrTemp, addrTemp, immTemp
969 sb src, (address.offset & 0xffff)(at)
971 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
972 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
973 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
974 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
975 m_assembler
.sb(src
, addrTempRegister
, address
.offset
);
979 void store8(TrustedImm32 imm
, void* address
)
986 if (!imm
.m_value
&& !m_fixedWidth
) {
987 move(TrustedImmPtr(address
), addrTempRegister
);
988 m_assembler
.sb(MIPSRegisters::zero
, addrTempRegister
, 0);
990 move(imm
, immTempRegister
);
991 move(TrustedImmPtr(address
), addrTempRegister
);
992 m_assembler
.sb(immTempRegister
, addrTempRegister
, 0);
996 void store16(RegisterID src
, BaseIndex address
)
998 if (address
.offset
>= -32768 && address
.offset
<= 32767
1001 sll addrTemp, address.index, address.scale
1002 addu addrTemp, addrTemp, address.base
1003 sh src, address.offset(addrTemp)
1005 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
1006 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1007 m_assembler
.sh(src
, addrTempRegister
, address
.offset
);
1010 sll addrTemp, address.index, address.scale
1011 addu addrTemp, addrTemp, address.base
1012 lui immTemp, (address.offset + 0x8000) >> 16
1013 addu addrTemp, addrTemp, immTemp
1014 sh src, (address.offset & 0xffff)(at)
1016 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
1017 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1018 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
1019 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
1020 m_assembler
.sh(src
, addrTempRegister
, address
.offset
);
1024 void store32(RegisterID src
, ImplicitAddress address
)
1026 if (address
.offset
>= -32768 && address
.offset
<= 32767
1028 m_assembler
.sw(src
, address
.base
, address
.offset
);
1031 lui addrTemp, (offset + 0x8000) >> 16
1032 addu addrTemp, addrTemp, base
1033 sw src, (offset & 0xffff)(addrTemp)
1035 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
1036 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1037 m_assembler
.sw(src
, addrTempRegister
, address
.offset
);
1041 void store32(RegisterID src
, BaseIndex address
)
1043 if (address
.offset
>= -32768 && address
.offset
<= 32767
1046 sll addrTemp, address.index, address.scale
1047 addu addrTemp, addrTemp, address.base
1048 sw src, address.offset(addrTemp)
1050 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
1051 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1052 m_assembler
.sw(src
, addrTempRegister
, address
.offset
);
1055 sll addrTemp, address.index, address.scale
1056 addu addrTemp, addrTemp, address.base
1057 lui immTemp, (address.offset + 0x8000) >> 16
1058 addu addrTemp, addrTemp, immTemp
1059 sw src, (address.offset & 0xffff)(at)
1061 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
1062 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1063 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
1064 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
1065 m_assembler
.sw(src
, addrTempRegister
, address
.offset
);
1069 void store32(TrustedImm32 imm
, ImplicitAddress address
)
1071 if (address
.offset
>= -32768 && address
.offset
<= 32767
1074 m_assembler
.sw(MIPSRegisters::zero
, address
.base
, address
.offset
);
1076 move(imm
, immTempRegister
);
1077 m_assembler
.sw(immTempRegister
, address
.base
, address
.offset
);
1081 lui addrTemp, (offset + 0x8000) >> 16
1082 addu addrTemp, addrTemp, base
1083 sw immTemp, (offset & 0xffff)(addrTemp)
1085 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
1086 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1087 if (!imm
.m_value
&& !m_fixedWidth
)
1088 m_assembler
.sw(MIPSRegisters::zero
, addrTempRegister
, address
.offset
);
1090 move(imm
, immTempRegister
);
1091 m_assembler
.sw(immTempRegister
, addrTempRegister
, address
.offset
);
1096 void store32(TrustedImm32 imm
, BaseIndex address
)
1098 if (address
.offset
>= -32768 && address
.offset
<= 32767 && !m_fixedWidth
) {
1100 sll addrTemp, address.index, address.scale
1101 addu addrTemp, addrTemp, address.base
1102 sw src, address.offset(addrTemp)
1104 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
1105 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1107 m_assembler
.sw(MIPSRegisters::zero
, addrTempRegister
, address
.offset
);
1109 move(imm
, immTempRegister
);
1110 m_assembler
.sw(immTempRegister
, addrTempRegister
, address
.offset
);
1114 sll addrTemp, address.index, address.scale
1115 addu addrTemp, addrTemp, address.base
1116 lui immTemp, (address.offset + 0x8000) >> 16
1117 addu addrTemp, addrTemp, immTemp
1118 sw src, (address.offset & 0xffff)(at)
1120 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
1121 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1122 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
1123 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
1124 if (!imm
.m_value
&& !m_fixedWidth
)
1125 m_assembler
.sw(MIPSRegisters::zero
, addrTempRegister
, address
.offset
);
1127 move(imm
, immTempRegister
);
1128 m_assembler
.sw(immTempRegister
, addrTempRegister
, address
.offset
);
1134 void store32(RegisterID src
, const void* address
)
1137 li addrTemp, address
1140 move(TrustedImmPtr(address
), addrTempRegister
);
1141 m_assembler
.sw(src
, addrTempRegister
, 0);
1144 void store32(TrustedImm32 imm
, const void* address
)
1148 li addrTemp, address
1151 if (!imm
.m_value
&& !m_fixedWidth
) {
1152 move(TrustedImmPtr(address
), addrTempRegister
);
1153 m_assembler
.sw(MIPSRegisters::zero
, addrTempRegister
, 0);
1155 move(imm
, immTempRegister
);
1156 move(TrustedImmPtr(address
), addrTempRegister
);
1157 m_assembler
.sw(immTempRegister
, addrTempRegister
, 0);
1161 // Floating-point operations:
1163 static bool supportsFloatingPoint()
1165 #if WTF_MIPS_DOUBLE_FLOAT
1172 static bool supportsFloatingPointTruncate()
1174 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
1181 static bool supportsFloatingPointSqrt()
1183 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
1189 static bool supportsFloatingPointAbs() { return false; }
1191 // Stack manipulation operations:
1193 // The ABI is assumed to provide a stack abstraction to memory,
1194 // containing machine word sized units of data. Push and pop
1195 // operations add and remove a single register sized unit of data
1196 // to or from the stack. Peek and poke operations read or write
1197 // values on the stack, without moving the current stack position.
1199 void pop(RegisterID dest
)
1201 m_assembler
.lw(dest
, MIPSRegisters::sp
, 0);
1202 m_assembler
.addiu(MIPSRegisters::sp
, MIPSRegisters::sp
, 4);
1205 void push(RegisterID src
)
1207 m_assembler
.addiu(MIPSRegisters::sp
, MIPSRegisters::sp
, -4);
1208 m_assembler
.sw(src
, MIPSRegisters::sp
, 0);
1211 void push(Address address
)
1213 load32(address
, dataTempRegister
);
1214 push(dataTempRegister
);
1217 void push(TrustedImm32 imm
)
1219 move(imm
, immTempRegister
);
1220 push(immTempRegister
);
1223 // Register move operations:
1225 // Move values in registers.
1227 void move(TrustedImm32 imm
, RegisterID dest
)
1229 if (!imm
.m_value
&& !m_fixedWidth
)
1230 move(MIPSRegisters::zero
, dest
);
1231 else if (m_fixedWidth
) {
1232 m_assembler
.lui(dest
, imm
.m_value
>> 16);
1233 m_assembler
.ori(dest
, dest
, imm
.m_value
);
1235 m_assembler
.li(dest
, imm
.m_value
);
1238 void move(RegisterID src
, RegisterID dest
)
1240 if (src
!= dest
|| m_fixedWidth
)
1241 m_assembler
.move(dest
, src
);
1244 void move(TrustedImmPtr imm
, RegisterID dest
)
1246 move(TrustedImm32(imm
), dest
);
1249 void swap(RegisterID reg1
, RegisterID reg2
)
1251 move(reg1
, immTempRegister
);
1253 move(immTempRegister
, reg2
);
1256 void signExtend32ToPtr(RegisterID src
, RegisterID dest
)
1258 if (src
!= dest
|| m_fixedWidth
)
1262 void zeroExtend32ToPtr(RegisterID src
, RegisterID dest
)
1264 if (src
!= dest
|| m_fixedWidth
)
1268 // Forwards / external control flow operations:
1270 // This set of jump and conditional branch operations return a Jump
1271 // object which may linked at a later point, allow forwards jump,
1272 // or jumps that will require external linkage (after the code has been
1275 // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
1276 // respecitvely, for unsigned comparisons the names b, a, be, and ae are
1277 // used (representing the names 'below' and 'above').
1279 // Operands to the comparision are provided in the expected order, e.g.
1280 // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when
1281 // treated as a signed 32bit value, is less than or equal to 5.
1283 // jz and jnz test whether the first operand is equal to zero, and take
1284 // an optional second operand of a mask under which to perform the test.
1286 Jump
branch8(RelationalCondition cond
, Address left
, TrustedImm32 right
)
1288 // Make sure the immediate value is unsigned 8 bits.
1289 ASSERT(!(right
.m_value
& 0xFFFFFF00));
1290 load8(left
, dataTempRegister
);
1291 move(right
, immTempRegister
);
1292 return branch32(cond
, dataTempRegister
, immTempRegister
);
1295 void compare8(RelationalCondition cond
, Address left
, TrustedImm32 right
, RegisterID dest
)
1297 // Make sure the immediate value is unsigned 8 bits.
1298 ASSERT(!(right
.m_value
& 0xFFFFFF00));
1299 load8(left
, dataTempRegister
);
1300 move(right
, immTempRegister
);
1301 compare32(cond
, dataTempRegister
, immTempRegister
, dest
);
1304 Jump
branch8(RelationalCondition cond
, BaseIndex left
, TrustedImm32 right
)
1306 ASSERT(!(right
.m_value
& 0xFFFFFF00));
1307 load8(left
, dataTempRegister
);
1308 // Be careful that the previous load8() uses immTempRegister.
1309 // So, we need to put move() after load8().
1310 move(right
, immTempRegister
);
1311 return branch32(cond
, dataTempRegister
, immTempRegister
);
1314 Jump
branch32(RelationalCondition cond
, RegisterID left
, RegisterID right
)
1317 return branchEqual(left
, right
);
1318 if (cond
== NotEqual
)
1319 return branchNotEqual(left
, right
);
1320 if (cond
== Above
) {
1321 m_assembler
.sltu(cmpTempRegister
, right
, left
);
1322 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1324 if (cond
== AboveOrEqual
) {
1325 m_assembler
.sltu(cmpTempRegister
, left
, right
);
1326 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1328 if (cond
== Below
) {
1329 m_assembler
.sltu(cmpTempRegister
, left
, right
);
1330 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1332 if (cond
== BelowOrEqual
) {
1333 m_assembler
.sltu(cmpTempRegister
, right
, left
);
1334 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1336 if (cond
== GreaterThan
) {
1337 m_assembler
.slt(cmpTempRegister
, right
, left
);
1338 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1340 if (cond
== GreaterThanOrEqual
) {
1341 m_assembler
.slt(cmpTempRegister
, left
, right
);
1342 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1344 if (cond
== LessThan
) {
1345 m_assembler
.slt(cmpTempRegister
, left
, right
);
1346 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1348 if (cond
== LessThanOrEqual
) {
1349 m_assembler
.slt(cmpTempRegister
, right
, left
);
1350 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1357 Jump
branch32(RelationalCondition cond
, RegisterID left
, TrustedImm32 right
)
1359 move(right
, immTempRegister
);
1360 return branch32(cond
, left
, immTempRegister
);
1363 Jump
branch32(RelationalCondition cond
, RegisterID left
, Address right
)
1365 load32(right
, dataTempRegister
);
1366 return branch32(cond
, left
, dataTempRegister
);
1369 Jump
branch32(RelationalCondition cond
, Address left
, RegisterID right
)
1371 load32(left
, dataTempRegister
);
1372 return branch32(cond
, dataTempRegister
, right
);
1375 Jump
branch32(RelationalCondition cond
, Address left
, TrustedImm32 right
)
1377 load32(left
, dataTempRegister
);
1378 move(right
, immTempRegister
);
1379 return branch32(cond
, dataTempRegister
, immTempRegister
);
1382 Jump
branch32(RelationalCondition cond
, BaseIndex left
, TrustedImm32 right
)
1384 load32(left
, dataTempRegister
);
1385 // Be careful that the previous load32() uses immTempRegister.
1386 // So, we need to put move() after load32().
1387 move(right
, immTempRegister
);
1388 return branch32(cond
, dataTempRegister
, immTempRegister
);
1391 Jump
branch32WithUnalignedHalfWords(RelationalCondition cond
, BaseIndex left
, TrustedImm32 right
)
1393 load32WithUnalignedHalfWords(left
, dataTempRegister
);
1394 // Be careful that the previous load32WithUnalignedHalfWords()
1395 // uses immTempRegister.
1396 // So, we need to put move() after load32WithUnalignedHalfWords().
1397 move(right
, immTempRegister
);
1398 return branch32(cond
, dataTempRegister
, immTempRegister
);
1401 Jump
branch32(RelationalCondition cond
, AbsoluteAddress left
, RegisterID right
)
1403 load32(left
.m_ptr
, dataTempRegister
);
1404 return branch32(cond
, dataTempRegister
, right
);
1407 Jump
branch32(RelationalCondition cond
, AbsoluteAddress left
, TrustedImm32 right
)
1409 load32(left
.m_ptr
, dataTempRegister
);
1410 move(right
, immTempRegister
);
1411 return branch32(cond
, dataTempRegister
, immTempRegister
);
1414 Jump
branchTest32(ResultCondition cond
, RegisterID reg
, RegisterID mask
)
1416 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1417 m_assembler
.andInsn(cmpTempRegister
, reg
, mask
);
1419 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1420 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1423 Jump
branchTest32(ResultCondition cond
, RegisterID reg
, TrustedImm32 mask
= TrustedImm32(-1))
1425 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1426 if (mask
.m_value
== -1 && !m_fixedWidth
) {
1428 return branchEqual(reg
, MIPSRegisters::zero
);
1429 return branchNotEqual(reg
, MIPSRegisters::zero
);
1431 move(mask
, immTempRegister
);
1432 return branchTest32(cond
, reg
, immTempRegister
);
1435 Jump
branchTest32(ResultCondition cond
, Address address
, TrustedImm32 mask
= TrustedImm32(-1))
1437 load32(address
, dataTempRegister
);
1438 return branchTest32(cond
, dataTempRegister
, mask
);
1441 Jump
branchTest32(ResultCondition cond
, BaseIndex address
, TrustedImm32 mask
= TrustedImm32(-1))
1443 load32(address
, dataTempRegister
);
1444 return branchTest32(cond
, dataTempRegister
, mask
);
1447 Jump
branchTest8(ResultCondition cond
, Address address
, TrustedImm32 mask
= TrustedImm32(-1))
1449 load8(address
, dataTempRegister
);
1450 return branchTest32(cond
, dataTempRegister
, mask
);
1453 Jump
branchTest8(ResultCondition cond
, AbsoluteAddress address
, TrustedImm32 mask
= TrustedImm32(-1))
1455 move(TrustedImmPtr(address
.m_ptr
), dataTempRegister
);
1456 load8(Address(dataTempRegister
), dataTempRegister
);
1457 return branchTest32(cond
, dataTempRegister
, mask
);
1462 return branchEqual(MIPSRegisters::zero
, MIPSRegisters::zero
);
1465 void jump(RegisterID target
)
1467 move(target
, MIPSRegisters::t9
);
1468 m_assembler
.jr(MIPSRegisters::t9
);
1472 void jump(Address address
)
1474 m_fixedWidth
= true;
1475 load32(address
, MIPSRegisters::t9
);
1476 m_assembler
.jr(MIPSRegisters::t9
);
1478 m_fixedWidth
= false;
1481 void jump(AbsoluteAddress address
)
1483 m_fixedWidth
= true;
1484 load32(address
.m_ptr
, MIPSRegisters::t9
);
1485 m_assembler
.jr(MIPSRegisters::t9
);
1487 m_fixedWidth
= false;
1490 void moveDoubleToInts(FPRegisterID src
, RegisterID dest1
, RegisterID dest2
)
1492 m_assembler
.vmov(dest1
, dest2
, src
);
1495 void moveIntsToDouble(RegisterID src1
, RegisterID src2
, FPRegisterID dest
, FPRegisterID scratch
)
1497 UNUSED_PARAM(scratch
);
1498 m_assembler
.vmov(dest
, src1
, src2
);
1501 // Arithmetic control flow operations:
1503 // This set of conditional branch operations branch based
1504 // on the result of an arithmetic operation. The operation
1505 // is performed as normal, storing the result.
1507 // * jz operations branch if the result is zero.
1508 // * jo operations branch if the (signed) arithmetic
1509 // operation caused an overflow to occur.
1511 Jump
branchAdd32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1513 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== PositiveOrZero
) || (cond
== Zero
) || (cond
== NonZero
));
1514 if (cond
== Overflow
) {
1517 xor cmpTemp, dataTemp, src
1518 bltz cmpTemp, No_overflow # diff sign bit -> no overflow
1519 addu dest, dataTemp, src
1520 xor cmpTemp, dest, dataTemp
1521 bgez cmpTemp, No_overflow # same sign big -> no overflow
1531 move(dest
, dataTempRegister
);
1532 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, src
);
1533 m_assembler
.bltz(cmpTempRegister
, 10);
1534 m_assembler
.addu(dest
, dataTempRegister
, src
);
1535 m_assembler
.xorInsn(cmpTempRegister
, dest
, dataTempRegister
);
1536 m_assembler
.bgez(cmpTempRegister
, 7);
1540 if (cond
== Signed
) {
1542 // Check if dest is negative.
1543 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1544 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1546 if (cond
== PositiveOrZero
) {
1548 // Check if dest is not negative.
1549 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1550 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1554 return branchEqual(dest
, MIPSRegisters::zero
);
1556 if (cond
== NonZero
) {
1558 return branchNotEqual(dest
, MIPSRegisters::zero
);
1564 Jump
branchAdd32(ResultCondition cond
, RegisterID op1
, RegisterID op2
, RegisterID dest
)
1566 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== PositiveOrZero
) || (cond
== Zero
) || (cond
== NonZero
));
1567 if (cond
== Overflow
) {
1570 xor cmpTemp, dataTemp, op2
1571 bltz cmpTemp, No_overflow # diff sign bit -> no overflow
1572 addu dest, dataTemp, op2
1573 xor cmpTemp, dest, dataTemp
1574 bgez cmpTemp, No_overflow # same sign big -> no overflow
1584 move(op1
, dataTempRegister
);
1585 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, op2
);
1586 m_assembler
.bltz(cmpTempRegister
, 10);
1587 m_assembler
.addu(dest
, dataTempRegister
, op2
);
1588 m_assembler
.xorInsn(cmpTempRegister
, dest
, dataTempRegister
);
1589 m_assembler
.bgez(cmpTempRegister
, 7);
1593 if (cond
== Signed
) {
1594 add32(op1
, op2
, dest
);
1595 // Check if dest is negative.
1596 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1597 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1599 if (cond
== PositiveOrZero
) {
1600 add32(op1
, op2
, dest
);
1601 // Check if dest is not negative.
1602 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1603 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1606 add32(op1
, op2
, dest
);
1607 return branchEqual(dest
, MIPSRegisters::zero
);
1609 if (cond
== NonZero
) {
1610 add32(op1
, op2
, dest
);
1611 return branchNotEqual(dest
, MIPSRegisters::zero
);
1617 Jump
branchAdd32(ResultCondition cond
, TrustedImm32 imm
, RegisterID dest
)
1619 move(imm
, immTempRegister
);
1620 return branchAdd32(cond
, immTempRegister
, dest
);
1623 Jump
branchAdd32(ResultCondition cond
, RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
1625 move(imm
, immTempRegister
);
1627 return branchAdd32(cond
, immTempRegister
, dest
);
1630 Jump
branchAdd32(ResultCondition cond
, TrustedImm32 imm
, AbsoluteAddress dest
)
1632 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== PositiveOrZero
) || (cond
== Zero
) || (cond
== NonZero
));
1633 if (cond
== Overflow
) {
1636 xori cmpTemp, dataTemp, imm
1637 bltz cmpTemp, No_overflow # diff sign bit -> no overflow
1638 addiu dataTemp, dataTemp, imm
1640 xori cmpTemp, dataTemp, imm
1641 bgez cmpTemp, No_overflow # same sign big -> no overflow
1651 if (imm
.m_value
>= -32768 && imm
.m_value
<= 32767 && !m_fixedWidth
) {
1652 load32(dest
.m_ptr
, dataTempRegister
);
1653 m_assembler
.xori(cmpTempRegister
, dataTempRegister
, imm
.m_value
);
1654 m_assembler
.bltz(cmpTempRegister
, 10);
1655 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, imm
.m_value
);
1656 store32(dataTempRegister
, dest
.m_ptr
);
1657 m_assembler
.xori(cmpTempRegister
, dataTempRegister
, imm
.m_value
);
1658 m_assembler
.bgez(cmpTempRegister
, 7);
1661 load32(dest
.m_ptr
, dataTempRegister
);
1662 move(imm
, immTempRegister
);
1663 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, immTempRegister
);
1664 m_assembler
.bltz(cmpTempRegister
, 10);
1665 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, immTempRegister
);
1666 store32(dataTempRegister
, dest
.m_ptr
);
1667 m_assembler
.xori(cmpTempRegister
, dataTempRegister
, immTempRegister
);
1668 m_assembler
.bgez(cmpTempRegister
, 7);
1673 move(imm
, immTempRegister
);
1674 load32(dest
.m_ptr
, dataTempRegister
);
1675 add32(immTempRegister
, dataTempRegister
);
1676 store32(dataTempRegister
, dest
.m_ptr
);
1677 if (cond
== Signed
) {
1678 // Check if dest is negative.
1679 m_assembler
.slt(cmpTempRegister
, dataTempRegister
, MIPSRegisters::zero
);
1680 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1682 if (cond
== PositiveOrZero
) {
1683 // Check if dest is not negative.
1684 m_assembler
.slt(cmpTempRegister
, dataTempRegister
, MIPSRegisters::zero
);
1685 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1688 return branchEqual(dataTempRegister
, MIPSRegisters::zero
);
1689 if (cond
== NonZero
)
1690 return branchNotEqual(dataTempRegister
, MIPSRegisters::zero
);
1695 Jump
branchMul32(ResultCondition cond
, RegisterID src1
, RegisterID src2
, RegisterID dest
)
1697 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1698 if (cond
== Overflow
) {
1703 sra addrTemp, dest, 31
1704 beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow
1714 m_assembler
.mult(src1
, src2
);
1715 m_assembler
.mfhi(dataTempRegister
);
1716 m_assembler
.mflo(dest
);
1717 m_assembler
.sra(addrTempRegister
, dest
, 31);
1718 m_assembler
.beq(dataTempRegister
, addrTempRegister
, 7);
1722 if (cond
== Signed
) {
1723 mul32(src1
, src2
, dest
);
1724 // Check if dest is negative.
1725 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1726 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1729 mul32(src1
, src2
, dest
);
1730 return branchEqual(dest
, MIPSRegisters::zero
);
1732 if (cond
== NonZero
) {
1733 mul32(src1
, src2
, dest
);
1734 return branchNotEqual(dest
, MIPSRegisters::zero
);
1740 Jump
branchMul32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1742 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1743 if (cond
== Overflow
) {
1748 sra addrTemp, dest, 31
1749 beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow
1759 m_assembler
.mult(src
, dest
);
1760 m_assembler
.mfhi(dataTempRegister
);
1761 m_assembler
.mflo(dest
);
1762 m_assembler
.sra(addrTempRegister
, dest
, 31);
1763 m_assembler
.beq(dataTempRegister
, addrTempRegister
, 7);
1767 if (cond
== Signed
) {
1769 // Check if dest is negative.
1770 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1771 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1775 return branchEqual(dest
, MIPSRegisters::zero
);
1777 if (cond
== NonZero
) {
1779 return branchNotEqual(dest
, MIPSRegisters::zero
);
1785 Jump
branchMul32(ResultCondition cond
, TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
1787 move(imm
, immTempRegister
);
1788 return branchMul32(cond
, immTempRegister
, src
, dest
);
1791 Jump
branchSub32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1793 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1794 if (cond
== Overflow
) {
1797 xor cmpTemp, dataTemp, src
1798 bgez cmpTemp, No_overflow # same sign bit -> no overflow
1799 subu dest, dataTemp, src
1800 xor cmpTemp, dest, dataTemp
1801 bgez cmpTemp, No_overflow # same sign bit -> no overflow
1811 move(dest
, dataTempRegister
);
1812 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, src
);
1813 m_assembler
.bgez(cmpTempRegister
, 10);
1814 m_assembler
.subu(dest
, dataTempRegister
, src
);
1815 m_assembler
.xorInsn(cmpTempRegister
, dest
, dataTempRegister
);
1816 m_assembler
.bgez(cmpTempRegister
, 7);
1820 if (cond
== Signed
) {
1822 // Check if dest is negative.
1823 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1824 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1828 return branchEqual(dest
, MIPSRegisters::zero
);
1830 if (cond
== NonZero
) {
1832 return branchNotEqual(dest
, MIPSRegisters::zero
);
1838 Jump
branchSub32(ResultCondition cond
, TrustedImm32 imm
, RegisterID dest
)
1840 move(imm
, immTempRegister
);
1841 return branchSub32(cond
, immTempRegister
, dest
);
1844 Jump
branchSub32(ResultCondition cond
, RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
1846 move(imm
, immTempRegister
);
1847 return branchSub32(cond
, src
, immTempRegister
, dest
);
1850 Jump
branchSub32(ResultCondition cond
, RegisterID op1
, RegisterID op2
, RegisterID dest
)
1852 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1853 if (cond
== Overflow
) {
1856 xor cmpTemp, dataTemp, op2
1857 bgez cmpTemp, No_overflow # same sign bit -> no overflow
1858 subu dest, dataTemp, op2
1859 xor cmpTemp, dest, dataTemp
1860 bgez cmpTemp, No_overflow # same sign bit -> no overflow
1870 move(op1
, dataTempRegister
);
1871 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, op2
);
1872 m_assembler
.bgez(cmpTempRegister
, 10);
1873 m_assembler
.subu(dest
, dataTempRegister
, op2
);
1874 m_assembler
.xorInsn(cmpTempRegister
, dest
, dataTempRegister
);
1875 m_assembler
.bgez(cmpTempRegister
, 7);
1879 if (cond
== Signed
) {
1880 sub32(op1
, op2
, dest
);
1881 // Check if dest is negative.
1882 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1883 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1886 sub32(op1
, op2
, dest
);
1887 return branchEqual(dest
, MIPSRegisters::zero
);
1889 if (cond
== NonZero
) {
1890 sub32(op1
, op2
, dest
);
1891 return branchNotEqual(dest
, MIPSRegisters::zero
);
1897 Jump
branchNeg32(ResultCondition cond
, RegisterID srcDest
)
1899 m_assembler
.li(dataTempRegister
, -1);
1900 return branchMul32(cond
, dataTempRegister
, srcDest
);
1903 Jump
branchOr32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1905 ASSERT((cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1906 if (cond
== Signed
) {
1908 // Check if dest is negative.
1909 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1910 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1914 return branchEqual(dest
, MIPSRegisters::zero
);
1916 if (cond
== NonZero
) {
1918 return branchNotEqual(dest
, MIPSRegisters::zero
);
1924 // Miscellaneous operations:
1933 /* We need two words for relaxation. */
1938 return Call(m_assembler
.label(), Call::LinkableNear
);
1943 m_assembler
.lui(MIPSRegisters::t9
, 0);
1944 m_assembler
.ori(MIPSRegisters::t9
, MIPSRegisters::t9
, 0);
1945 m_assembler
.jalr(MIPSRegisters::t9
);
1947 return Call(m_assembler
.label(), Call::Linkable
);
1950 Call
call(RegisterID target
)
1952 move(target
, MIPSRegisters::t9
);
1953 m_assembler
.jalr(MIPSRegisters::t9
);
1955 return Call(m_assembler
.label(), Call::None
);
1958 Call
call(Address address
)
1960 m_fixedWidth
= true;
1961 load32(address
, MIPSRegisters::t9
);
1962 m_assembler
.jalr(MIPSRegisters::t9
);
1964 m_fixedWidth
= false;
1965 return Call(m_assembler
.label(), Call::None
);
1970 m_assembler
.jr(MIPSRegisters::ra
);
1974 void compare32(RelationalCondition cond
, RegisterID left
, RegisterID right
, RegisterID dest
)
1976 if (cond
== Equal
) {
1977 m_assembler
.xorInsn(dest
, left
, right
);
1978 m_assembler
.sltiu(dest
, dest
, 1);
1979 } else if (cond
== NotEqual
) {
1980 m_assembler
.xorInsn(dest
, left
, right
);
1981 m_assembler
.sltu(dest
, MIPSRegisters::zero
, dest
);
1982 } else if (cond
== Above
)
1983 m_assembler
.sltu(dest
, right
, left
);
1984 else if (cond
== AboveOrEqual
) {
1985 m_assembler
.sltu(dest
, left
, right
);
1986 m_assembler
.xori(dest
, dest
, 1);
1987 } else if (cond
== Below
)
1988 m_assembler
.sltu(dest
, left
, right
);
1989 else if (cond
== BelowOrEqual
) {
1990 m_assembler
.sltu(dest
, right
, left
);
1991 m_assembler
.xori(dest
, dest
, 1);
1992 } else if (cond
== GreaterThan
)
1993 m_assembler
.slt(dest
, right
, left
);
1994 else if (cond
== GreaterThanOrEqual
) {
1995 m_assembler
.slt(dest
, left
, right
);
1996 m_assembler
.xori(dest
, dest
, 1);
1997 } else if (cond
== LessThan
)
1998 m_assembler
.slt(dest
, left
, right
);
1999 else if (cond
== LessThanOrEqual
) {
2000 m_assembler
.slt(dest
, right
, left
);
2001 m_assembler
.xori(dest
, dest
, 1);
2005 void compare32(RelationalCondition cond
, RegisterID left
, TrustedImm32 right
, RegisterID dest
)
2007 move(right
, immTempRegister
);
2008 compare32(cond
, left
, immTempRegister
, dest
);
2011 void test8(ResultCondition cond
, Address address
, TrustedImm32 mask
, RegisterID dest
)
2013 ASSERT((cond
== Zero
) || (cond
== NonZero
));
2014 load8(address
, dataTempRegister
);
2015 if (mask
.m_value
== -1 && !m_fixedWidth
) {
2017 m_assembler
.sltiu(dest
, dataTempRegister
, 1);
2019 m_assembler
.sltu(dest
, MIPSRegisters::zero
, dataTempRegister
);
2021 move(mask
, immTempRegister
);
2022 m_assembler
.andInsn(cmpTempRegister
, dataTempRegister
, immTempRegister
);
2024 m_assembler
.sltiu(dest
, cmpTempRegister
, 1);
2026 m_assembler
.sltu(dest
, MIPSRegisters::zero
, cmpTempRegister
);
2030 void test32(ResultCondition cond
, Address address
, TrustedImm32 mask
, RegisterID dest
)
2032 ASSERT((cond
== Zero
) || (cond
== NonZero
));
2033 load32(address
, dataTempRegister
);
2034 if (mask
.m_value
== -1 && !m_fixedWidth
) {
2036 m_assembler
.sltiu(dest
, dataTempRegister
, 1);
2038 m_assembler
.sltu(dest
, MIPSRegisters::zero
, dataTempRegister
);
2040 move(mask
, immTempRegister
);
2041 m_assembler
.andInsn(cmpTempRegister
, dataTempRegister
, immTempRegister
);
2043 m_assembler
.sltiu(dest
, cmpTempRegister
, 1);
2045 m_assembler
.sltu(dest
, MIPSRegisters::zero
, cmpTempRegister
);
2049 DataLabel32
moveWithPatch(TrustedImm32 imm
, RegisterID dest
)
2051 m_fixedWidth
= true;
2052 DataLabel32
label(this);
2054 m_fixedWidth
= false;
2058 DataLabelPtr
moveWithPatch(TrustedImmPtr initialValue
, RegisterID dest
)
2060 m_fixedWidth
= true;
2061 DataLabelPtr
label(this);
2062 move(initialValue
, dest
);
2063 m_fixedWidth
= false;
2067 Jump
branchPtrWithPatch(RelationalCondition cond
, RegisterID left
, DataLabelPtr
& dataLabel
, TrustedImmPtr initialRightValue
= TrustedImmPtr(0))
2069 m_fixedWidth
= true;
2070 dataLabel
= moveWithPatch(initialRightValue
, immTempRegister
);
2071 Jump temp
= branch32(cond
, left
, immTempRegister
);
2072 m_fixedWidth
= false;
2076 Jump
branchPtrWithPatch(RelationalCondition cond
, Address left
, DataLabelPtr
& dataLabel
, TrustedImmPtr initialRightValue
= TrustedImmPtr(0))
2078 m_fixedWidth
= true;
2079 load32(left
, dataTempRegister
);
2080 dataLabel
= moveWithPatch(initialRightValue
, immTempRegister
);
2081 Jump temp
= branch32(cond
, dataTempRegister
, immTempRegister
);
2082 m_fixedWidth
= false;
2086 DataLabelPtr
storePtrWithPatch(TrustedImmPtr initialValue
, ImplicitAddress address
)
2088 m_fixedWidth
= true;
2089 DataLabelPtr dataLabel
= moveWithPatch(initialValue
, dataTempRegister
);
2090 store32(dataTempRegister
, address
);
2091 m_fixedWidth
= false;
2095 DataLabelPtr
storePtrWithPatch(ImplicitAddress address
)
2097 return storePtrWithPatch(TrustedImmPtr(0), address
);
2100 Call
tailRecursiveCall()
2102 // Like a normal call, but don't update the returned address register
2103 m_fixedWidth
= true;
2104 move(TrustedImm32(0), MIPSRegisters::t9
);
2105 m_assembler
.jr(MIPSRegisters::t9
);
2107 m_fixedWidth
= false;
2108 return Call(m_assembler
.label(), Call::Linkable
);
2111 Call
makeTailRecursiveCall(Jump oldJump
)
2114 return tailRecursiveCall();
2117 void loadFloat(BaseIndex address
, FPRegisterID dest
)
2119 if (address
.offset
>= -32768 && address
.offset
<= 32767
2122 sll addrTemp, address.index, address.scale
2123 addu addrTemp, addrTemp, address.base
2124 lwc1 dest, address.offset(addrTemp)
2126 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2127 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2128 m_assembler
.lwc1(dest
, addrTempRegister
, address
.offset
);
2131 sll addrTemp, address.index, address.scale
2132 addu addrTemp, addrTemp, address.base
2133 lui immTemp, (address.offset + 0x8000) >> 16
2134 addu addrTemp, addrTemp, immTemp
2135 lwc1 dest, (address.offset & 0xffff)(at)
2137 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2138 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2139 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
2140 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
2141 m_assembler
.lwc1(dest
, addrTempRegister
, address
.offset
);
2145 void loadDouble(ImplicitAddress address
, FPRegisterID dest
)
2149 li addrTemp, address.offset
2150 addu addrTemp, addrTemp, base
2151 lwc1 dest, 0(addrTemp)
2152 lwc1 dest+1, 4(addrTemp)
2154 move(TrustedImm32(address
.offset
), addrTempRegister
);
2155 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2156 m_assembler
.lwc1(dest
, addrTempRegister
, 0);
2157 m_assembler
.lwc1(FPRegisterID(dest
+ 1), addrTempRegister
, 4);
2159 if (address
.offset
>= -32768 && address
.offset
<= 32767
2161 m_assembler
.ldc1(dest
, address
.base
, address
.offset
);
2164 lui addrTemp, (offset + 0x8000) >> 16
2165 addu addrTemp, addrTemp, base
2166 ldc1 dest, (offset & 0xffff)(addrTemp)
2168 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
2169 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2170 m_assembler
.ldc1(dest
, addrTempRegister
, address
.offset
);
2175 void loadDouble(BaseIndex address
, FPRegisterID dest
)
2178 if (address
.offset
>= -32768 && address
.offset
<= 32767
2181 sll addrTemp, address.index, address.scale
2182 addu addrTemp, addrTemp, address.base
2183 lwc1 dest, address.offset(addrTemp)
2184 lwc1 dest+1, (address.offset+4)(addrTemp)
2186 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2187 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2188 m_assembler
.lwc1(dest
, addrTempRegister
, address
.offset
);
2189 m_assembler
.lwc1(FPRegisterID(dest
+ 1), addrTempRegister
, address
.offset
+ 4);
2192 sll addrTemp, address.index, address.scale
2193 addu addrTemp, addrTemp, address.base
2194 lui immTemp, (address.offset + 0x8000) >> 16
2195 addu addrTemp, addrTemp, immTemp
2196 lwc1 dest, (address.offset & 0xffff)(at)
2197 lwc1 dest+1, (address.offset & 0xffff + 4)(at)
2199 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2200 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2201 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
2202 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
2203 m_assembler
.lwc1(dest
, addrTempRegister
, address
.offset
);
2204 m_assembler
.lwc1(FPRegisterID(dest
+ 1), addrTempRegister
, address
.offset
+ 4);
2207 if (address
.offset
>= -32768 && address
.offset
<= 32767
2210 sll addrTemp, address.index, address.scale
2211 addu addrTemp, addrTemp, address.base
2212 ldc1 dest, address.offset(addrTemp)
2214 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2215 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2216 m_assembler
.ldc1(dest
, addrTempRegister
, address
.offset
);
2219 sll addrTemp, address.index, address.scale
2220 addu addrTemp, addrTemp, address.base
2221 lui immTemp, (address.offset + 0x8000) >> 16
2222 addu addrTemp, addrTemp, immTemp
2223 ldc1 dest, (address.offset & 0xffff)(at)
2225 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2226 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2227 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
2228 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
2229 m_assembler
.ldc1(dest
, addrTempRegister
, address
.offset
);
2234 void loadDouble(const void* address
, FPRegisterID dest
)
2238 li addrTemp, address
2239 lwc1 dest, 0(addrTemp)
2240 lwc1 dest+1, 4(addrTemp)
2242 move(TrustedImmPtr(address
), addrTempRegister
);
2243 m_assembler
.lwc1(dest
, addrTempRegister
, 0);
2244 m_assembler
.lwc1(FPRegisterID(dest
+ 1), addrTempRegister
, 4);
2247 li addrTemp, address
2248 ldc1 dest, 0(addrTemp)
2250 move(TrustedImmPtr(address
), addrTempRegister
);
2251 m_assembler
.ldc1(dest
, addrTempRegister
, 0);
2255 void storeFloat(FPRegisterID src
, BaseIndex address
)
2257 if (address
.offset
>= -32768 && address
.offset
<= 32767
2260 sll addrTemp, address.index, address.scale
2261 addu addrTemp, addrTemp, address.base
2262 swc1 src, address.offset(addrTemp)
2264 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2265 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2266 m_assembler
.swc1(src
, addrTempRegister
, address
.offset
);
2269 sll addrTemp, address.index, address.scale
2270 addu addrTemp, addrTemp, address.base
2271 lui immTemp, (address.offset + 0x8000) >> 16
2272 addu addrTemp, addrTemp, immTemp
2273 swc1 src, (address.offset & 0xffff)(at)
2275 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2276 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2277 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
2278 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
2279 m_assembler
.swc1(src
, addrTempRegister
, address
.offset
);
2283 void storeDouble(FPRegisterID src
, ImplicitAddress address
)
2287 li addrTemp, address.offset
2288 addu addrTemp, addrTemp, base
2289 swc1 dest, 0(addrTemp)
2290 swc1 dest+1, 4(addrTemp)
2292 move(TrustedImm32(address
.offset
), addrTempRegister
);
2293 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2294 m_assembler
.swc1(src
, addrTempRegister
, 0);
2295 m_assembler
.swc1(FPRegisterID(src
+ 1), addrTempRegister
, 4);
2297 if (address
.offset
>= -32768 && address
.offset
<= 32767
2299 m_assembler
.sdc1(src
, address
.base
, address
.offset
);
2302 lui addrTemp, (offset + 0x8000) >> 16
2303 addu addrTemp, addrTemp, base
2304 sdc1 src, (offset & 0xffff)(addrTemp)
2306 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
2307 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2308 m_assembler
.sdc1(src
, addrTempRegister
, address
.offset
);
2313 void storeDouble(FPRegisterID src
, BaseIndex address
)
2316 if (address
.offset
>= -32768 && address
.offset
<= 32767
2319 sll addrTemp, address.index, address.scale
2320 addu addrTemp, addrTemp, address.base
2321 swc1 src, address.offset(addrTemp)
2322 swc1 src+1, (address.offset + 4)(addrTemp)
2324 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2325 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2326 m_assembler
.swc1(src
, addrTempRegister
, address
.offset
);
2327 m_assembler
.swc1(FPRegisterID(src
+ 1), addrTempRegister
, address
.offset
+ 4);
2330 sll addrTemp, address.index, address.scale
2331 addu addrTemp, addrTemp, address.base
2332 lui immTemp, (address.offset + 0x8000) >> 16
2333 addu addrTemp, addrTemp, immTemp
2334 swc1 src, (address.offset & 0xffff)(at)
2335 swc1 src+1, (address.offset & 0xffff + 4)(at)
2337 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2338 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2339 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
2340 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
2341 m_assembler
.swc1(src
, addrTempRegister
, address
.offset
);
2342 m_assembler
.swc1(FPRegisterID(src
+ 1), addrTempRegister
, address
.offset
+ 4);
2345 if (address
.offset
>= -32768 && address
.offset
<= 32767
2348 sll addrTemp, address.index, address.scale
2349 addu addrTemp, addrTemp, address.base
2350 sdc1 src, address.offset(addrTemp)
2352 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2353 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2354 m_assembler
.sdc1(src
, addrTempRegister
, address
.offset
);
2357 sll addrTemp, address.index, address.scale
2358 addu addrTemp, addrTemp, address.base
2359 lui immTemp, (address.offset + 0x8000) >> 16
2360 addu addrTemp, addrTemp, immTemp
2361 sdc1 src, (address.offset & 0xffff)(at)
2363 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
2364 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
2365 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
2366 m_assembler
.addu(addrTempRegister
, addrTempRegister
, immTempRegister
);
2367 m_assembler
.sdc1(src
, addrTempRegister
, address
.offset
);
2372 void storeDouble(FPRegisterID src
, const void* address
)
2375 move(TrustedImmPtr(address
), addrTempRegister
);
2376 m_assembler
.swc1(src
, addrTempRegister
, 0);
2377 m_assembler
.swc1(FPRegisterID(src
+ 1), addrTempRegister
, 4);
2379 move(TrustedImmPtr(address
), addrTempRegister
);
2380 m_assembler
.sdc1(src
, addrTempRegister
, 0);
2384 void moveDouble(FPRegisterID src
, FPRegisterID dest
)
2386 if (src
!= dest
|| m_fixedWidth
)
2387 m_assembler
.movd(dest
, src
);
2390 void swapDouble(FPRegisterID fr1
, FPRegisterID fr2
)
2392 moveDouble(fr1
, fpTempRegister
);
2393 moveDouble(fr2
, fr1
);
2394 moveDouble(fpTempRegister
, fr2
);
2397 void addDouble(FPRegisterID src
, FPRegisterID dest
)
2399 m_assembler
.addd(dest
, dest
, src
);
2402 void addDouble(FPRegisterID op1
, FPRegisterID op2
, FPRegisterID dest
)
2404 m_assembler
.addd(dest
, op1
, op2
);
2407 void addDouble(Address src
, FPRegisterID dest
)
2409 loadDouble(src
, fpTempRegister
);
2410 m_assembler
.addd(dest
, dest
, fpTempRegister
);
2413 void addDouble(AbsoluteAddress address
, FPRegisterID dest
)
2415 loadDouble(address
.m_ptr
, fpTempRegister
);
2416 m_assembler
.addd(dest
, dest
, fpTempRegister
);
2419 void subDouble(FPRegisterID src
, FPRegisterID dest
)
2421 m_assembler
.subd(dest
, dest
, src
);
2424 void subDouble(FPRegisterID op1
, FPRegisterID op2
, FPRegisterID dest
)
2426 m_assembler
.subd(dest
, op1
, op2
);
2429 void subDouble(Address src
, FPRegisterID dest
)
2431 loadDouble(src
, fpTempRegister
);
2432 m_assembler
.subd(dest
, dest
, fpTempRegister
);
2435 void mulDouble(FPRegisterID src
, FPRegisterID dest
)
2437 m_assembler
.muld(dest
, dest
, src
);
2440 void mulDouble(Address src
, FPRegisterID dest
)
2442 loadDouble(src
, fpTempRegister
);
2443 m_assembler
.muld(dest
, dest
, fpTempRegister
);
2446 void mulDouble(FPRegisterID op1
, FPRegisterID op2
, FPRegisterID dest
)
2448 m_assembler
.muld(dest
, op1
, op2
);
2451 void divDouble(FPRegisterID src
, FPRegisterID dest
)
2453 m_assembler
.divd(dest
, dest
, src
);
2456 void divDouble(FPRegisterID op1
, FPRegisterID op2
, FPRegisterID dest
)
2458 m_assembler
.divd(dest
, op1
, op2
);
2461 void divDouble(Address src
, FPRegisterID dest
)
2463 loadDouble(src
, fpTempRegister
);
2464 m_assembler
.divd(dest
, dest
, fpTempRegister
);
2467 void negateDouble(FPRegisterID src
, FPRegisterID dest
)
2469 m_assembler
.negd(dest
, src
);
2472 void convertInt32ToDouble(RegisterID src
, FPRegisterID dest
)
2474 m_assembler
.mtc1(src
, fpTempRegister
);
2475 m_assembler
.cvtdw(dest
, fpTempRegister
);
2478 void convertInt32ToDouble(Address src
, FPRegisterID dest
)
2480 load32(src
, dataTempRegister
);
2481 m_assembler
.mtc1(dataTempRegister
, fpTempRegister
);
2482 m_assembler
.cvtdw(dest
, fpTempRegister
);
2485 void convertInt32ToDouble(AbsoluteAddress src
, FPRegisterID dest
)
2487 load32(src
.m_ptr
, dataTempRegister
);
2488 m_assembler
.mtc1(dataTempRegister
, fpTempRegister
);
2489 m_assembler
.cvtdw(dest
, fpTempRegister
);
2492 void convertFloatToDouble(FPRegisterID src
, FPRegisterID dst
)
2494 m_assembler
.cvtds(dst
, src
);
2497 void convertDoubleToFloat(FPRegisterID src
, FPRegisterID dst
)
2499 m_assembler
.cvtsd(dst
, src
);
2502 void insertRelaxationWords()
2504 /* We need four words for relaxation. */
2505 m_assembler
.beq(MIPSRegisters::zero
, MIPSRegisters::zero
, 3); // Jump over nops;
2513 m_assembler
.appendJump();
2516 insertRelaxationWords();
2517 return Jump(m_assembler
.label());
2522 m_assembler
.appendJump();
2525 insertRelaxationWords();
2526 return Jump(m_assembler
.label());
2529 Jump
branchEqual(RegisterID rs
, RegisterID rt
)
2533 m_assembler
.appendJump();
2534 m_assembler
.beq(rs
, rt
, 0);
2536 insertRelaxationWords();
2537 return Jump(m_assembler
.label());
2540 Jump
branchNotEqual(RegisterID rs
, RegisterID rt
)
2544 m_assembler
.appendJump();
2545 m_assembler
.bne(rs
, rt
, 0);
2547 insertRelaxationWords();
2548 return Jump(m_assembler
.label());
2551 Jump
branchDouble(DoubleCondition cond
, FPRegisterID left
, FPRegisterID right
)
2553 if (cond
== DoubleEqual
) {
2554 m_assembler
.ceqd(left
, right
);
2555 return branchTrue();
2557 if (cond
== DoubleNotEqual
) {
2558 m_assembler
.cueqd(left
, right
);
2559 return branchFalse(); // false
2561 if (cond
== DoubleGreaterThan
) {
2562 m_assembler
.cngtd(left
, right
);
2563 return branchFalse(); // false
2565 if (cond
== DoubleGreaterThanOrEqual
) {
2566 m_assembler
.cnged(left
, right
);
2567 return branchFalse(); // false
2569 if (cond
== DoubleLessThan
) {
2570 m_assembler
.cltd(left
, right
);
2571 return branchTrue();
2573 if (cond
== DoubleLessThanOrEqual
) {
2574 m_assembler
.cled(left
, right
);
2575 return branchTrue();
2577 if (cond
== DoubleEqualOrUnordered
) {
2578 m_assembler
.cueqd(left
, right
);
2579 return branchTrue();
2581 if (cond
== DoubleNotEqualOrUnordered
) {
2582 m_assembler
.ceqd(left
, right
);
2583 return branchFalse(); // false
2585 if (cond
== DoubleGreaterThanOrUnordered
) {
2586 m_assembler
.coled(left
, right
);
2587 return branchFalse(); // false
2589 if (cond
== DoubleGreaterThanOrEqualOrUnordered
) {
2590 m_assembler
.coltd(left
, right
);
2591 return branchFalse(); // false
2593 if (cond
== DoubleLessThanOrUnordered
) {
2594 m_assembler
.cultd(left
, right
);
2595 return branchTrue();
2597 if (cond
== DoubleLessThanOrEqualOrUnordered
) {
2598 m_assembler
.culed(left
, right
);
2599 return branchTrue();
2606 // Truncates 'src' to an integer, and places the resulting 'dest'.
2607 // If the result is not representable as a 32 bit value, branch.
2608 // May also branch for some values that are representable in 32 bits
2609 // (specifically, in this case, INT_MAX 0x7fffffff).
2610 enum BranchTruncateType
{ BranchIfTruncateFailed
, BranchIfTruncateSuccessful
};
2611 Jump
branchTruncateDoubleToInt32(FPRegisterID src
, RegisterID dest
, BranchTruncateType branchType
= BranchIfTruncateFailed
)
2613 m_assembler
.truncwd(fpTempRegister
, src
);
2614 m_assembler
.mfc1(dest
, fpTempRegister
);
2615 return branch32(branchType
== BranchIfTruncateFailed
? Equal
: NotEqual
, dest
, TrustedImm32(0x7fffffff));
2618 Jump
branchTruncateDoubleToUint32(FPRegisterID src
, RegisterID dest
, BranchTruncateType branchType
= BranchIfTruncateFailed
)
2620 m_assembler
.truncwd(fpTempRegister
, src
);
2621 m_assembler
.mfc1(dest
, fpTempRegister
);
2622 return branch32(branchType
== BranchIfTruncateFailed
? Equal
: NotEqual
, dest
, TrustedImm32(0));
2625 // Result is undefined if the value is outside of the integer range.
2626 void truncateDoubleToInt32(FPRegisterID src
, RegisterID dest
)
2628 m_assembler
.truncwd(fpTempRegister
, src
);
2629 m_assembler
.mfc1(dest
, fpTempRegister
);
2632 // Result is undefined if src > 2^31
2633 void truncateDoubleToUint32(FPRegisterID src
, RegisterID dest
)
2635 m_assembler
.truncwd(fpTempRegister
, src
);
2636 m_assembler
.mfc1(dest
, fpTempRegister
);
2639 // Convert 'src' to an integer, and places the resulting 'dest'.
2640 // If the result is not representable as a 32 bit value, branch.
2641 // May also branch for some values that are representable in 32 bits
2642 // (specifically, in this case, 0).
2643 void branchConvertDoubleToInt32(FPRegisterID src
, RegisterID dest
, JumpList
& failureCases
, FPRegisterID fpTemp
, bool negZeroCheck
= true)
2645 m_assembler
.cvtwd(fpTempRegister
, src
);
2646 m_assembler
.mfc1(dest
, fpTempRegister
);
2648 // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
2650 failureCases
.append(branch32(Equal
, dest
, MIPSRegisters::zero
));
2652 // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
2653 convertInt32ToDouble(dest
, fpTemp
);
2654 failureCases
.append(branchDouble(DoubleNotEqualOrUnordered
, fpTemp
, src
));
2657 Jump
branchDoubleNonZero(FPRegisterID reg
, FPRegisterID scratch
)
2659 m_assembler
.vmov(scratch
, MIPSRegisters::zero
, MIPSRegisters::zero
);
2660 return branchDouble(DoubleNotEqual
, reg
, scratch
);
2663 Jump
branchDoubleZeroOrNaN(FPRegisterID reg
, FPRegisterID scratch
)
2665 m_assembler
.vmov(scratch
, MIPSRegisters::zero
, MIPSRegisters::zero
);
2666 return branchDouble(DoubleEqualOrUnordered
, reg
, scratch
);
2669 // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc.
2670 static RelationalCondition
invert(RelationalCondition cond
)
2672 RelationalCondition r
;
2675 else if (cond
== NotEqual
)
2677 else if (cond
== Above
)
2679 else if (cond
== AboveOrEqual
)
2681 else if (cond
== Below
)
2683 else if (cond
== BelowOrEqual
)
2685 else if (cond
== GreaterThan
)
2686 r
= LessThanOrEqual
;
2687 else if (cond
== GreaterThanOrEqual
)
2689 else if (cond
== LessThan
)
2690 r
= GreaterThanOrEqual
;
2691 else if (cond
== LessThanOrEqual
)
2701 static FunctionPtr
readCallTarget(CodeLocationCall call
)
2703 return FunctionPtr(reinterpret_cast<void(*)()>(MIPSAssembler::readCallTarget(call
.dataLocation())));
2706 static void replaceWithJump(CodeLocationLabel instructionStart
, CodeLocationLabel destination
)
2708 MIPSAssembler::replaceWithJump(instructionStart
.dataLocation(), destination
.dataLocation());
2711 static ptrdiff_t maxJumpReplacementSize()
2713 MIPSAssembler::maxJumpReplacementSize();
2717 static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; }
2719 static CodeLocationLabel
startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label
)
2721 return label
.labelAtOffset(0);
2724 static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart
, RegisterID
, void* initialValue
)
2726 MIPSAssembler::revertJumpToMove(instructionStart
.dataLocation(), immTempRegister
, reinterpret_cast<int>(initialValue
) & 0xffff);
2729 static CodeLocationLabel
startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr
)
2731 UNREACHABLE_FOR_PLATFORM();
2732 return CodeLocationLabel();
2735 static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart
, Address
, void* initialValue
)
2737 UNREACHABLE_FOR_PLATFORM();
2742 // If m_fixedWidth is true, we will generate a fixed number of instructions.
2743 // Otherwise, we can emit any number of instructions.
2746 friend class LinkBuffer
;
2747 friend class RepatchBuffer
;
2749 static void linkCall(void* code
, Call call
, FunctionPtr function
)
2751 MIPSAssembler::linkCall(code
, call
.m_label
, function
.value());
2754 static void repatchCall(CodeLocationCall call
, CodeLocationLabel destination
)
2756 MIPSAssembler::relinkCall(call
.dataLocation(), destination
.executableAddress());
2759 static void repatchCall(CodeLocationCall call
, FunctionPtr destination
)
2761 MIPSAssembler::relinkCall(call
.dataLocation(), destination
.executableAddress());
2768 #endif // ENABLE(ASSEMBLER) && CPU(MIPS)
2770 #endif // MacroAssemblerMIPS_h