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 "MIPSAssembler.h"
33 #include "AbstractMacroAssembler.h"
37 class MacroAssemblerMIPS
: public AbstractMacroAssembler
<MIPSAssembler
> {
39 typedef MIPSRegisters::FPRegisterID FPRegisterID
;
46 static const Scale ScalePtr
= TimesFour
;
48 // For storing immediate number
49 static const RegisterID immTempRegister
= MIPSRegisters::t0
;
50 // For storing data loaded from the memory
51 static const RegisterID dataTempRegister
= MIPSRegisters::t1
;
52 // For storing address base
53 static const RegisterID addrTempRegister
= MIPSRegisters::t2
;
54 // For storing compare result
55 static const RegisterID cmpTempRegister
= MIPSRegisters::t3
;
58 static const FPRegisterID fpTempRegister
= MIPSRegisters::f16
;
60 static const int MaximumCompactPtrAlignedAddressOffset
= 0x7FFFFFFF;
62 enum RelationalCondition
{
75 enum ResultCondition
{
82 enum DoubleCondition
{
86 DoubleGreaterThanOrEqual
,
88 DoubleLessThanOrEqual
,
89 DoubleEqualOrUnordered
,
90 DoubleNotEqualOrUnordered
,
91 DoubleGreaterThanOrUnordered
,
92 DoubleGreaterThanOrEqualOrUnordered
,
93 DoubleLessThanOrUnordered
,
94 DoubleLessThanOrEqualOrUnordered
97 static const RegisterID stackPointerRegister
= MIPSRegisters::sp
;
98 static const RegisterID returnAddressRegister
= MIPSRegisters::ra
;
100 // Integer arithmetic operations:
102 // Operations are typically two operand - operation(source, srcDst)
103 // For many operations the source may be an TrustedImm32, the srcDst operand
104 // may often be a memory location (explictly described using an Address
107 void add32(RegisterID src
, RegisterID dest
)
109 m_assembler
.addu(dest
, dest
, src
);
112 void add32(TrustedImm32 imm
, RegisterID dest
)
114 add32(imm
, dest
, dest
);
117 void add32(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
119 if (!imm
.m_isPointer
&& imm
.m_value
>= -32768 && imm
.m_value
<= 32767
124 m_assembler
.addiu(dest
, src
, imm
.m_value
);
128 addu dest, src, immTemp
130 move(imm
, immTempRegister
);
131 m_assembler
.addu(dest
, src
, immTempRegister
);
135 void add32(TrustedImm32 imm
, Address address
)
137 if (address
.offset
>= -32768 && address
.offset
<= 32767
140 lw dataTemp, offset(base)
142 addu dataTemp, dataTemp, immTemp
143 sw dataTemp, offset(base)
145 m_assembler
.lw(dataTempRegister
, address
.base
, address
.offset
);
147 && imm
.m_value
>= -32768 && imm
.m_value
<= 32767
149 m_assembler
.addiu(dataTempRegister
, dataTempRegister
,
152 move(imm
, immTempRegister
);
153 m_assembler
.addu(dataTempRegister
, dataTempRegister
,
156 m_assembler
.sw(dataTempRegister
, address
.base
, address
.offset
);
159 lui addrTemp, (offset + 0x8000) >> 16
160 addu addrTemp, addrTemp, base
161 lw dataTemp, (offset & 0xffff)(addrTemp)
163 addu dataTemp, dataTemp, immTemp
164 sw dataTemp, (offset & 0xffff)(addrTemp)
166 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
167 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
168 m_assembler
.lw(dataTempRegister
, addrTempRegister
, address
.offset
);
170 if (imm
.m_value
>= -32768 && imm
.m_value
<= 32767 && !m_fixedWidth
)
171 m_assembler
.addiu(dataTempRegister
, dataTempRegister
,
174 move(imm
, immTempRegister
);
175 m_assembler
.addu(dataTempRegister
, dataTempRegister
,
178 m_assembler
.sw(dataTempRegister
, addrTempRegister
, address
.offset
);
182 void add32(Address src
, RegisterID dest
)
184 load32(src
, dataTempRegister
);
185 add32(dataTempRegister
, dest
);
188 void add32(RegisterID src
, Address dest
)
190 if (dest
.offset
>= -32768 && dest
.offset
<= 32767 && !m_fixedWidth
) {
192 lw dataTemp, offset(base)
193 addu dataTemp, dataTemp, src
194 sw dataTemp, offset(base)
196 m_assembler
.lw(dataTempRegister
, dest
.base
, dest
.offset
);
197 m_assembler
.addu(dataTempRegister
, dataTempRegister
, src
);
198 m_assembler
.sw(dataTempRegister
, dest
.base
, dest
.offset
);
201 lui addrTemp, (offset + 0x8000) >> 16
202 addu addrTemp, addrTemp, base
203 lw dataTemp, (offset & 0xffff)(addrTemp)
204 addu dataTemp, dataTemp, src
205 sw dataTemp, (offset & 0xffff)(addrTemp)
207 m_assembler
.lui(addrTempRegister
, (dest
.offset
+ 0x8000) >> 16);
208 m_assembler
.addu(addrTempRegister
, addrTempRegister
, dest
.base
);
209 m_assembler
.lw(dataTempRegister
, addrTempRegister
, dest
.offset
);
210 m_assembler
.addu(dataTempRegister
, dataTempRegister
, src
);
211 m_assembler
.sw(dataTempRegister
, addrTempRegister
, dest
.offset
);
215 void add32(TrustedImm32 imm
, AbsoluteAddress address
)
220 lw dataTemp, 0(addrTemp)
221 addu dataTemp, dataTemp, immTemp
222 sw dataTemp, 0(addrTemp)
224 move(TrustedImmPtr(address
.m_ptr
), addrTempRegister
);
225 m_assembler
.lw(dataTempRegister
, addrTempRegister
, 0);
226 if (!imm
.m_isPointer
&& imm
.m_value
>= -32768 && imm
.m_value
<= 32767
228 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, imm
.m_value
);
230 move(imm
, immTempRegister
);
231 m_assembler
.addu(dataTempRegister
, dataTempRegister
, immTempRegister
);
233 m_assembler
.sw(dataTempRegister
, addrTempRegister
, 0);
236 void and32(RegisterID src
, RegisterID dest
)
238 m_assembler
.andInsn(dest
, dest
, src
);
241 void and32(TrustedImm32 imm
, RegisterID dest
)
243 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
)
244 move(MIPSRegisters::zero
, dest
);
245 else if (!imm
.m_isPointer
&& imm
.m_value
> 0 && imm
.m_value
< 65535
247 m_assembler
.andi(dest
, dest
, imm
.m_value
);
251 and dest, dest, immTemp
253 move(imm
, immTempRegister
);
254 m_assembler
.andInsn(dest
, dest
, immTempRegister
);
258 void lshift32(TrustedImm32 imm
, RegisterID dest
)
260 m_assembler
.sll(dest
, dest
, imm
.m_value
);
263 void lshift32(RegisterID shiftAmount
, RegisterID dest
)
265 m_assembler
.sllv(dest
, dest
, shiftAmount
);
268 void mul32(RegisterID src
, RegisterID dest
)
270 m_assembler
.mul(dest
, dest
, src
);
273 void mul32(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
275 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
)
276 move(MIPSRegisters::zero
, dest
);
277 else if (!imm
.m_isPointer
&& imm
.m_value
== 1 && !m_fixedWidth
)
282 mul dest, src, dataTemp
284 move(imm
, dataTempRegister
);
285 m_assembler
.mul(dest
, src
, dataTempRegister
);
289 void neg32(RegisterID srcDest
)
291 m_assembler
.subu(srcDest
, MIPSRegisters::zero
, srcDest
);
294 void not32(RegisterID srcDest
)
296 m_assembler
.nor(srcDest
, srcDest
, MIPSRegisters::zero
);
299 void or32(RegisterID src
, RegisterID dest
)
301 m_assembler
.orInsn(dest
, dest
, src
);
304 void or32(TrustedImm32 imm
, RegisterID dest
)
306 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
)
309 if (!imm
.m_isPointer
&& imm
.m_value
> 0 && imm
.m_value
< 65535
311 m_assembler
.ori(dest
, dest
, imm
.m_value
);
317 or dest, dest, dataTemp
319 move(imm
, dataTempRegister
);
320 m_assembler
.orInsn(dest
, dest
, dataTempRegister
);
323 void rshift32(RegisterID shiftAmount
, RegisterID dest
)
325 m_assembler
.srav(dest
, dest
, shiftAmount
);
328 void rshift32(TrustedImm32 imm
, RegisterID dest
)
330 m_assembler
.sra(dest
, dest
, imm
.m_value
);
333 void urshift32(RegisterID shiftAmount
, RegisterID dest
)
335 m_assembler
.srlv(dest
, dest
, shiftAmount
);
338 void urshift32(TrustedImm32 imm
, RegisterID dest
)
340 m_assembler
.srl(dest
, dest
, imm
.m_value
);
343 void sub32(RegisterID src
, RegisterID dest
)
345 m_assembler
.subu(dest
, dest
, src
);
348 void sub32(TrustedImm32 imm
, RegisterID dest
)
350 if (!imm
.m_isPointer
&& imm
.m_value
>= -32767 && imm
.m_value
<= 32768
355 m_assembler
.addiu(dest
, dest
, -imm
.m_value
);
359 subu dest, src, immTemp
361 move(imm
, immTempRegister
);
362 m_assembler
.subu(dest
, dest
, immTempRegister
);
366 void sub32(TrustedImm32 imm
, Address address
)
368 if (address
.offset
>= -32768 && address
.offset
<= 32767
371 lw dataTemp, offset(base)
373 subu dataTemp, dataTemp, immTemp
374 sw dataTemp, offset(base)
376 m_assembler
.lw(dataTempRegister
, address
.base
, address
.offset
);
378 && imm
.m_value
>= -32767 && imm
.m_value
<= 32768
380 m_assembler
.addiu(dataTempRegister
, dataTempRegister
,
383 move(imm
, immTempRegister
);
384 m_assembler
.subu(dataTempRegister
, dataTempRegister
,
387 m_assembler
.sw(dataTempRegister
, address
.base
, address
.offset
);
390 lui addrTemp, (offset + 0x8000) >> 16
391 addu addrTemp, addrTemp, base
392 lw dataTemp, (offset & 0xffff)(addrTemp)
394 subu dataTemp, dataTemp, immTemp
395 sw dataTemp, (offset & 0xffff)(addrTemp)
397 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
398 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
399 m_assembler
.lw(dataTempRegister
, addrTempRegister
, address
.offset
);
402 && imm
.m_value
>= -32767 && imm
.m_value
<= 32768
404 m_assembler
.addiu(dataTempRegister
, dataTempRegister
,
407 move(imm
, immTempRegister
);
408 m_assembler
.subu(dataTempRegister
, dataTempRegister
,
411 m_assembler
.sw(dataTempRegister
, addrTempRegister
, address
.offset
);
415 void sub32(Address src
, RegisterID dest
)
417 load32(src
, dataTempRegister
);
418 sub32(dataTempRegister
, dest
);
421 void sub32(TrustedImm32 imm
, AbsoluteAddress address
)
426 lw dataTemp, 0(addrTemp)
427 subu dataTemp, dataTemp, immTemp
428 sw dataTemp, 0(addrTemp)
430 move(TrustedImmPtr(address
.m_ptr
), addrTempRegister
);
431 m_assembler
.lw(dataTempRegister
, addrTempRegister
, 0);
433 if (!imm
.m_isPointer
&& imm
.m_value
>= -32767 && imm
.m_value
<= 32768
435 m_assembler
.addiu(dataTempRegister
, dataTempRegister
,
438 move(imm
, immTempRegister
);
439 m_assembler
.subu(dataTempRegister
, dataTempRegister
, immTempRegister
);
441 m_assembler
.sw(dataTempRegister
, addrTempRegister
, 0);
444 void xor32(RegisterID src
, RegisterID dest
)
446 m_assembler
.xorInsn(dest
, dest
, src
);
449 void xor32(TrustedImm32 imm
, RegisterID dest
)
453 xor dest, dest, immTemp
455 move(imm
, immTempRegister
);
456 m_assembler
.xorInsn(dest
, dest
, immTempRegister
);
459 void sqrtDouble(FPRegisterID src
, FPRegisterID dst
)
461 m_assembler
.sqrtd(dst
, src
);
464 // Memory access operations:
466 // Loads are of the form load(address, destination) and stores of the form
467 // store(source, address). The source for a store may be an TrustedImm32. Address
468 // operand objects to loads and store will be implicitly constructed if a
469 // register is passed.
471 /* Need to use zero-extened load byte for load8. */
472 void load8(ImplicitAddress address
, RegisterID dest
)
474 if (address
.offset
>= -32768 && address
.offset
<= 32767
476 m_assembler
.lbu(dest
, address
.base
, address
.offset
);
479 lui addrTemp, (offset + 0x8000) >> 16
480 addu addrTemp, addrTemp, base
481 lbu dest, (offset & 0xffff)(addrTemp)
483 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
484 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
485 m_assembler
.lbu(dest
, addrTempRegister
, address
.offset
);
489 void load32(ImplicitAddress address
, RegisterID dest
)
491 if (address
.offset
>= -32768 && address
.offset
<= 32767
493 m_assembler
.lw(dest
, address
.base
, address
.offset
);
496 lui addrTemp, (offset + 0x8000) >> 16
497 addu addrTemp, addrTemp, base
498 lw dest, (offset & 0xffff)(addrTemp)
500 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
501 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
502 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
506 void load32(BaseIndex address
, RegisterID dest
)
508 if (address
.offset
>= -32768 && address
.offset
<= 32767
511 sll addrTemp, address.index, address.scale
512 addu addrTemp, addrTemp, address.base
513 lw dest, address.offset(addrTemp)
515 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
516 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
517 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
520 sll addrTemp, address.index, address.scale
521 addu addrTemp, addrTemp, address.base
522 lui immTemp, (address.offset + 0x8000) >> 16
523 addu addrTemp, addrTemp, immTemp
524 lw dest, (address.offset & 0xffff)(at)
526 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
527 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
528 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
529 m_assembler
.addu(addrTempRegister
, addrTempRegister
,
531 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
535 void load32WithUnalignedHalfWords(BaseIndex address
, RegisterID dest
)
537 if (address
.offset
>= -32768 && address
.offset
<= 32764
540 sll addrTemp, address.index, address.scale
541 addu addrTemp, addrTemp, address.base
543 lwl dest, address.offset(addrTemp)
544 lwr dest, address.offset+3(addrTemp)
546 lwl dest, address.offset+3(addrTemp)
547 lwr dest, address.offset(addrTemp)
549 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
550 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
552 m_assembler
.lwl(dest
, addrTempRegister
, address
.offset
);
553 m_assembler
.lwr(dest
, addrTempRegister
, address
.offset
+ 3);
555 m_assembler
.lwl(dest
, addrTempRegister
, address
.offset
+ 3);
556 m_assembler
.lwr(dest
, addrTempRegister
, address
.offset
);
561 sll addrTemp, address.index, address.scale
562 addu addrTemp, addrTemp, address.base
563 lui immTemp, address.offset >> 16
564 ori immTemp, immTemp, address.offset & 0xffff
565 addu addrTemp, addrTemp, immTemp
573 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
574 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
575 m_assembler
.lui(immTempRegister
, address
.offset
>> 16);
576 m_assembler
.ori(immTempRegister
, immTempRegister
, address
.offset
);
577 m_assembler
.addu(addrTempRegister
, addrTempRegister
,
580 m_assembler
.lwl(dest
, addrTempRegister
, 0);
581 m_assembler
.lwr(dest
, addrTempRegister
, 3);
583 m_assembler
.lwl(dest
, addrTempRegister
, 3);
584 m_assembler
.lwr(dest
, addrTempRegister
, 0);
589 void load32(const void* address
, RegisterID dest
)
595 move(TrustedImmPtr(address
), addrTempRegister
);
596 m_assembler
.lw(dest
, addrTempRegister
, 0);
599 DataLabel32
load32WithAddressOffsetPatch(Address address
, RegisterID dest
)
603 lui addrTemp, address.offset >> 16
604 ori addrTemp, addrTemp, address.offset & 0xffff
605 addu addrTemp, addrTemp, address.base
608 DataLabel32
dataLabel(this);
609 move(TrustedImm32(address
.offset
), addrTempRegister
);
610 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
611 m_assembler
.lw(dest
, addrTempRegister
, 0);
612 m_fixedWidth
= false;
616 DataLabelCompact
load32WithCompactAddressOffsetPatch(Address address
, RegisterID dest
)
618 DataLabelCompact
dataLabel(this);
619 load32WithAddressOffsetPatch(address
, dest
);
623 /* Need to use zero-extened load half-word for load16. */
624 void load16(ImplicitAddress address
, RegisterID dest
)
626 if (address
.offset
>= -32768 && address
.offset
<= 32767
628 m_assembler
.lhu(dest
, address
.base
, address
.offset
);
631 lui addrTemp, (offset + 0x8000) >> 16
632 addu addrTemp, addrTemp, base
633 lhu dest, (offset & 0xffff)(addrTemp)
635 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
636 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
637 m_assembler
.lhu(dest
, addrTempRegister
, address
.offset
);
641 /* Need to use zero-extened load half-word for load16. */
642 void load16(BaseIndex address
, RegisterID dest
)
644 if (address
.offset
>= -32768 && address
.offset
<= 32767
647 sll addrTemp, address.index, address.scale
648 addu addrTemp, addrTemp, address.base
649 lhu dest, address.offset(addrTemp)
651 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
652 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
653 m_assembler
.lhu(dest
, addrTempRegister
, address
.offset
);
656 sll addrTemp, address.index, address.scale
657 addu addrTemp, addrTemp, address.base
658 lui immTemp, (address.offset + 0x8000) >> 16
659 addu addrTemp, addrTemp, immTemp
660 lhu dest, (address.offset & 0xffff)(addrTemp)
662 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
663 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
664 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
665 m_assembler
.addu(addrTempRegister
, addrTempRegister
,
667 m_assembler
.lhu(dest
, addrTempRegister
, address
.offset
);
671 DataLabel32
store32WithAddressOffsetPatch(RegisterID src
, Address address
)
675 lui addrTemp, address.offset >> 16
676 ori addrTemp, addrTemp, address.offset & 0xffff
677 addu addrTemp, addrTemp, address.base
680 DataLabel32
dataLabel(this);
681 move(TrustedImm32(address
.offset
), addrTempRegister
);
682 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
683 m_assembler
.sw(src
, addrTempRegister
, 0);
684 m_fixedWidth
= false;
688 void store32(RegisterID src
, ImplicitAddress address
)
690 if (address
.offset
>= -32768 && address
.offset
<= 32767
692 m_assembler
.sw(src
, address
.base
, address
.offset
);
695 lui addrTemp, (offset + 0x8000) >> 16
696 addu addrTemp, addrTemp, base
697 sw src, (offset & 0xffff)(addrTemp)
699 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
700 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
701 m_assembler
.sw(src
, addrTempRegister
, address
.offset
);
705 void store32(RegisterID src
, BaseIndex address
)
707 if (address
.offset
>= -32768 && address
.offset
<= 32767
710 sll addrTemp, address.index, address.scale
711 addu addrTemp, addrTemp, address.base
712 sw src, address.offset(addrTemp)
714 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
715 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
716 m_assembler
.sw(src
, addrTempRegister
, address
.offset
);
719 sll addrTemp, address.index, address.scale
720 addu addrTemp, addrTemp, address.base
721 lui immTemp, (address.offset + 0x8000) >> 16
722 addu addrTemp, addrTemp, immTemp
723 sw src, (address.offset & 0xffff)(at)
725 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
726 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
727 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
728 m_assembler
.addu(addrTempRegister
, addrTempRegister
,
730 m_assembler
.sw(src
, addrTempRegister
, address
.offset
);
734 void store32(TrustedImm32 imm
, ImplicitAddress address
)
736 if (address
.offset
>= -32768 && address
.offset
<= 32767
738 if (!imm
.m_isPointer
&& !imm
.m_value
)
739 m_assembler
.sw(MIPSRegisters::zero
, address
.base
,
742 move(imm
, immTempRegister
);
743 m_assembler
.sw(immTempRegister
, address
.base
, address
.offset
);
747 lui addrTemp, (offset + 0x8000) >> 16
748 addu addrTemp, addrTemp, base
749 sw immTemp, (offset & 0xffff)(addrTemp)
751 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
752 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
753 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
)
754 m_assembler
.sw(MIPSRegisters::zero
, addrTempRegister
,
757 move(imm
, immTempRegister
);
758 m_assembler
.sw(immTempRegister
, addrTempRegister
,
764 void store32(RegisterID src
, const void* address
)
770 move(TrustedImmPtr(address
), addrTempRegister
);
771 m_assembler
.sw(src
, addrTempRegister
, 0);
774 void store32(TrustedImm32 imm
, const void* address
)
781 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
) {
782 move(TrustedImmPtr(address
), addrTempRegister
);
783 m_assembler
.sw(MIPSRegisters::zero
, addrTempRegister
, 0);
785 move(imm
, immTempRegister
);
786 move(TrustedImmPtr(address
), addrTempRegister
);
787 m_assembler
.sw(immTempRegister
, addrTempRegister
, 0);
791 // Floating-point operations:
793 bool supportsFloatingPoint() const
795 #if WTF_MIPS_DOUBLE_FLOAT
802 bool supportsFloatingPointTruncate() const
804 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
811 bool supportsFloatingPointSqrt() const
813 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
820 // Stack manipulation operations:
822 // The ABI is assumed to provide a stack abstraction to memory,
823 // containing machine word sized units of data. Push and pop
824 // operations add and remove a single register sized unit of data
825 // to or from the stack. Peek and poke operations read or write
826 // values on the stack, without moving the current stack position.
828 void pop(RegisterID dest
)
830 m_assembler
.lw(dest
, MIPSRegisters::sp
, 0);
831 m_assembler
.addiu(MIPSRegisters::sp
, MIPSRegisters::sp
, 4);
834 void push(RegisterID src
)
836 m_assembler
.addiu(MIPSRegisters::sp
, MIPSRegisters::sp
, -4);
837 m_assembler
.sw(src
, MIPSRegisters::sp
, 0);
840 void push(Address address
)
842 load32(address
, dataTempRegister
);
843 push(dataTempRegister
);
846 void push(TrustedImm32 imm
)
848 move(imm
, immTempRegister
);
849 push(immTempRegister
);
852 // Register move operations:
854 // Move values in registers.
856 void move(TrustedImm32 imm
, RegisterID dest
)
858 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
)
859 move(MIPSRegisters::zero
, dest
);
860 else if (imm
.m_isPointer
|| m_fixedWidth
) {
861 m_assembler
.lui(dest
, imm
.m_value
>> 16);
862 m_assembler
.ori(dest
, dest
, imm
.m_value
);
864 m_assembler
.li(dest
, imm
.m_value
);
867 void move(RegisterID src
, RegisterID dest
)
869 if (src
!= dest
|| m_fixedWidth
)
870 m_assembler
.move(dest
, src
);
873 void move(TrustedImmPtr imm
, RegisterID dest
)
875 move(TrustedImm32(imm
), dest
);
878 void swap(RegisterID reg1
, RegisterID reg2
)
880 move(reg1
, immTempRegister
);
882 move(immTempRegister
, reg2
);
885 void signExtend32ToPtr(RegisterID src
, RegisterID dest
)
887 if (src
!= dest
|| m_fixedWidth
)
891 void zeroExtend32ToPtr(RegisterID src
, RegisterID dest
)
893 if (src
!= dest
|| m_fixedWidth
)
897 // Forwards / external control flow operations:
899 // This set of jump and conditional branch operations return a Jump
900 // object which may linked at a later point, allow forwards jump,
901 // or jumps that will require external linkage (after the code has been
904 // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
905 // respecitvely, for unsigned comparisons the names b, a, be, and ae are
906 // used (representing the names 'below' and 'above').
908 // Operands to the comparision are provided in the expected order, e.g.
909 // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when
910 // treated as a signed 32bit value, is less than or equal to 5.
912 // jz and jnz test whether the first operand is equal to zero, and take
913 // an optional second operand of a mask under which to perform the test.
915 Jump
branch8(RelationalCondition cond
, Address left
, TrustedImm32 right
)
917 // Make sure the immediate value is unsigned 8 bits.
918 ASSERT(!(right
.m_value
& 0xFFFFFF00));
919 load8(left
, dataTempRegister
);
920 move(right
, immTempRegister
);
921 return branch32(cond
, dataTempRegister
, immTempRegister
);
924 Jump
branch32(RelationalCondition cond
, RegisterID left
, RegisterID right
)
927 return branchEqual(left
, right
);
928 if (cond
== NotEqual
)
929 return branchNotEqual(left
, right
);
931 m_assembler
.sltu(cmpTempRegister
, right
, left
);
932 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
934 if (cond
== AboveOrEqual
) {
935 m_assembler
.sltu(cmpTempRegister
, left
, right
);
936 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
939 m_assembler
.sltu(cmpTempRegister
, left
, right
);
940 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
942 if (cond
== BelowOrEqual
) {
943 m_assembler
.sltu(cmpTempRegister
, right
, left
);
944 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
946 if (cond
== GreaterThan
) {
947 m_assembler
.slt(cmpTempRegister
, right
, left
);
948 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
950 if (cond
== GreaterThanOrEqual
) {
951 m_assembler
.slt(cmpTempRegister
, left
, right
);
952 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
954 if (cond
== LessThan
) {
955 m_assembler
.slt(cmpTempRegister
, left
, right
);
956 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
958 if (cond
== LessThanOrEqual
) {
959 m_assembler
.slt(cmpTempRegister
, right
, left
);
960 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
967 Jump
branch32(RelationalCondition cond
, RegisterID left
, TrustedImm32 right
)
969 move(right
, immTempRegister
);
970 return branch32(cond
, left
, immTempRegister
);
973 Jump
branch32(RelationalCondition cond
, RegisterID left
, Address right
)
975 load32(right
, dataTempRegister
);
976 return branch32(cond
, left
, dataTempRegister
);
979 Jump
branch32(RelationalCondition cond
, Address left
, RegisterID right
)
981 load32(left
, dataTempRegister
);
982 return branch32(cond
, dataTempRegister
, right
);
985 Jump
branch32(RelationalCondition cond
, Address left
, TrustedImm32 right
)
987 load32(left
, dataTempRegister
);
988 move(right
, immTempRegister
);
989 return branch32(cond
, dataTempRegister
, immTempRegister
);
992 Jump
branch32(RelationalCondition cond
, BaseIndex left
, TrustedImm32 right
)
994 load32(left
, dataTempRegister
);
995 // Be careful that the previous load32() uses immTempRegister.
996 // So, we need to put move() after load32().
997 move(right
, immTempRegister
);
998 return branch32(cond
, dataTempRegister
, immTempRegister
);
1001 Jump
branch32WithUnalignedHalfWords(RelationalCondition cond
, BaseIndex left
, TrustedImm32 right
)
1003 load32WithUnalignedHalfWords(left
, dataTempRegister
);
1004 // Be careful that the previous load32WithUnalignedHalfWords()
1005 // uses immTempRegister.
1006 // So, we need to put move() after load32WithUnalignedHalfWords().
1007 move(right
, immTempRegister
);
1008 return branch32(cond
, dataTempRegister
, immTempRegister
);
1011 Jump
branch32(RelationalCondition cond
, AbsoluteAddress left
, RegisterID right
)
1013 load32(left
.m_ptr
, dataTempRegister
);
1014 return branch32(cond
, dataTempRegister
, right
);
1017 Jump
branch32(RelationalCondition cond
, AbsoluteAddress left
, TrustedImm32 right
)
1019 load32(left
.m_ptr
, dataTempRegister
);
1020 move(right
, immTempRegister
);
1021 return branch32(cond
, dataTempRegister
, immTempRegister
);
1024 Jump
branch16(RelationalCondition cond
, BaseIndex left
, RegisterID right
)
1026 load16(left
, dataTempRegister
);
1027 return branch32(cond
, dataTempRegister
, right
);
1030 Jump
branch16(RelationalCondition cond
, BaseIndex left
, TrustedImm32 right
)
1032 ASSERT(!(right
.m_value
& 0xFFFF0000));
1033 load16(left
, dataTempRegister
);
1034 // Be careful that the previous load16() uses immTempRegister.
1035 // So, we need to put move() after load16().
1036 move(right
, immTempRegister
);
1037 return branch32(cond
, dataTempRegister
, immTempRegister
);
1040 Jump
branchTest32(ResultCondition cond
, RegisterID reg
, RegisterID mask
)
1042 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1043 m_assembler
.andInsn(cmpTempRegister
, reg
, mask
);
1045 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1046 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1049 Jump
branchTest32(ResultCondition cond
, RegisterID reg
, TrustedImm32 mask
= TrustedImm32(-1))
1051 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1052 if (mask
.m_value
== -1 && !m_fixedWidth
) {
1054 return branchEqual(reg
, MIPSRegisters::zero
);
1055 return branchNotEqual(reg
, MIPSRegisters::zero
);
1057 move(mask
, immTempRegister
);
1058 return branchTest32(cond
, reg
, immTempRegister
);
1061 Jump
branchTest32(ResultCondition cond
, Address address
, TrustedImm32 mask
= TrustedImm32(-1))
1063 load32(address
, dataTempRegister
);
1064 return branchTest32(cond
, dataTempRegister
, mask
);
1067 Jump
branchTest32(ResultCondition cond
, BaseIndex address
, TrustedImm32 mask
= TrustedImm32(-1))
1069 load32(address
, dataTempRegister
);
1070 return branchTest32(cond
, dataTempRegister
, mask
);
1073 Jump
branchTest8(ResultCondition cond
, Address address
, TrustedImm32 mask
= TrustedImm32(-1))
1075 load8(address
, dataTempRegister
);
1076 return branchTest32(cond
, dataTempRegister
, mask
);
1081 return branchEqual(MIPSRegisters::zero
, MIPSRegisters::zero
);
1084 void jump(RegisterID target
)
1086 m_assembler
.jr(target
);
1090 void jump(Address address
)
1092 m_fixedWidth
= true;
1093 load32(address
, MIPSRegisters::t9
);
1094 m_assembler
.jr(MIPSRegisters::t9
);
1096 m_fixedWidth
= false;
1099 // Arithmetic control flow operations:
1101 // This set of conditional branch operations branch based
1102 // on the result of an arithmetic operation. The operation
1103 // is performed as normal, storing the result.
1105 // * jz operations branch if the result is zero.
1106 // * jo operations branch if the (signed) arithmetic
1107 // operation caused an overflow to occur.
1109 Jump
branchAdd32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1111 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1112 if (cond
== Overflow
) {
1115 xor cmpTemp, dataTemp, src
1116 bltz cmpTemp, No_overflow # diff sign bit -> no overflow
1117 addu dest, dataTemp, src
1118 xor cmpTemp, dest, dataTemp
1119 bgez cmpTemp, No_overflow # same sign big -> no overflow
1129 move(dest
, dataTempRegister
);
1130 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, src
);
1131 m_assembler
.bltz(cmpTempRegister
, 10);
1132 m_assembler
.addu(dest
, dataTempRegister
, src
);
1133 m_assembler
.xorInsn(cmpTempRegister
, dest
, dataTempRegister
);
1134 m_assembler
.bgez(cmpTempRegister
, 7);
1138 if (cond
== Signed
) {
1140 // Check if dest is negative.
1141 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1142 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1146 return branchEqual(dest
, MIPSRegisters::zero
);
1148 if (cond
== NonZero
) {
1150 return branchNotEqual(dest
, MIPSRegisters::zero
);
1156 Jump
branchAdd32(ResultCondition cond
, TrustedImm32 imm
, RegisterID dest
)
1158 move(imm
, immTempRegister
);
1159 return branchAdd32(cond
, immTempRegister
, dest
);
1162 Jump
branchMul32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1164 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1165 if (cond
== Overflow
) {
1170 sra addrTemp, dest, 31
1171 beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow
1181 m_assembler
.mult(src
, dest
);
1182 m_assembler
.mfhi(dataTempRegister
);
1183 m_assembler
.mflo(dest
);
1184 m_assembler
.sra(addrTempRegister
, dest
, 31);
1185 m_assembler
.beq(dataTempRegister
, addrTempRegister
, 7);
1189 if (cond
== Signed
) {
1191 // Check if dest is negative.
1192 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1193 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1197 return branchEqual(dest
, MIPSRegisters::zero
);
1199 if (cond
== NonZero
) {
1201 return branchNotEqual(dest
, MIPSRegisters::zero
);
1207 Jump
branchMul32(ResultCondition cond
, TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
1209 move(imm
, immTempRegister
);
1211 return branchMul32(cond
, immTempRegister
, dest
);
1214 Jump
branchSub32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1216 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1217 if (cond
== Overflow
) {
1220 xor cmpTemp, dataTemp, src
1221 bgez cmpTemp, No_overflow # same sign bit -> no overflow
1222 subu dest, dataTemp, src
1223 xor cmpTemp, dest, dataTemp
1224 bgez cmpTemp, No_overflow # same sign bit -> no overflow
1234 move(dest
, dataTempRegister
);
1235 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, src
);
1236 m_assembler
.bgez(cmpTempRegister
, 10);
1237 m_assembler
.subu(dest
, dataTempRegister
, src
);
1238 m_assembler
.xorInsn(cmpTempRegister
, dest
, dataTempRegister
);
1239 m_assembler
.bgez(cmpTempRegister
, 7);
1243 if (cond
== Signed
) {
1245 // Check if dest is negative.
1246 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1247 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1251 return branchEqual(dest
, MIPSRegisters::zero
);
1253 if (cond
== NonZero
) {
1255 return branchNotEqual(dest
, MIPSRegisters::zero
);
1261 Jump
branchSub32(ResultCondition cond
, TrustedImm32 imm
, RegisterID dest
)
1263 move(imm
, immTempRegister
);
1264 return branchSub32(cond
, immTempRegister
, dest
);
1267 Jump
branchOr32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1269 ASSERT((cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1270 if (cond
== Signed
) {
1272 // Check if dest is negative.
1273 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1274 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1278 return branchEqual(dest
, MIPSRegisters::zero
);
1280 if (cond
== NonZero
) {
1282 return branchNotEqual(dest
, MIPSRegisters::zero
);
1288 // Miscellaneous operations:
1297 /* We need two words for relaxation. */
1302 return Call(m_assembler
.label(), Call::LinkableNear
);
1307 m_assembler
.lui(MIPSRegisters::t9
, 0);
1308 m_assembler
.ori(MIPSRegisters::t9
, MIPSRegisters::t9
, 0);
1309 m_assembler
.jalr(MIPSRegisters::t9
);
1311 return Call(m_assembler
.label(), Call::Linkable
);
1314 Call
call(RegisterID target
)
1316 m_assembler
.jalr(target
);
1318 return Call(m_assembler
.label(), Call::None
);
1321 Call
call(Address address
)
1323 m_fixedWidth
= true;
1324 load32(address
, MIPSRegisters::t9
);
1325 m_assembler
.jalr(MIPSRegisters::t9
);
1327 m_fixedWidth
= false;
1328 return Call(m_assembler
.label(), Call::None
);
1333 m_assembler
.jr(MIPSRegisters::ra
);
1337 void compare32(RelationalCondition cond
, RegisterID left
, RegisterID right
, RegisterID dest
)
1339 if (cond
== Equal
) {
1340 m_assembler
.xorInsn(dest
, left
, right
);
1341 m_assembler
.sltiu(dest
, dest
, 1);
1342 } else if (cond
== NotEqual
) {
1343 m_assembler
.xorInsn(dest
, left
, right
);
1344 m_assembler
.sltu(dest
, MIPSRegisters::zero
, dest
);
1345 } else if (cond
== Above
)
1346 m_assembler
.sltu(dest
, right
, left
);
1347 else if (cond
== AboveOrEqual
) {
1348 m_assembler
.sltu(dest
, left
, right
);
1349 m_assembler
.xori(dest
, dest
, 1);
1350 } else if (cond
== Below
)
1351 m_assembler
.sltu(dest
, left
, right
);
1352 else if (cond
== BelowOrEqual
) {
1353 m_assembler
.sltu(dest
, right
, left
);
1354 m_assembler
.xori(dest
, dest
, 1);
1355 } else if (cond
== GreaterThan
)
1356 m_assembler
.slt(dest
, right
, left
);
1357 else if (cond
== GreaterThanOrEqual
) {
1358 m_assembler
.slt(dest
, left
, right
);
1359 m_assembler
.xori(dest
, dest
, 1);
1360 } else if (cond
== LessThan
)
1361 m_assembler
.slt(dest
, left
, right
);
1362 else if (cond
== LessThanOrEqual
) {
1363 m_assembler
.slt(dest
, right
, left
);
1364 m_assembler
.xori(dest
, dest
, 1);
1368 void compare32(RelationalCondition cond
, RegisterID left
, TrustedImm32 right
, RegisterID dest
)
1370 move(right
, immTempRegister
);
1371 compare32(cond
, left
, immTempRegister
, dest
);
1374 void test8(ResultCondition cond
, Address address
, TrustedImm32 mask
, RegisterID dest
)
1376 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1377 load8(address
, dataTempRegister
);
1378 if (mask
.m_value
== -1 && !m_fixedWidth
) {
1380 m_assembler
.sltiu(dest
, dataTempRegister
, 1);
1382 m_assembler
.sltu(dest
, MIPSRegisters::zero
, dataTempRegister
);
1384 move(mask
, immTempRegister
);
1385 m_assembler
.andInsn(cmpTempRegister
, dataTempRegister
,
1388 m_assembler
.sltiu(dest
, cmpTempRegister
, 1);
1390 m_assembler
.sltu(dest
, MIPSRegisters::zero
, cmpTempRegister
);
1394 void test32(ResultCondition cond
, Address address
, TrustedImm32 mask
, RegisterID dest
)
1396 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1397 load32(address
, dataTempRegister
);
1398 if (mask
.m_value
== -1 && !m_fixedWidth
) {
1400 m_assembler
.sltiu(dest
, dataTempRegister
, 1);
1402 m_assembler
.sltu(dest
, MIPSRegisters::zero
, dataTempRegister
);
1404 move(mask
, immTempRegister
);
1405 m_assembler
.andInsn(cmpTempRegister
, dataTempRegister
,
1408 m_assembler
.sltiu(dest
, cmpTempRegister
, 1);
1410 m_assembler
.sltu(dest
, MIPSRegisters::zero
, cmpTempRegister
);
1414 DataLabel32
moveWithPatch(TrustedImm32 imm
, RegisterID dest
)
1416 m_fixedWidth
= true;
1417 DataLabel32
label(this);
1419 m_fixedWidth
= false;
1423 DataLabelPtr
moveWithPatch(TrustedImmPtr initialValue
, RegisterID dest
)
1425 m_fixedWidth
= true;
1426 DataLabelPtr
label(this);
1427 move(initialValue
, dest
);
1428 m_fixedWidth
= false;
1432 Jump
branchPtrWithPatch(RelationalCondition cond
, RegisterID left
, DataLabelPtr
& dataLabel
, TrustedImmPtr initialRightValue
= TrustedImmPtr(0))
1434 m_fixedWidth
= true;
1435 dataLabel
= moveWithPatch(initialRightValue
, immTempRegister
);
1436 Jump temp
= branch32(cond
, left
, immTempRegister
);
1437 m_fixedWidth
= false;
1441 Jump
branchPtrWithPatch(RelationalCondition cond
, Address left
, DataLabelPtr
& dataLabel
, TrustedImmPtr initialRightValue
= TrustedImmPtr(0))
1443 m_fixedWidth
= true;
1444 load32(left
, dataTempRegister
);
1445 dataLabel
= moveWithPatch(initialRightValue
, immTempRegister
);
1446 Jump temp
= branch32(cond
, dataTempRegister
, immTempRegister
);
1447 m_fixedWidth
= false;
1451 DataLabelPtr
storePtrWithPatch(TrustedImmPtr initialValue
, ImplicitAddress address
)
1453 m_fixedWidth
= true;
1454 DataLabelPtr dataLabel
= moveWithPatch(initialValue
, dataTempRegister
);
1455 store32(dataTempRegister
, address
);
1456 m_fixedWidth
= false;
1460 DataLabelPtr
storePtrWithPatch(ImplicitAddress address
)
1462 return storePtrWithPatch(TrustedImmPtr(0), address
);
1465 Call
tailRecursiveCall()
1467 // Like a normal call, but don't update the returned address register
1468 m_fixedWidth
= true;
1469 move(TrustedImm32(0), MIPSRegisters::t9
);
1470 m_assembler
.jr(MIPSRegisters::t9
);
1472 m_fixedWidth
= false;
1473 return Call(m_assembler
.label(), Call::Linkable
);
1476 Call
makeTailRecursiveCall(Jump oldJump
)
1479 return tailRecursiveCall();
1482 void loadDouble(ImplicitAddress address
, FPRegisterID dest
)
1486 li addrTemp, address.offset
1487 addu addrTemp, addrTemp, base
1488 lwc1 dest, 0(addrTemp)
1489 lwc1 dest+1, 4(addrTemp)
1491 move(TrustedImm32(address
.offset
), addrTempRegister
);
1492 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1493 m_assembler
.lwc1(dest
, addrTempRegister
, 0);
1494 m_assembler
.lwc1(FPRegisterID(dest
+ 1), addrTempRegister
, 4);
1496 if (address
.offset
>= -32768 && address
.offset
<= 32767
1498 m_assembler
.ldc1(dest
, address
.base
, address
.offset
);
1501 lui addrTemp, (offset + 0x8000) >> 16
1502 addu addrTemp, addrTemp, base
1503 ldc1 dest, (offset & 0xffff)(addrTemp)
1505 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
1506 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1507 m_assembler
.ldc1(dest
, addrTempRegister
, address
.offset
);
1512 void loadDouble(const void* address
, FPRegisterID dest
)
1516 li addrTemp, address
1517 lwc1 dest, 0(addrTemp)
1518 lwc1 dest+1, 4(addrTemp)
1520 move(TrustedImmPtr(address
), addrTempRegister
);
1521 m_assembler
.lwc1(dest
, addrTempRegister
, 0);
1522 m_assembler
.lwc1(FPRegisterID(dest
+ 1), addrTempRegister
, 4);
1525 li addrTemp, address
1526 ldc1 dest, 0(addrTemp)
1528 move(TrustedImmPtr(address
), addrTempRegister
);
1529 m_assembler
.ldc1(dest
, addrTempRegister
, 0);
1534 void storeDouble(FPRegisterID src
, ImplicitAddress address
)
1538 li addrTemp, address.offset
1539 addu addrTemp, addrTemp, base
1540 swc1 dest, 0(addrTemp)
1541 swc1 dest+1, 4(addrTemp)
1543 move(TrustedImm32(address
.offset
), addrTempRegister
);
1544 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1545 m_assembler
.swc1(src
, addrTempRegister
, 0);
1546 m_assembler
.swc1(FPRegisterID(src
+ 1), addrTempRegister
, 4);
1548 if (address
.offset
>= -32768 && address
.offset
<= 32767
1550 m_assembler
.sdc1(src
, address
.base
, address
.offset
);
1553 lui addrTemp, (offset + 0x8000) >> 16
1554 addu addrTemp, addrTemp, base
1555 sdc1 src, (offset & 0xffff)(addrTemp)
1557 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
1558 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1559 m_assembler
.sdc1(src
, addrTempRegister
, address
.offset
);
1564 void addDouble(FPRegisterID src
, FPRegisterID dest
)
1566 m_assembler
.addd(dest
, dest
, src
);
1569 void addDouble(Address src
, FPRegisterID dest
)
1571 loadDouble(src
, fpTempRegister
);
1572 m_assembler
.addd(dest
, dest
, fpTempRegister
);
1575 void subDouble(FPRegisterID src
, FPRegisterID dest
)
1577 m_assembler
.subd(dest
, dest
, src
);
1580 void subDouble(Address src
, FPRegisterID dest
)
1582 loadDouble(src
, fpTempRegister
);
1583 m_assembler
.subd(dest
, dest
, fpTempRegister
);
1586 void mulDouble(FPRegisterID src
, FPRegisterID dest
)
1588 m_assembler
.muld(dest
, dest
, src
);
1591 void mulDouble(Address src
, FPRegisterID dest
)
1593 loadDouble(src
, fpTempRegister
);
1594 m_assembler
.muld(dest
, dest
, fpTempRegister
);
1597 void divDouble(FPRegisterID src
, FPRegisterID dest
)
1599 m_assembler
.divd(dest
, dest
, src
);
1602 void convertInt32ToDouble(RegisterID src
, FPRegisterID dest
)
1604 m_assembler
.mtc1(src
, fpTempRegister
);
1605 m_assembler
.cvtdw(dest
, fpTempRegister
);
1608 void convertInt32ToDouble(Address src
, FPRegisterID dest
)
1610 load32(src
, dataTempRegister
);
1611 m_assembler
.mtc1(dataTempRegister
, fpTempRegister
);
1612 m_assembler
.cvtdw(dest
, fpTempRegister
);
1615 void convertInt32ToDouble(AbsoluteAddress src
, FPRegisterID dest
)
1617 load32(src
.m_ptr
, dataTempRegister
);
1618 m_assembler
.mtc1(dataTempRegister
, fpTempRegister
);
1619 m_assembler
.cvtdw(dest
, fpTempRegister
);
1622 void insertRelaxationWords()
1624 /* We need four words for relaxation. */
1625 m_assembler
.beq(MIPSRegisters::zero
, MIPSRegisters::zero
, 3); // Jump over nops;
1633 m_assembler
.appendJump();
1636 insertRelaxationWords();
1637 return Jump(m_assembler
.label());
1642 m_assembler
.appendJump();
1645 insertRelaxationWords();
1646 return Jump(m_assembler
.label());
1649 Jump
branchEqual(RegisterID rs
, RegisterID rt
)
1651 m_assembler
.appendJump();
1652 m_assembler
.beq(rs
, rt
, 0);
1654 insertRelaxationWords();
1655 return Jump(m_assembler
.label());
1658 Jump
branchNotEqual(RegisterID rs
, RegisterID rt
)
1660 m_assembler
.appendJump();
1661 m_assembler
.bne(rs
, rt
, 0);
1663 insertRelaxationWords();
1664 return Jump(m_assembler
.label());
1667 Jump
branchDouble(DoubleCondition cond
, FPRegisterID left
, FPRegisterID right
)
1669 if (cond
== DoubleEqual
) {
1670 m_assembler
.ceqd(left
, right
);
1671 return branchTrue();
1673 if (cond
== DoubleNotEqual
) {
1674 m_assembler
.cueqd(left
, right
);
1675 return branchFalse(); // false
1677 if (cond
== DoubleGreaterThan
) {
1678 m_assembler
.cngtd(left
, right
);
1679 return branchFalse(); // false
1681 if (cond
== DoubleGreaterThanOrEqual
) {
1682 m_assembler
.cnged(left
, right
);
1683 return branchFalse(); // false
1685 if (cond
== DoubleLessThan
) {
1686 m_assembler
.cltd(left
, right
);
1687 return branchTrue();
1689 if (cond
== DoubleLessThanOrEqual
) {
1690 m_assembler
.cled(left
, right
);
1691 return branchTrue();
1693 if (cond
== DoubleEqualOrUnordered
) {
1694 m_assembler
.cueqd(left
, right
);
1695 return branchTrue();
1697 if (cond
== DoubleNotEqualOrUnordered
) {
1698 m_assembler
.ceqd(left
, right
);
1699 return branchFalse(); // false
1701 if (cond
== DoubleGreaterThanOrUnordered
) {
1702 m_assembler
.coled(left
, right
);
1703 return branchFalse(); // false
1705 if (cond
== DoubleGreaterThanOrEqualOrUnordered
) {
1706 m_assembler
.coltd(left
, right
);
1707 return branchFalse(); // false
1709 if (cond
== DoubleLessThanOrUnordered
) {
1710 m_assembler
.cultd(left
, right
);
1711 return branchTrue();
1713 if (cond
== DoubleLessThanOrEqualOrUnordered
) {
1714 m_assembler
.culed(left
, right
);
1715 return branchTrue();
1722 // Truncates 'src' to an integer, and places the resulting 'dest'.
1723 // If the result is not representable as a 32 bit value, branch.
1724 // May also branch for some values that are representable in 32 bits
1725 // (specifically, in this case, INT_MAX 0x7fffffff).
1726 Jump
branchTruncateDoubleToInt32(FPRegisterID src
, RegisterID dest
)
1728 m_assembler
.truncwd(fpTempRegister
, src
);
1729 m_assembler
.mfc1(dest
, fpTempRegister
);
1730 return branch32(Equal
, dest
, TrustedImm32(0x7fffffff));
1733 // Convert 'src' to an integer, and places the resulting 'dest'.
1734 // If the result is not representable as a 32 bit value, branch.
1735 // May also branch for some values that are representable in 32 bits
1736 // (specifically, in this case, 0).
1737 void branchConvertDoubleToInt32(FPRegisterID src
, RegisterID dest
, JumpList
& failureCases
, FPRegisterID fpTemp
)
1739 m_assembler
.cvtwd(fpTempRegister
, src
);
1740 m_assembler
.mfc1(dest
, fpTempRegister
);
1742 // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
1743 failureCases
.append(branch32(Equal
, dest
, MIPSRegisters::zero
));
1745 // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
1746 convertInt32ToDouble(dest
, fpTemp
);
1747 failureCases
.append(branchDouble(DoubleNotEqualOrUnordered
, fpTemp
, src
));
1750 Jump
branchDoubleNonZero(FPRegisterID reg
, FPRegisterID scratch
)
1752 #if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
1753 m_assembler
.mtc1(MIPSRegisters::zero
, scratch
);
1754 m_assembler
.mthc1(MIPSRegisters::zero
, scratch
);
1756 m_assembler
.mtc1(MIPSRegisters::zero
, scratch
);
1757 m_assembler
.mtc1(MIPSRegisters::zero
, FPRegisterID(scratch
+ 1));
1759 return branchDouble(DoubleNotEqual
, reg
, scratch
);
1762 Jump
branchDoubleZeroOrNaN(FPRegisterID reg
, FPRegisterID scratch
)
1764 #if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
1765 m_assembler
.mtc1(MIPSRegisters::zero
, scratch
);
1766 m_assembler
.mthc1(MIPSRegisters::zero
, scratch
);
1768 m_assembler
.mtc1(MIPSRegisters::zero
, scratch
);
1769 m_assembler
.mtc1(MIPSRegisters::zero
, FPRegisterID(scratch
+ 1));
1771 return branchDouble(DoubleEqualOrUnordered
, reg
, scratch
);
1780 // If m_fixedWidth is true, we will generate a fixed number of instructions.
1781 // Otherwise, we can emit any number of instructions.
1784 friend class LinkBuffer
;
1785 friend class RepatchBuffer
;
1787 static void linkCall(void* code
, Call call
, FunctionPtr function
)
1789 MIPSAssembler::linkCall(code
, call
.m_jmp
, function
.value());
1792 static void repatchCall(CodeLocationCall call
, CodeLocationLabel destination
)
1794 MIPSAssembler::relinkCall(call
.dataLocation(), destination
.executableAddress());
1797 static void repatchCall(CodeLocationCall call
, FunctionPtr destination
)
1799 MIPSAssembler::relinkCall(call
.dataLocation(), destination
.executableAddress());
1806 #endif // ENABLE(ASSEMBLER) && CPU(MIPS)
1808 #endif // MacroAssemblerMIPS_h