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(RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
137 add32(imm
, src
, dest
);
140 void add32(TrustedImm32 imm
, Address address
)
142 if (address
.offset
>= -32768 && address
.offset
<= 32767
145 lw dataTemp, offset(base)
147 addu dataTemp, dataTemp, immTemp
148 sw dataTemp, offset(base)
150 m_assembler
.lw(dataTempRegister
, address
.base
, address
.offset
);
152 && imm
.m_value
>= -32768 && imm
.m_value
<= 32767
154 m_assembler
.addiu(dataTempRegister
, dataTempRegister
,
157 move(imm
, immTempRegister
);
158 m_assembler
.addu(dataTempRegister
, dataTempRegister
,
161 m_assembler
.sw(dataTempRegister
, address
.base
, address
.offset
);
164 lui addrTemp, (offset + 0x8000) >> 16
165 addu addrTemp, addrTemp, base
166 lw dataTemp, (offset & 0xffff)(addrTemp)
168 addu dataTemp, dataTemp, immTemp
169 sw dataTemp, (offset & 0xffff)(addrTemp)
171 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
172 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
173 m_assembler
.lw(dataTempRegister
, addrTempRegister
, address
.offset
);
175 if (imm
.m_value
>= -32768 && imm
.m_value
<= 32767 && !m_fixedWidth
)
176 m_assembler
.addiu(dataTempRegister
, dataTempRegister
,
179 move(imm
, immTempRegister
);
180 m_assembler
.addu(dataTempRegister
, dataTempRegister
,
183 m_assembler
.sw(dataTempRegister
, addrTempRegister
, address
.offset
);
187 void add32(Address src
, RegisterID dest
)
189 load32(src
, dataTempRegister
);
190 add32(dataTempRegister
, dest
);
193 void add32(RegisterID src
, Address dest
)
195 if (dest
.offset
>= -32768 && dest
.offset
<= 32767 && !m_fixedWidth
) {
197 lw dataTemp, offset(base)
198 addu dataTemp, dataTemp, src
199 sw dataTemp, offset(base)
201 m_assembler
.lw(dataTempRegister
, dest
.base
, dest
.offset
);
202 m_assembler
.addu(dataTempRegister
, dataTempRegister
, src
);
203 m_assembler
.sw(dataTempRegister
, dest
.base
, dest
.offset
);
206 lui addrTemp, (offset + 0x8000) >> 16
207 addu addrTemp, addrTemp, base
208 lw dataTemp, (offset & 0xffff)(addrTemp)
209 addu dataTemp, dataTemp, src
210 sw dataTemp, (offset & 0xffff)(addrTemp)
212 m_assembler
.lui(addrTempRegister
, (dest
.offset
+ 0x8000) >> 16);
213 m_assembler
.addu(addrTempRegister
, addrTempRegister
, dest
.base
);
214 m_assembler
.lw(dataTempRegister
, addrTempRegister
, dest
.offset
);
215 m_assembler
.addu(dataTempRegister
, dataTempRegister
, src
);
216 m_assembler
.sw(dataTempRegister
, addrTempRegister
, dest
.offset
);
220 void add32(TrustedImm32 imm
, AbsoluteAddress address
)
225 lw dataTemp, 0(addrTemp)
226 addu dataTemp, dataTemp, immTemp
227 sw dataTemp, 0(addrTemp)
229 move(TrustedImmPtr(address
.m_ptr
), addrTempRegister
);
230 m_assembler
.lw(dataTempRegister
, addrTempRegister
, 0);
231 if (!imm
.m_isPointer
&& imm
.m_value
>= -32768 && imm
.m_value
<= 32767
233 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, imm
.m_value
);
235 move(imm
, immTempRegister
);
236 m_assembler
.addu(dataTempRegister
, dataTempRegister
, immTempRegister
);
238 m_assembler
.sw(dataTempRegister
, addrTempRegister
, 0);
241 void and32(RegisterID src
, RegisterID dest
)
243 m_assembler
.andInsn(dest
, dest
, src
);
246 void and32(TrustedImm32 imm
, RegisterID dest
)
248 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
)
249 move(MIPSRegisters::zero
, dest
);
250 else if (!imm
.m_isPointer
&& imm
.m_value
> 0 && imm
.m_value
< 65535
252 m_assembler
.andi(dest
, dest
, imm
.m_value
);
256 and dest, dest, immTemp
258 move(imm
, immTempRegister
);
259 m_assembler
.andInsn(dest
, dest
, immTempRegister
);
263 void lshift32(TrustedImm32 imm
, RegisterID dest
)
265 m_assembler
.sll(dest
, dest
, imm
.m_value
);
268 void lshift32(RegisterID shiftAmount
, RegisterID dest
)
270 m_assembler
.sllv(dest
, dest
, shiftAmount
);
273 void mul32(RegisterID src
, RegisterID dest
)
275 m_assembler
.mul(dest
, dest
, src
);
278 void mul32(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
280 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
)
281 move(MIPSRegisters::zero
, dest
);
282 else if (!imm
.m_isPointer
&& imm
.m_value
== 1 && !m_fixedWidth
)
287 mul dest, src, dataTemp
289 move(imm
, dataTempRegister
);
290 m_assembler
.mul(dest
, src
, dataTempRegister
);
294 void neg32(RegisterID srcDest
)
296 m_assembler
.subu(srcDest
, MIPSRegisters::zero
, srcDest
);
299 void or32(RegisterID src
, RegisterID dest
)
301 m_assembler
.orInsn(dest
, dest
, src
);
304 void or32(RegisterID op1
, RegisterID op2
, RegisterID dest
)
306 m_assembler
.orInsn(dest
, op1
, op2
);
309 void or32(TrustedImm32 imm
, RegisterID dest
)
311 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
)
314 if (!imm
.m_isPointer
&& imm
.m_value
> 0 && imm
.m_value
< 65535
316 m_assembler
.ori(dest
, dest
, imm
.m_value
);
322 or dest, dest, dataTemp
324 move(imm
, dataTempRegister
);
325 m_assembler
.orInsn(dest
, dest
, dataTempRegister
);
328 void rshift32(RegisterID shiftAmount
, RegisterID dest
)
330 m_assembler
.srav(dest
, dest
, shiftAmount
);
333 void rshift32(TrustedImm32 imm
, RegisterID dest
)
335 m_assembler
.sra(dest
, dest
, imm
.m_value
);
338 void rshift32(RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
340 m_assembler
.sra(dest
, src
, imm
.m_value
);
343 void urshift32(RegisterID shiftAmount
, RegisterID dest
)
345 m_assembler
.srlv(dest
, dest
, shiftAmount
);
348 void urshift32(TrustedImm32 imm
, RegisterID dest
)
350 m_assembler
.srl(dest
, dest
, imm
.m_value
);
353 void sub32(RegisterID src
, RegisterID dest
)
355 m_assembler
.subu(dest
, dest
, src
);
358 void sub32(TrustedImm32 imm
, RegisterID dest
)
360 if (!imm
.m_isPointer
&& imm
.m_value
>= -32767 && imm
.m_value
<= 32768
365 m_assembler
.addiu(dest
, dest
, -imm
.m_value
);
369 subu dest, src, immTemp
371 move(imm
, immTempRegister
);
372 m_assembler
.subu(dest
, dest
, immTempRegister
);
376 void sub32(RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
378 if (!imm
.m_isPointer
&& imm
.m_value
>= -32767 && imm
.m_value
<= 32768
383 m_assembler
.addiu(dest
, src
, -imm
.m_value
);
387 subu dest, src, immTemp
389 move(imm
, immTempRegister
);
390 m_assembler
.subu(dest
, src
, immTempRegister
);
394 void sub32(TrustedImm32 imm
, Address address
)
396 if (address
.offset
>= -32768 && address
.offset
<= 32767
399 lw dataTemp, offset(base)
401 subu dataTemp, dataTemp, immTemp
402 sw dataTemp, offset(base)
404 m_assembler
.lw(dataTempRegister
, address
.base
, address
.offset
);
406 && imm
.m_value
>= -32767 && imm
.m_value
<= 32768
408 m_assembler
.addiu(dataTempRegister
, dataTempRegister
,
411 move(imm
, immTempRegister
);
412 m_assembler
.subu(dataTempRegister
, dataTempRegister
,
415 m_assembler
.sw(dataTempRegister
, address
.base
, address
.offset
);
418 lui addrTemp, (offset + 0x8000) >> 16
419 addu addrTemp, addrTemp, base
420 lw dataTemp, (offset & 0xffff)(addrTemp)
422 subu dataTemp, dataTemp, immTemp
423 sw dataTemp, (offset & 0xffff)(addrTemp)
425 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
426 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
427 m_assembler
.lw(dataTempRegister
, addrTempRegister
, address
.offset
);
430 && imm
.m_value
>= -32767 && imm
.m_value
<= 32768
432 m_assembler
.addiu(dataTempRegister
, dataTempRegister
,
435 move(imm
, immTempRegister
);
436 m_assembler
.subu(dataTempRegister
, dataTempRegister
,
439 m_assembler
.sw(dataTempRegister
, addrTempRegister
, address
.offset
);
443 void sub32(Address src
, RegisterID dest
)
445 load32(src
, dataTempRegister
);
446 sub32(dataTempRegister
, dest
);
449 void sub32(TrustedImm32 imm
, AbsoluteAddress address
)
454 lw dataTemp, 0(addrTemp)
455 subu dataTemp, dataTemp, immTemp
456 sw dataTemp, 0(addrTemp)
458 move(TrustedImmPtr(address
.m_ptr
), addrTempRegister
);
459 m_assembler
.lw(dataTempRegister
, addrTempRegister
, 0);
461 if (!imm
.m_isPointer
&& imm
.m_value
>= -32767 && imm
.m_value
<= 32768
463 m_assembler
.addiu(dataTempRegister
, dataTempRegister
,
466 move(imm
, immTempRegister
);
467 m_assembler
.subu(dataTempRegister
, dataTempRegister
, immTempRegister
);
469 m_assembler
.sw(dataTempRegister
, addrTempRegister
, 0);
472 void xor32(RegisterID src
, RegisterID dest
)
474 m_assembler
.xorInsn(dest
, dest
, src
);
477 void xor32(TrustedImm32 imm
, RegisterID dest
)
479 if (imm
.m_value
== -1) {
480 m_assembler
.nor(dest
, dest
, MIPSRegisters::zero
);
486 xor dest, dest, immTemp
488 move(imm
, immTempRegister
);
489 m_assembler
.xorInsn(dest
, dest
, immTempRegister
);
492 void sqrtDouble(FPRegisterID src
, FPRegisterID dst
)
494 m_assembler
.sqrtd(dst
, src
);
497 void absDouble(FPRegisterID
, FPRegisterID
)
499 ASSERT_NOT_REACHED();
502 // Memory access operations:
504 // Loads are of the form load(address, destination) and stores of the form
505 // store(source, address). The source for a store may be an TrustedImm32. Address
506 // operand objects to loads and store will be implicitly constructed if a
507 // register is passed.
509 /* Need to use zero-extened load byte for load8. */
510 void load8(ImplicitAddress address
, RegisterID dest
)
512 if (address
.offset
>= -32768 && address
.offset
<= 32767
514 m_assembler
.lbu(dest
, address
.base
, address
.offset
);
517 lui addrTemp, (offset + 0x8000) >> 16
518 addu addrTemp, addrTemp, base
519 lbu dest, (offset & 0xffff)(addrTemp)
521 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
522 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
523 m_assembler
.lbu(dest
, addrTempRegister
, address
.offset
);
527 void load8(BaseIndex address
, RegisterID dest
)
529 if (address
.offset
>= -32768 && address
.offset
<= 32767
532 sll addrTemp, address.index, address.scale
533 addu addrTemp, addrTemp, address.base
534 lbu dest, address.offset(addrTemp)
536 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
537 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
538 m_assembler
.lbu(dest
, addrTempRegister
, address
.offset
);
541 sll addrTemp, address.index, address.scale
542 addu addrTemp, addrTemp, address.base
543 lui immTemp, (address.offset + 0x8000) >> 16
544 addu addrTemp, addrTemp, immTemp
545 lbu dest, (address.offset & 0xffff)(at)
547 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
548 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
549 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
550 m_assembler
.addu(addrTempRegister
, addrTempRegister
,
552 m_assembler
.lbu(dest
, addrTempRegister
, address
.offset
);
556 void load32(ImplicitAddress address
, RegisterID dest
)
558 if (address
.offset
>= -32768 && address
.offset
<= 32767
560 m_assembler
.lw(dest
, address
.base
, address
.offset
);
563 lui addrTemp, (offset + 0x8000) >> 16
564 addu addrTemp, addrTemp, base
565 lw dest, (offset & 0xffff)(addrTemp)
567 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
568 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
569 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
573 void load32(BaseIndex address
, RegisterID dest
)
575 if (address
.offset
>= -32768 && address
.offset
<= 32767
578 sll addrTemp, address.index, address.scale
579 addu addrTemp, addrTemp, address.base
580 lw dest, address.offset(addrTemp)
582 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
583 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
584 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
587 sll addrTemp, address.index, address.scale
588 addu addrTemp, addrTemp, address.base
589 lui immTemp, (address.offset + 0x8000) >> 16
590 addu addrTemp, addrTemp, immTemp
591 lw dest, (address.offset & 0xffff)(at)
593 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
594 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
595 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
596 m_assembler
.addu(addrTempRegister
, addrTempRegister
,
598 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
602 void load16Unaligned(BaseIndex address
, RegisterID dest
)
604 load16(address
, dest
);
607 void load32WithUnalignedHalfWords(BaseIndex address
, RegisterID dest
)
609 if (address
.offset
>= -32768 && address
.offset
<= 32764
612 sll addrTemp, address.index, address.scale
613 addu addrTemp, addrTemp, address.base
615 lwl dest, address.offset(addrTemp)
616 lwr dest, address.offset+3(addrTemp)
618 lwl dest, address.offset+3(addrTemp)
619 lwr dest, address.offset(addrTemp)
621 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
622 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
624 m_assembler
.lwl(dest
, addrTempRegister
, address
.offset
);
625 m_assembler
.lwr(dest
, addrTempRegister
, address
.offset
+ 3);
627 m_assembler
.lwl(dest
, addrTempRegister
, address
.offset
+ 3);
628 m_assembler
.lwr(dest
, addrTempRegister
, address
.offset
);
633 sll addrTemp, address.index, address.scale
634 addu addrTemp, addrTemp, address.base
635 lui immTemp, address.offset >> 16
636 ori immTemp, immTemp, address.offset & 0xffff
637 addu addrTemp, addrTemp, immTemp
645 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
646 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
647 m_assembler
.lui(immTempRegister
, address
.offset
>> 16);
648 m_assembler
.ori(immTempRegister
, immTempRegister
, address
.offset
);
649 m_assembler
.addu(addrTempRegister
, addrTempRegister
,
652 m_assembler
.lwl(dest
, addrTempRegister
, 0);
653 m_assembler
.lwr(dest
, addrTempRegister
, 3);
655 m_assembler
.lwl(dest
, addrTempRegister
, 3);
656 m_assembler
.lwr(dest
, addrTempRegister
, 0);
661 void load32(const void* address
, RegisterID dest
)
667 move(TrustedImmPtr(address
), addrTempRegister
);
668 m_assembler
.lw(dest
, addrTempRegister
, 0);
671 DataLabel32
load32WithAddressOffsetPatch(Address address
, RegisterID dest
)
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
.lw(dest
, addrTempRegister
, 0);
684 m_fixedWidth
= false;
688 DataLabelCompact
load32WithCompactAddressOffsetPatch(Address address
, RegisterID dest
)
690 DataLabelCompact
dataLabel(this);
691 load32WithAddressOffsetPatch(address
, dest
);
695 /* Need to use zero-extened load half-word for load16. */
696 void load16(ImplicitAddress address
, RegisterID dest
)
698 if (address
.offset
>= -32768 && address
.offset
<= 32767
700 m_assembler
.lhu(dest
, address
.base
, address
.offset
);
703 lui addrTemp, (offset + 0x8000) >> 16
704 addu addrTemp, addrTemp, base
705 lhu dest, (offset & 0xffff)(addrTemp)
707 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
708 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
709 m_assembler
.lhu(dest
, addrTempRegister
, address
.offset
);
713 /* Need to use zero-extened load half-word for load16. */
714 void load16(BaseIndex address
, RegisterID dest
)
716 if (address
.offset
>= -32768 && address
.offset
<= 32767
719 sll addrTemp, address.index, address.scale
720 addu addrTemp, addrTemp, address.base
721 lhu dest, address.offset(addrTemp)
723 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
724 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
725 m_assembler
.lhu(dest
, addrTempRegister
, address
.offset
);
728 sll addrTemp, address.index, address.scale
729 addu addrTemp, addrTemp, address.base
730 lui immTemp, (address.offset + 0x8000) >> 16
731 addu addrTemp, addrTemp, immTemp
732 lhu dest, (address.offset & 0xffff)(addrTemp)
734 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
735 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
736 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
737 m_assembler
.addu(addrTempRegister
, addrTempRegister
,
739 m_assembler
.lhu(dest
, addrTempRegister
, address
.offset
);
743 DataLabel32
store32WithAddressOffsetPatch(RegisterID src
, Address address
)
747 lui addrTemp, address.offset >> 16
748 ori addrTemp, addrTemp, address.offset & 0xffff
749 addu addrTemp, addrTemp, address.base
752 DataLabel32
dataLabel(this);
753 move(TrustedImm32(address
.offset
), addrTempRegister
);
754 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
755 m_assembler
.sw(src
, addrTempRegister
, 0);
756 m_fixedWidth
= false;
760 void store32(RegisterID src
, ImplicitAddress address
)
762 if (address
.offset
>= -32768 && address
.offset
<= 32767
764 m_assembler
.sw(src
, address
.base
, address
.offset
);
767 lui addrTemp, (offset + 0x8000) >> 16
768 addu addrTemp, addrTemp, base
769 sw src, (offset & 0xffff)(addrTemp)
771 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
772 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
773 m_assembler
.sw(src
, addrTempRegister
, address
.offset
);
777 void store32(RegisterID src
, BaseIndex address
)
779 if (address
.offset
>= -32768 && address
.offset
<= 32767
782 sll addrTemp, address.index, address.scale
783 addu addrTemp, addrTemp, address.base
784 sw src, address.offset(addrTemp)
786 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
787 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
788 m_assembler
.sw(src
, addrTempRegister
, address
.offset
);
791 sll addrTemp, address.index, address.scale
792 addu addrTemp, addrTemp, address.base
793 lui immTemp, (address.offset + 0x8000) >> 16
794 addu addrTemp, addrTemp, immTemp
795 sw src, (address.offset & 0xffff)(at)
797 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
798 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
799 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
800 m_assembler
.addu(addrTempRegister
, addrTempRegister
,
802 m_assembler
.sw(src
, addrTempRegister
, address
.offset
);
806 void store32(TrustedImm32 imm
, ImplicitAddress address
)
808 if (address
.offset
>= -32768 && address
.offset
<= 32767
810 if (!imm
.m_isPointer
&& !imm
.m_value
)
811 m_assembler
.sw(MIPSRegisters::zero
, address
.base
,
814 move(imm
, immTempRegister
);
815 m_assembler
.sw(immTempRegister
, address
.base
, address
.offset
);
819 lui addrTemp, (offset + 0x8000) >> 16
820 addu addrTemp, addrTemp, base
821 sw immTemp, (offset & 0xffff)(addrTemp)
823 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
824 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
825 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
)
826 m_assembler
.sw(MIPSRegisters::zero
, addrTempRegister
,
829 move(imm
, immTempRegister
);
830 m_assembler
.sw(immTempRegister
, addrTempRegister
,
836 void store32(RegisterID src
, const void* address
)
842 move(TrustedImmPtr(address
), addrTempRegister
);
843 m_assembler
.sw(src
, addrTempRegister
, 0);
846 void store32(TrustedImm32 imm
, const void* address
)
853 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
) {
854 move(TrustedImmPtr(address
), addrTempRegister
);
855 m_assembler
.sw(MIPSRegisters::zero
, addrTempRegister
, 0);
857 move(imm
, immTempRegister
);
858 move(TrustedImmPtr(address
), addrTempRegister
);
859 m_assembler
.sw(immTempRegister
, addrTempRegister
, 0);
863 // Floating-point operations:
865 static bool supportsFloatingPoint()
867 #if WTF_MIPS_DOUBLE_FLOAT
874 static bool supportsFloatingPointTruncate()
876 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
883 static bool supportsFloatingPointSqrt()
885 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
891 static bool supportsFloatingPointAbs() { return false; }
893 // Stack manipulation operations:
895 // The ABI is assumed to provide a stack abstraction to memory,
896 // containing machine word sized units of data. Push and pop
897 // operations add and remove a single register sized unit of data
898 // to or from the stack. Peek and poke operations read or write
899 // values on the stack, without moving the current stack position.
901 void pop(RegisterID dest
)
903 m_assembler
.lw(dest
, MIPSRegisters::sp
, 0);
904 m_assembler
.addiu(MIPSRegisters::sp
, MIPSRegisters::sp
, 4);
907 void push(RegisterID src
)
909 m_assembler
.addiu(MIPSRegisters::sp
, MIPSRegisters::sp
, -4);
910 m_assembler
.sw(src
, MIPSRegisters::sp
, 0);
913 void push(Address address
)
915 load32(address
, dataTempRegister
);
916 push(dataTempRegister
);
919 void push(TrustedImm32 imm
)
921 move(imm
, immTempRegister
);
922 push(immTempRegister
);
925 // Register move operations:
927 // Move values in registers.
929 void move(TrustedImm32 imm
, RegisterID dest
)
931 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
)
932 move(MIPSRegisters::zero
, dest
);
933 else if (imm
.m_isPointer
|| m_fixedWidth
) {
934 m_assembler
.lui(dest
, imm
.m_value
>> 16);
935 m_assembler
.ori(dest
, dest
, imm
.m_value
);
937 m_assembler
.li(dest
, imm
.m_value
);
940 void move(RegisterID src
, RegisterID dest
)
942 if (src
!= dest
|| m_fixedWidth
)
943 m_assembler
.move(dest
, src
);
946 void move(TrustedImmPtr imm
, RegisterID dest
)
948 move(TrustedImm32(imm
), dest
);
951 void swap(RegisterID reg1
, RegisterID reg2
)
953 move(reg1
, immTempRegister
);
955 move(immTempRegister
, reg2
);
958 void signExtend32ToPtr(RegisterID src
, RegisterID dest
)
960 if (src
!= dest
|| m_fixedWidth
)
964 void zeroExtend32ToPtr(RegisterID src
, RegisterID dest
)
966 if (src
!= dest
|| m_fixedWidth
)
970 // Forwards / external control flow operations:
972 // This set of jump and conditional branch operations return a Jump
973 // object which may linked at a later point, allow forwards jump,
974 // or jumps that will require external linkage (after the code has been
977 // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
978 // respecitvely, for unsigned comparisons the names b, a, be, and ae are
979 // used (representing the names 'below' and 'above').
981 // Operands to the comparision are provided in the expected order, e.g.
982 // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when
983 // treated as a signed 32bit value, is less than or equal to 5.
985 // jz and jnz test whether the first operand is equal to zero, and take
986 // an optional second operand of a mask under which to perform the test.
988 Jump
branch8(RelationalCondition cond
, Address left
, TrustedImm32 right
)
990 // Make sure the immediate value is unsigned 8 bits.
991 ASSERT(!(right
.m_value
& 0xFFFFFF00));
992 load8(left
, dataTempRegister
);
993 move(right
, immTempRegister
);
994 return branch32(cond
, dataTempRegister
, immTempRegister
);
997 void compare8(RelationalCondition cond
, Address left
, TrustedImm32 right
, RegisterID dest
)
999 // Make sure the immediate value is unsigned 8 bits.
1000 ASSERT(!(right
.m_value
& 0xFFFFFF00));
1001 load8(left
, dataTempRegister
);
1002 move(right
, immTempRegister
);
1003 compare32(cond
, dataTempRegister
, immTempRegister
, dest
);
1006 Jump
branch8(RelationalCondition cond
, BaseIndex left
, TrustedImm32 right
)
1008 ASSERT(!(right
.m_value
& 0xFFFFFF00));
1009 load8(left
, dataTempRegister
);
1010 // Be careful that the previous load8() uses immTempRegister.
1011 // So, we need to put move() after load8().
1012 move(right
, immTempRegister
);
1013 return branch32(cond
, dataTempRegister
, immTempRegister
);
1016 Jump
branch32(RelationalCondition cond
, RegisterID left
, RegisterID right
)
1019 return branchEqual(left
, right
);
1020 if (cond
== NotEqual
)
1021 return branchNotEqual(left
, right
);
1022 if (cond
== Above
) {
1023 m_assembler
.sltu(cmpTempRegister
, right
, left
);
1024 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1026 if (cond
== AboveOrEqual
) {
1027 m_assembler
.sltu(cmpTempRegister
, left
, right
);
1028 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1030 if (cond
== Below
) {
1031 m_assembler
.sltu(cmpTempRegister
, left
, right
);
1032 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1034 if (cond
== BelowOrEqual
) {
1035 m_assembler
.sltu(cmpTempRegister
, right
, left
);
1036 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1038 if (cond
== GreaterThan
) {
1039 m_assembler
.slt(cmpTempRegister
, right
, left
);
1040 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1042 if (cond
== GreaterThanOrEqual
) {
1043 m_assembler
.slt(cmpTempRegister
, left
, right
);
1044 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1046 if (cond
== LessThan
) {
1047 m_assembler
.slt(cmpTempRegister
, left
, right
);
1048 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1050 if (cond
== LessThanOrEqual
) {
1051 m_assembler
.slt(cmpTempRegister
, right
, left
);
1052 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1059 Jump
branch32(RelationalCondition cond
, RegisterID left
, TrustedImm32 right
)
1061 move(right
, immTempRegister
);
1062 return branch32(cond
, left
, immTempRegister
);
1065 Jump
branch32(RelationalCondition cond
, RegisterID left
, Address right
)
1067 load32(right
, dataTempRegister
);
1068 return branch32(cond
, left
, dataTempRegister
);
1071 Jump
branch32(RelationalCondition cond
, Address left
, RegisterID right
)
1073 load32(left
, dataTempRegister
);
1074 return branch32(cond
, dataTempRegister
, right
);
1077 Jump
branch32(RelationalCondition cond
, Address left
, TrustedImm32 right
)
1079 load32(left
, dataTempRegister
);
1080 move(right
, immTempRegister
);
1081 return branch32(cond
, dataTempRegister
, immTempRegister
);
1084 Jump
branch32(RelationalCondition cond
, BaseIndex left
, TrustedImm32 right
)
1086 load32(left
, dataTempRegister
);
1087 // Be careful that the previous load32() uses immTempRegister.
1088 // So, we need to put move() after load32().
1089 move(right
, immTempRegister
);
1090 return branch32(cond
, dataTempRegister
, immTempRegister
);
1093 Jump
branch32WithUnalignedHalfWords(RelationalCondition cond
, BaseIndex left
, TrustedImm32 right
)
1095 load32WithUnalignedHalfWords(left
, dataTempRegister
);
1096 // Be careful that the previous load32WithUnalignedHalfWords()
1097 // uses immTempRegister.
1098 // So, we need to put move() after load32WithUnalignedHalfWords().
1099 move(right
, immTempRegister
);
1100 return branch32(cond
, dataTempRegister
, immTempRegister
);
1103 Jump
branch32(RelationalCondition cond
, AbsoluteAddress left
, RegisterID right
)
1105 load32(left
.m_ptr
, dataTempRegister
);
1106 return branch32(cond
, dataTempRegister
, right
);
1109 Jump
branch32(RelationalCondition cond
, AbsoluteAddress left
, TrustedImm32 right
)
1111 load32(left
.m_ptr
, dataTempRegister
);
1112 move(right
, immTempRegister
);
1113 return branch32(cond
, dataTempRegister
, immTempRegister
);
1116 Jump
branchTest32(ResultCondition cond
, RegisterID reg
, RegisterID mask
)
1118 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1119 m_assembler
.andInsn(cmpTempRegister
, reg
, mask
);
1121 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1122 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1125 Jump
branchTest32(ResultCondition cond
, RegisterID reg
, TrustedImm32 mask
= TrustedImm32(-1))
1127 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1128 if (mask
.m_value
== -1 && !m_fixedWidth
) {
1130 return branchEqual(reg
, MIPSRegisters::zero
);
1131 return branchNotEqual(reg
, MIPSRegisters::zero
);
1133 move(mask
, immTempRegister
);
1134 return branchTest32(cond
, reg
, immTempRegister
);
1137 Jump
branchTest32(ResultCondition cond
, Address address
, TrustedImm32 mask
= TrustedImm32(-1))
1139 load32(address
, dataTempRegister
);
1140 return branchTest32(cond
, dataTempRegister
, mask
);
1143 Jump
branchTest32(ResultCondition cond
, BaseIndex address
, TrustedImm32 mask
= TrustedImm32(-1))
1145 load32(address
, dataTempRegister
);
1146 return branchTest32(cond
, dataTempRegister
, mask
);
1149 Jump
branchTest8(ResultCondition cond
, Address address
, TrustedImm32 mask
= TrustedImm32(-1))
1151 load8(address
, dataTempRegister
);
1152 return branchTest32(cond
, dataTempRegister
, mask
);
1157 return branchEqual(MIPSRegisters::zero
, MIPSRegisters::zero
);
1160 void jump(RegisterID target
)
1162 m_assembler
.jr(target
);
1166 void jump(Address address
)
1168 m_fixedWidth
= true;
1169 load32(address
, MIPSRegisters::t9
);
1170 m_assembler
.jr(MIPSRegisters::t9
);
1172 m_fixedWidth
= false;
1175 // Arithmetic control flow operations:
1177 // This set of conditional branch operations branch based
1178 // on the result of an arithmetic operation. The operation
1179 // is performed as normal, storing the result.
1181 // * jz operations branch if the result is zero.
1182 // * jo operations branch if the (signed) arithmetic
1183 // operation caused an overflow to occur.
1185 Jump
branchAdd32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1187 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1188 if (cond
== Overflow
) {
1191 xor cmpTemp, dataTemp, src
1192 bltz cmpTemp, No_overflow # diff sign bit -> no overflow
1193 addu dest, dataTemp, src
1194 xor cmpTemp, dest, dataTemp
1195 bgez cmpTemp, No_overflow # same sign big -> no overflow
1205 move(dest
, dataTempRegister
);
1206 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, src
);
1207 m_assembler
.bltz(cmpTempRegister
, 10);
1208 m_assembler
.addu(dest
, dataTempRegister
, src
);
1209 m_assembler
.xorInsn(cmpTempRegister
, dest
, dataTempRegister
);
1210 m_assembler
.bgez(cmpTempRegister
, 7);
1214 if (cond
== Signed
) {
1216 // Check if dest is negative.
1217 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1218 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1222 return branchEqual(dest
, MIPSRegisters::zero
);
1224 if (cond
== NonZero
) {
1226 return branchNotEqual(dest
, MIPSRegisters::zero
);
1232 Jump
branchAdd32(ResultCondition cond
, TrustedImm32 imm
, RegisterID dest
)
1234 move(imm
, immTempRegister
);
1235 return branchAdd32(cond
, immTempRegister
, dest
);
1238 Jump
branchAdd32(ResultCondition cond
, RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
1240 move(imm
, immTempRegister
);
1242 return branchAdd32(cond
, immTempRegister
, dest
);
1245 Jump
branchMul32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1247 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1248 if (cond
== Overflow
) {
1253 sra addrTemp, dest, 31
1254 beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow
1264 m_assembler
.mult(src
, dest
);
1265 m_assembler
.mfhi(dataTempRegister
);
1266 m_assembler
.mflo(dest
);
1267 m_assembler
.sra(addrTempRegister
, dest
, 31);
1268 m_assembler
.beq(dataTempRegister
, addrTempRegister
, 7);
1272 if (cond
== Signed
) {
1274 // Check if dest is negative.
1275 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1276 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1280 return branchEqual(dest
, MIPSRegisters::zero
);
1282 if (cond
== NonZero
) {
1284 return branchNotEqual(dest
, MIPSRegisters::zero
);
1290 Jump
branchMul32(ResultCondition cond
, TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
1292 move(imm
, immTempRegister
);
1294 return branchMul32(cond
, immTempRegister
, dest
);
1297 Jump
branchSub32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1299 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1300 if (cond
== Overflow
) {
1303 xor cmpTemp, dataTemp, src
1304 bgez cmpTemp, No_overflow # same sign bit -> no overflow
1305 subu dest, dataTemp, src
1306 xor cmpTemp, dest, dataTemp
1307 bgez cmpTemp, No_overflow # same sign bit -> no overflow
1317 move(dest
, dataTempRegister
);
1318 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, src
);
1319 m_assembler
.bgez(cmpTempRegister
, 10);
1320 m_assembler
.subu(dest
, dataTempRegister
, src
);
1321 m_assembler
.xorInsn(cmpTempRegister
, dest
, dataTempRegister
);
1322 m_assembler
.bgez(cmpTempRegister
, 7);
1326 if (cond
== Signed
) {
1328 // Check if dest is negative.
1329 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1330 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1334 return branchEqual(dest
, MIPSRegisters::zero
);
1336 if (cond
== NonZero
) {
1338 return branchNotEqual(dest
, MIPSRegisters::zero
);
1344 Jump
branchSub32(ResultCondition cond
, TrustedImm32 imm
, RegisterID dest
)
1346 move(imm
, immTempRegister
);
1347 return branchSub32(cond
, immTempRegister
, dest
);
1350 Jump
branchSub32(ResultCondition cond
, RegisterID src
, TrustedImm32 imm
, RegisterID dest
)
1352 move(imm
, immTempRegister
);
1354 return branchSub32(cond
, immTempRegister
, dest
);
1357 Jump
branchOr32(ResultCondition cond
, RegisterID src
, RegisterID dest
)
1359 ASSERT((cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1360 if (cond
== Signed
) {
1362 // Check if dest is negative.
1363 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1364 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1368 return branchEqual(dest
, MIPSRegisters::zero
);
1370 if (cond
== NonZero
) {
1372 return branchNotEqual(dest
, MIPSRegisters::zero
);
1378 // Miscellaneous operations:
1387 /* We need two words for relaxation. */
1392 return Call(m_assembler
.label(), Call::LinkableNear
);
1397 m_assembler
.lui(MIPSRegisters::t9
, 0);
1398 m_assembler
.ori(MIPSRegisters::t9
, MIPSRegisters::t9
, 0);
1399 m_assembler
.jalr(MIPSRegisters::t9
);
1401 return Call(m_assembler
.label(), Call::Linkable
);
1404 Call
call(RegisterID target
)
1406 m_assembler
.jalr(target
);
1408 return Call(m_assembler
.label(), Call::None
);
1411 Call
call(Address address
)
1413 m_fixedWidth
= true;
1414 load32(address
, MIPSRegisters::t9
);
1415 m_assembler
.jalr(MIPSRegisters::t9
);
1417 m_fixedWidth
= false;
1418 return Call(m_assembler
.label(), Call::None
);
1423 m_assembler
.jr(MIPSRegisters::ra
);
1427 void compare32(RelationalCondition cond
, RegisterID left
, RegisterID right
, RegisterID dest
)
1429 if (cond
== Equal
) {
1430 m_assembler
.xorInsn(dest
, left
, right
);
1431 m_assembler
.sltiu(dest
, dest
, 1);
1432 } else if (cond
== NotEqual
) {
1433 m_assembler
.xorInsn(dest
, left
, right
);
1434 m_assembler
.sltu(dest
, MIPSRegisters::zero
, dest
);
1435 } else if (cond
== Above
)
1436 m_assembler
.sltu(dest
, right
, left
);
1437 else if (cond
== AboveOrEqual
) {
1438 m_assembler
.sltu(dest
, left
, right
);
1439 m_assembler
.xori(dest
, dest
, 1);
1440 } else if (cond
== Below
)
1441 m_assembler
.sltu(dest
, left
, right
);
1442 else if (cond
== BelowOrEqual
) {
1443 m_assembler
.sltu(dest
, right
, left
);
1444 m_assembler
.xori(dest
, dest
, 1);
1445 } else if (cond
== GreaterThan
)
1446 m_assembler
.slt(dest
, right
, left
);
1447 else if (cond
== GreaterThanOrEqual
) {
1448 m_assembler
.slt(dest
, left
, right
);
1449 m_assembler
.xori(dest
, dest
, 1);
1450 } else if (cond
== LessThan
)
1451 m_assembler
.slt(dest
, left
, right
);
1452 else if (cond
== LessThanOrEqual
) {
1453 m_assembler
.slt(dest
, right
, left
);
1454 m_assembler
.xori(dest
, dest
, 1);
1458 void compare32(RelationalCondition cond
, RegisterID left
, TrustedImm32 right
, RegisterID dest
)
1460 move(right
, immTempRegister
);
1461 compare32(cond
, left
, immTempRegister
, dest
);
1464 void test8(ResultCondition cond
, Address address
, TrustedImm32 mask
, RegisterID dest
)
1466 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1467 load8(address
, dataTempRegister
);
1468 if (mask
.m_value
== -1 && !m_fixedWidth
) {
1470 m_assembler
.sltiu(dest
, dataTempRegister
, 1);
1472 m_assembler
.sltu(dest
, MIPSRegisters::zero
, dataTempRegister
);
1474 move(mask
, immTempRegister
);
1475 m_assembler
.andInsn(cmpTempRegister
, dataTempRegister
,
1478 m_assembler
.sltiu(dest
, cmpTempRegister
, 1);
1480 m_assembler
.sltu(dest
, MIPSRegisters::zero
, cmpTempRegister
);
1484 void test32(ResultCondition cond
, Address address
, TrustedImm32 mask
, RegisterID dest
)
1486 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1487 load32(address
, dataTempRegister
);
1488 if (mask
.m_value
== -1 && !m_fixedWidth
) {
1490 m_assembler
.sltiu(dest
, dataTempRegister
, 1);
1492 m_assembler
.sltu(dest
, MIPSRegisters::zero
, dataTempRegister
);
1494 move(mask
, immTempRegister
);
1495 m_assembler
.andInsn(cmpTempRegister
, dataTempRegister
,
1498 m_assembler
.sltiu(dest
, cmpTempRegister
, 1);
1500 m_assembler
.sltu(dest
, MIPSRegisters::zero
, cmpTempRegister
);
1504 DataLabel32
moveWithPatch(TrustedImm32 imm
, RegisterID dest
)
1506 m_fixedWidth
= true;
1507 DataLabel32
label(this);
1509 m_fixedWidth
= false;
1513 DataLabelPtr
moveWithPatch(TrustedImmPtr initialValue
, RegisterID dest
)
1515 m_fixedWidth
= true;
1516 DataLabelPtr
label(this);
1517 move(initialValue
, dest
);
1518 m_fixedWidth
= false;
1522 Jump
branchPtrWithPatch(RelationalCondition cond
, RegisterID left
, DataLabelPtr
& dataLabel
, TrustedImmPtr initialRightValue
= TrustedImmPtr(0))
1524 m_fixedWidth
= true;
1525 dataLabel
= moveWithPatch(initialRightValue
, immTempRegister
);
1526 Jump temp
= branch32(cond
, left
, immTempRegister
);
1527 m_fixedWidth
= false;
1531 Jump
branchPtrWithPatch(RelationalCondition cond
, Address left
, DataLabelPtr
& dataLabel
, TrustedImmPtr initialRightValue
= TrustedImmPtr(0))
1533 m_fixedWidth
= true;
1534 load32(left
, dataTempRegister
);
1535 dataLabel
= moveWithPatch(initialRightValue
, immTempRegister
);
1536 Jump temp
= branch32(cond
, dataTempRegister
, immTempRegister
);
1537 m_fixedWidth
= false;
1541 DataLabelPtr
storePtrWithPatch(TrustedImmPtr initialValue
, ImplicitAddress address
)
1543 m_fixedWidth
= true;
1544 DataLabelPtr dataLabel
= moveWithPatch(initialValue
, dataTempRegister
);
1545 store32(dataTempRegister
, address
);
1546 m_fixedWidth
= false;
1550 DataLabelPtr
storePtrWithPatch(ImplicitAddress address
)
1552 return storePtrWithPatch(TrustedImmPtr(0), address
);
1555 Call
tailRecursiveCall()
1557 // Like a normal call, but don't update the returned address register
1558 m_fixedWidth
= true;
1559 move(TrustedImm32(0), MIPSRegisters::t9
);
1560 m_assembler
.jr(MIPSRegisters::t9
);
1562 m_fixedWidth
= false;
1563 return Call(m_assembler
.label(), Call::Linkable
);
1566 Call
makeTailRecursiveCall(Jump oldJump
)
1569 return tailRecursiveCall();
1572 void loadDouble(ImplicitAddress address
, FPRegisterID dest
)
1576 li addrTemp, address.offset
1577 addu addrTemp, addrTemp, base
1578 lwc1 dest, 0(addrTemp)
1579 lwc1 dest+1, 4(addrTemp)
1581 move(TrustedImm32(address
.offset
), addrTempRegister
);
1582 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1583 m_assembler
.lwc1(dest
, addrTempRegister
, 0);
1584 m_assembler
.lwc1(FPRegisterID(dest
+ 1), addrTempRegister
, 4);
1586 if (address
.offset
>= -32768 && address
.offset
<= 32767
1588 m_assembler
.ldc1(dest
, address
.base
, address
.offset
);
1591 lui addrTemp, (offset + 0x8000) >> 16
1592 addu addrTemp, addrTemp, base
1593 ldc1 dest, (offset & 0xffff)(addrTemp)
1595 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
1596 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1597 m_assembler
.ldc1(dest
, addrTempRegister
, address
.offset
);
1602 void loadDouble(const void* address
, FPRegisterID dest
)
1606 li addrTemp, address
1607 lwc1 dest, 0(addrTemp)
1608 lwc1 dest+1, 4(addrTemp)
1610 move(TrustedImmPtr(address
), addrTempRegister
);
1611 m_assembler
.lwc1(dest
, addrTempRegister
, 0);
1612 m_assembler
.lwc1(FPRegisterID(dest
+ 1), addrTempRegister
, 4);
1615 li addrTemp, address
1616 ldc1 dest, 0(addrTemp)
1618 move(TrustedImmPtr(address
), addrTempRegister
);
1619 m_assembler
.ldc1(dest
, addrTempRegister
, 0);
1624 void storeDouble(FPRegisterID src
, ImplicitAddress address
)
1628 li addrTemp, address.offset
1629 addu addrTemp, addrTemp, base
1630 swc1 dest, 0(addrTemp)
1631 swc1 dest+1, 4(addrTemp)
1633 move(TrustedImm32(address
.offset
), addrTempRegister
);
1634 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1635 m_assembler
.swc1(src
, addrTempRegister
, 0);
1636 m_assembler
.swc1(FPRegisterID(src
+ 1), addrTempRegister
, 4);
1638 if (address
.offset
>= -32768 && address
.offset
<= 32767
1640 m_assembler
.sdc1(src
, address
.base
, address
.offset
);
1643 lui addrTemp, (offset + 0x8000) >> 16
1644 addu addrTemp, addrTemp, base
1645 sdc1 src, (offset & 0xffff)(addrTemp)
1647 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
1648 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1649 m_assembler
.sdc1(src
, addrTempRegister
, address
.offset
);
1654 void addDouble(FPRegisterID src
, FPRegisterID dest
)
1656 m_assembler
.addd(dest
, dest
, src
);
1659 void addDouble(Address src
, FPRegisterID dest
)
1661 loadDouble(src
, fpTempRegister
);
1662 m_assembler
.addd(dest
, dest
, fpTempRegister
);
1665 void subDouble(FPRegisterID src
, FPRegisterID dest
)
1667 m_assembler
.subd(dest
, dest
, src
);
1670 void subDouble(Address src
, FPRegisterID dest
)
1672 loadDouble(src
, fpTempRegister
);
1673 m_assembler
.subd(dest
, dest
, fpTempRegister
);
1676 void mulDouble(FPRegisterID src
, FPRegisterID dest
)
1678 m_assembler
.muld(dest
, dest
, src
);
1681 void mulDouble(Address src
, FPRegisterID dest
)
1683 loadDouble(src
, fpTempRegister
);
1684 m_assembler
.muld(dest
, dest
, fpTempRegister
);
1687 void divDouble(FPRegisterID src
, FPRegisterID dest
)
1689 m_assembler
.divd(dest
, dest
, src
);
1692 void convertInt32ToDouble(RegisterID src
, FPRegisterID dest
)
1694 m_assembler
.mtc1(src
, fpTempRegister
);
1695 m_assembler
.cvtdw(dest
, fpTempRegister
);
1698 void convertInt32ToDouble(Address src
, FPRegisterID dest
)
1700 load32(src
, dataTempRegister
);
1701 m_assembler
.mtc1(dataTempRegister
, fpTempRegister
);
1702 m_assembler
.cvtdw(dest
, fpTempRegister
);
1705 void convertInt32ToDouble(AbsoluteAddress src
, FPRegisterID dest
)
1707 load32(src
.m_ptr
, dataTempRegister
);
1708 m_assembler
.mtc1(dataTempRegister
, fpTempRegister
);
1709 m_assembler
.cvtdw(dest
, fpTempRegister
);
1712 void insertRelaxationWords()
1714 /* We need four words for relaxation. */
1715 m_assembler
.beq(MIPSRegisters::zero
, MIPSRegisters::zero
, 3); // Jump over nops;
1723 m_assembler
.appendJump();
1726 insertRelaxationWords();
1727 return Jump(m_assembler
.label());
1732 m_assembler
.appendJump();
1735 insertRelaxationWords();
1736 return Jump(m_assembler
.label());
1739 Jump
branchEqual(RegisterID rs
, RegisterID rt
)
1741 m_assembler
.appendJump();
1742 m_assembler
.beq(rs
, rt
, 0);
1744 insertRelaxationWords();
1745 return Jump(m_assembler
.label());
1748 Jump
branchNotEqual(RegisterID rs
, RegisterID rt
)
1750 m_assembler
.appendJump();
1751 m_assembler
.bne(rs
, rt
, 0);
1753 insertRelaxationWords();
1754 return Jump(m_assembler
.label());
1757 Jump
branchDouble(DoubleCondition cond
, FPRegisterID left
, FPRegisterID right
)
1759 if (cond
== DoubleEqual
) {
1760 m_assembler
.ceqd(left
, right
);
1761 return branchTrue();
1763 if (cond
== DoubleNotEqual
) {
1764 m_assembler
.cueqd(left
, right
);
1765 return branchFalse(); // false
1767 if (cond
== DoubleGreaterThan
) {
1768 m_assembler
.cngtd(left
, right
);
1769 return branchFalse(); // false
1771 if (cond
== DoubleGreaterThanOrEqual
) {
1772 m_assembler
.cnged(left
, right
);
1773 return branchFalse(); // false
1775 if (cond
== DoubleLessThan
) {
1776 m_assembler
.cltd(left
, right
);
1777 return branchTrue();
1779 if (cond
== DoubleLessThanOrEqual
) {
1780 m_assembler
.cled(left
, right
);
1781 return branchTrue();
1783 if (cond
== DoubleEqualOrUnordered
) {
1784 m_assembler
.cueqd(left
, right
);
1785 return branchTrue();
1787 if (cond
== DoubleNotEqualOrUnordered
) {
1788 m_assembler
.ceqd(left
, right
);
1789 return branchFalse(); // false
1791 if (cond
== DoubleGreaterThanOrUnordered
) {
1792 m_assembler
.coled(left
, right
);
1793 return branchFalse(); // false
1795 if (cond
== DoubleGreaterThanOrEqualOrUnordered
) {
1796 m_assembler
.coltd(left
, right
);
1797 return branchFalse(); // false
1799 if (cond
== DoubleLessThanOrUnordered
) {
1800 m_assembler
.cultd(left
, right
);
1801 return branchTrue();
1803 if (cond
== DoubleLessThanOrEqualOrUnordered
) {
1804 m_assembler
.culed(left
, right
);
1805 return branchTrue();
1812 // Truncates 'src' to an integer, and places the resulting 'dest'.
1813 // If the result is not representable as a 32 bit value, branch.
1814 // May also branch for some values that are representable in 32 bits
1815 // (specifically, in this case, INT_MAX 0x7fffffff).
1816 Jump
branchTruncateDoubleToInt32(FPRegisterID src
, RegisterID dest
)
1818 m_assembler
.truncwd(fpTempRegister
, src
);
1819 m_assembler
.mfc1(dest
, fpTempRegister
);
1820 return branch32(Equal
, dest
, TrustedImm32(0x7fffffff));
1823 // Convert 'src' to an integer, and places the resulting 'dest'.
1824 // If the result is not representable as a 32 bit value, branch.
1825 // May also branch for some values that are representable in 32 bits
1826 // (specifically, in this case, 0).
1827 void branchConvertDoubleToInt32(FPRegisterID src
, RegisterID dest
, JumpList
& failureCases
, FPRegisterID fpTemp
)
1829 m_assembler
.cvtwd(fpTempRegister
, src
);
1830 m_assembler
.mfc1(dest
, fpTempRegister
);
1832 // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
1833 failureCases
.append(branch32(Equal
, dest
, MIPSRegisters::zero
));
1835 // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
1836 convertInt32ToDouble(dest
, fpTemp
);
1837 failureCases
.append(branchDouble(DoubleNotEqualOrUnordered
, fpTemp
, src
));
1840 Jump
branchDoubleNonZero(FPRegisterID reg
, FPRegisterID scratch
)
1842 #if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
1843 m_assembler
.mtc1(MIPSRegisters::zero
, scratch
);
1844 m_assembler
.mthc1(MIPSRegisters::zero
, scratch
);
1846 m_assembler
.mtc1(MIPSRegisters::zero
, scratch
);
1847 m_assembler
.mtc1(MIPSRegisters::zero
, FPRegisterID(scratch
+ 1));
1849 return branchDouble(DoubleNotEqual
, reg
, scratch
);
1852 Jump
branchDoubleZeroOrNaN(FPRegisterID reg
, FPRegisterID scratch
)
1854 #if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
1855 m_assembler
.mtc1(MIPSRegisters::zero
, scratch
);
1856 m_assembler
.mthc1(MIPSRegisters::zero
, scratch
);
1858 m_assembler
.mtc1(MIPSRegisters::zero
, scratch
);
1859 m_assembler
.mtc1(MIPSRegisters::zero
, FPRegisterID(scratch
+ 1));
1861 return branchDouble(DoubleEqualOrUnordered
, reg
, scratch
);
1869 static FunctionPtr
readCallTarget(CodeLocationCall call
)
1871 return FunctionPtr(reinterpret_cast<void(*)()>(MIPSAssembler::readCallTarget(call
.dataLocation())));
1875 // If m_fixedWidth is true, we will generate a fixed number of instructions.
1876 // Otherwise, we can emit any number of instructions.
1879 friend class LinkBuffer
;
1880 friend class RepatchBuffer
;
1882 static void linkCall(void* code
, Call call
, FunctionPtr function
)
1884 MIPSAssembler::linkCall(code
, call
.m_label
, function
.value());
1887 static void repatchCall(CodeLocationCall call
, CodeLocationLabel destination
)
1889 MIPSAssembler::relinkCall(call
.dataLocation(), destination
.executableAddress());
1892 static void repatchCall(CodeLocationCall call
, FunctionPtr destination
)
1894 MIPSAssembler::relinkCall(call
.dataLocation(), destination
.executableAddress());
1901 #endif // ENABLE(ASSEMBLER) && CPU(MIPS)
1903 #endif // MacroAssemblerMIPS_h