2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 MIPS Technologies, Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY MIPS TECHNOLOGIES, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MIPS TECHNOLOGIES, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #ifndef MacroAssemblerMIPS_h
28 #define MacroAssemblerMIPS_h
30 #if ENABLE(ASSEMBLER) && CPU(MIPS)
32 #include "AbstractMacroAssembler.h"
33 #include "MIPSAssembler.h"
37 class MacroAssemblerMIPS
: public AbstractMacroAssembler
<MIPSAssembler
> {
45 static const Scale ScalePtr
= TimesFour
;
47 // For storing immediate number
48 static const RegisterID immTempRegister
= MIPSRegisters::t0
;
49 // For storing data loaded from the memory
50 static const RegisterID dataTempRegister
= MIPSRegisters::t1
;
51 // For storing address base
52 static const RegisterID addrTempRegister
= MIPSRegisters::t2
;
53 // For storing compare result
54 static const RegisterID cmpTempRegister
= MIPSRegisters::t3
;
57 static const FPRegisterID fpTempRegister
= MIPSRegisters::f16
;
76 enum DoubleCondition
{
80 DoubleGreaterThanOrEqual
,
82 DoubleLessThanOrEqual
,
83 DoubleEqualOrUnordered
,
84 DoubleNotEqualOrUnordered
,
85 DoubleGreaterThanOrUnordered
,
86 DoubleGreaterThanOrEqualOrUnordered
,
87 DoubleLessThanOrUnordered
,
88 DoubleLessThanOrEqualOrUnordered
91 static const RegisterID stackPointerRegister
= MIPSRegisters::sp
;
92 static const RegisterID returnAddressRegister
= MIPSRegisters::ra
;
94 // Integer arithmetic operations:
96 // Operations are typically two operand - operation(source, srcDst)
97 // For many operations the source may be an Imm32, the srcDst operand
98 // may often be a memory location (explictly described using an Address
101 void add32(RegisterID src
, RegisterID dest
)
103 m_assembler
.addu(dest
, dest
, src
);
106 void add32(Imm32 imm
, RegisterID dest
)
108 add32(imm
, dest
, dest
);
111 void add32(Imm32 imm
, RegisterID src
, RegisterID dest
)
113 if (!imm
.m_isPointer
&& imm
.m_value
>= -32768 && imm
.m_value
<= 32767
118 m_assembler
.addiu(dest
, src
, imm
.m_value
);
122 addu dest, src, immTemp
124 move(imm
, immTempRegister
);
125 m_assembler
.addu(dest
, src
, immTempRegister
);
129 void add32(Imm32 imm
, Address address
)
131 if (address
.offset
>= -32768 && address
.offset
<= 32767
134 lw dataTemp, offset(base)
136 addu dataTemp, dataTemp, immTemp
137 sw dataTemp, offset(base)
139 m_assembler
.lw(dataTempRegister
, address
.base
, address
.offset
);
141 && imm
.m_value
>= -32768 && imm
.m_value
<= 32767
143 m_assembler
.addiu(dataTempRegister
, dataTempRegister
,
146 move(imm
, immTempRegister
);
147 m_assembler
.addu(dataTempRegister
, dataTempRegister
,
150 m_assembler
.sw(dataTempRegister
, address
.base
, address
.offset
);
153 lui addrTemp, (offset + 0x8000) >> 16
154 addu addrTemp, addrTemp, base
155 lw dataTemp, (offset & 0xffff)(addrTemp)
157 addu dataTemp, dataTemp, immTemp
158 sw dataTemp, (offset & 0xffff)(addrTemp)
160 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
161 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
162 m_assembler
.lw(dataTempRegister
, addrTempRegister
, address
.offset
);
164 if (imm
.m_value
>= -32768 && imm
.m_value
<= 32767 && !m_fixedWidth
)
165 m_assembler
.addiu(dataTempRegister
, dataTempRegister
,
168 move(imm
, immTempRegister
);
169 m_assembler
.addu(dataTempRegister
, dataTempRegister
,
172 m_assembler
.sw(dataTempRegister
, addrTempRegister
, address
.offset
);
176 void add32(Address src
, RegisterID dest
)
178 load32(src
, dataTempRegister
);
179 add32(dataTempRegister
, dest
);
182 void add32(RegisterID src
, Address dest
)
184 if (dest
.offset
>= -32768 && dest
.offset
<= 32767 && !m_fixedWidth
) {
186 lw dataTemp, offset(base)
187 addu dataTemp, dataTemp, src
188 sw dataTemp, offset(base)
190 m_assembler
.lw(dataTempRegister
, dest
.base
, dest
.offset
);
191 m_assembler
.addu(dataTempRegister
, dataTempRegister
, src
);
192 m_assembler
.sw(dataTempRegister
, dest
.base
, dest
.offset
);
195 lui addrTemp, (offset + 0x8000) >> 16
196 addu addrTemp, addrTemp, base
197 lw dataTemp, (offset & 0xffff)(addrTemp)
198 addu dataTemp, dataTemp, src
199 sw dataTemp, (offset & 0xffff)(addrTemp)
201 m_assembler
.lui(addrTempRegister
, (dest
.offset
+ 0x8000) >> 16);
202 m_assembler
.addu(addrTempRegister
, addrTempRegister
, dest
.base
);
203 m_assembler
.lw(dataTempRegister
, addrTempRegister
, dest
.offset
);
204 m_assembler
.addu(dataTempRegister
, dataTempRegister
, src
);
205 m_assembler
.sw(dataTempRegister
, addrTempRegister
, dest
.offset
);
209 void add32(Imm32 imm
, AbsoluteAddress address
)
214 lw dataTemp, 0(addrTemp)
215 addu dataTemp, dataTemp, immTemp
216 sw dataTemp, 0(addrTemp)
218 move(ImmPtr(address
.m_ptr
), addrTempRegister
);
219 m_assembler
.lw(dataTempRegister
, addrTempRegister
, 0);
220 if (!imm
.m_isPointer
&& imm
.m_value
>= -32768 && imm
.m_value
<= 32767
222 m_assembler
.addiu(dataTempRegister
, dataTempRegister
, imm
.m_value
);
224 move(imm
, immTempRegister
);
225 m_assembler
.addu(dataTempRegister
, dataTempRegister
, immTempRegister
);
227 m_assembler
.sw(dataTempRegister
, addrTempRegister
, 0);
230 void and32(RegisterID src
, RegisterID dest
)
232 m_assembler
.andInsn(dest
, dest
, src
);
235 void and32(Imm32 imm
, RegisterID dest
)
237 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
)
238 move(MIPSRegisters::zero
, dest
);
239 else if (!imm
.m_isPointer
&& imm
.m_value
> 0 && imm
.m_value
< 65535
241 m_assembler
.andi(dest
, dest
, imm
.m_value
);
245 and dest, dest, immTemp
247 move(imm
, immTempRegister
);
248 m_assembler
.andInsn(dest
, dest
, immTempRegister
);
252 void lshift32(Imm32 imm
, RegisterID dest
)
254 m_assembler
.sll(dest
, dest
, imm
.m_value
);
257 void lshift32(RegisterID shiftAmount
, RegisterID dest
)
259 m_assembler
.sllv(dest
, dest
, shiftAmount
);
262 void mul32(RegisterID src
, RegisterID dest
)
264 m_assembler
.mul(dest
, dest
, src
);
267 void mul32(Imm32 imm
, RegisterID src
, RegisterID dest
)
269 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
)
270 move(MIPSRegisters::zero
, dest
);
271 else if (!imm
.m_isPointer
&& imm
.m_value
== 1 && !m_fixedWidth
)
276 mul dest, src, dataTemp
278 move(imm
, dataTempRegister
);
279 m_assembler
.mul(dest
, src
, dataTempRegister
);
283 void not32(RegisterID srcDest
)
285 m_assembler
.nor(srcDest
, srcDest
, MIPSRegisters::zero
);
288 void or32(RegisterID src
, RegisterID dest
)
290 m_assembler
.orInsn(dest
, dest
, src
);
293 void or32(Imm32 imm
, RegisterID dest
)
295 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
)
298 if (!imm
.m_isPointer
&& imm
.m_value
> 0 && imm
.m_value
< 65535
300 m_assembler
.ori(dest
, dest
, imm
.m_value
);
306 or dest, dest, dataTemp
308 move(imm
, dataTempRegister
);
309 m_assembler
.orInsn(dest
, dest
, dataTempRegister
);
312 void rshift32(RegisterID shiftAmount
, RegisterID dest
)
314 m_assembler
.srav(dest
, dest
, shiftAmount
);
317 void rshift32(Imm32 imm
, RegisterID dest
)
319 m_assembler
.sra(dest
, dest
, imm
.m_value
);
322 void sub32(RegisterID src
, RegisterID dest
)
324 m_assembler
.subu(dest
, dest
, src
);
327 void sub32(Imm32 imm
, RegisterID dest
)
329 if (!imm
.m_isPointer
&& imm
.m_value
>= -32767 && imm
.m_value
<= 32768
334 m_assembler
.addiu(dest
, dest
, -imm
.m_value
);
338 subu dest, src, immTemp
340 move(imm
, immTempRegister
);
341 m_assembler
.subu(dest
, dest
, immTempRegister
);
345 void sub32(Imm32 imm
, Address address
)
347 if (address
.offset
>= -32768 && address
.offset
<= 32767
350 lw dataTemp, offset(base)
352 subu dataTemp, dataTemp, immTemp
353 sw dataTemp, offset(base)
355 m_assembler
.lw(dataTempRegister
, address
.base
, address
.offset
);
357 && imm
.m_value
>= -32767 && imm
.m_value
<= 32768
359 m_assembler
.addiu(dataTempRegister
, dataTempRegister
,
362 move(imm
, immTempRegister
);
363 m_assembler
.subu(dataTempRegister
, dataTempRegister
,
366 m_assembler
.sw(dataTempRegister
, address
.base
, address
.offset
);
369 lui addrTemp, (offset + 0x8000) >> 16
370 addu addrTemp, addrTemp, base
371 lw dataTemp, (offset & 0xffff)(addrTemp)
373 subu dataTemp, dataTemp, immTemp
374 sw dataTemp, (offset & 0xffff)(addrTemp)
376 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
377 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
378 m_assembler
.lw(dataTempRegister
, addrTempRegister
, address
.offset
);
381 && imm
.m_value
>= -32767 && imm
.m_value
<= 32768
383 m_assembler
.addiu(dataTempRegister
, dataTempRegister
,
386 move(imm
, immTempRegister
);
387 m_assembler
.subu(dataTempRegister
, dataTempRegister
,
390 m_assembler
.sw(dataTempRegister
, addrTempRegister
, address
.offset
);
394 void sub32(Address src
, RegisterID dest
)
396 load32(src
, dataTempRegister
);
397 sub32(dataTempRegister
, dest
);
400 void sub32(Imm32 imm
, AbsoluteAddress address
)
405 lw dataTemp, 0(addrTemp)
406 subu dataTemp, dataTemp, immTemp
407 sw dataTemp, 0(addrTemp)
409 move(ImmPtr(address
.m_ptr
), addrTempRegister
);
410 m_assembler
.lw(dataTempRegister
, addrTempRegister
, 0);
412 if (!imm
.m_isPointer
&& imm
.m_value
>= -32767 && imm
.m_value
<= 32768
414 m_assembler
.addiu(dataTempRegister
, dataTempRegister
,
417 move(imm
, immTempRegister
);
418 m_assembler
.subu(dataTempRegister
, dataTempRegister
, immTempRegister
);
420 m_assembler
.sw(dataTempRegister
, addrTempRegister
, 0);
423 void xor32(RegisterID src
, RegisterID dest
)
425 m_assembler
.xorInsn(dest
, dest
, src
);
428 void xor32(Imm32 imm
, RegisterID dest
)
432 xor dest, dest, immTemp
434 move(imm
, immTempRegister
);
435 m_assembler
.xorInsn(dest
, dest
, immTempRegister
);
438 // Memory access operations:
440 // Loads are of the form load(address, destination) and stores of the form
441 // store(source, address). The source for a store may be an Imm32. Address
442 // operand objects to loads and store will be implicitly constructed if a
443 // register is passed.
445 /* Need to use zero-extened load byte for load8. */
446 void load8(ImplicitAddress address
, RegisterID dest
)
448 if (address
.offset
>= -32768 && address
.offset
<= 32767
450 m_assembler
.lbu(dest
, address
.base
, address
.offset
);
453 lui addrTemp, (offset + 0x8000) >> 16
454 addu addrTemp, addrTemp, base
455 lbu dest, (offset & 0xffff)(addrTemp)
457 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
458 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
459 m_assembler
.lbu(dest
, addrTempRegister
, address
.offset
);
463 void load32(ImplicitAddress address
, RegisterID dest
)
465 if (address
.offset
>= -32768 && address
.offset
<= 32767
467 m_assembler
.lw(dest
, address
.base
, address
.offset
);
470 lui addrTemp, (offset + 0x8000) >> 16
471 addu addrTemp, addrTemp, base
472 lw dest, (offset & 0xffff)(addrTemp)
474 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
475 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
476 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
480 void load32(BaseIndex address
, RegisterID dest
)
482 if (address
.offset
>= -32768 && address
.offset
<= 32767
485 sll addrTemp, address.index, address.scale
486 addu addrTemp, addrTemp, address.base
487 lw dest, address.offset(addrTemp)
489 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
490 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
491 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
494 sll addrTemp, address.index, address.scale
495 addu addrTemp, addrTemp, address.base
496 lui immTemp, (address.offset + 0x8000) >> 16
497 addu addrTemp, addrTemp, immTemp
498 lw dest, (address.offset & 0xffff)(at)
500 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
501 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
502 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
503 m_assembler
.addu(addrTempRegister
, addrTempRegister
,
505 m_assembler
.lw(dest
, addrTempRegister
, address
.offset
);
509 void load32WithUnalignedHalfWords(BaseIndex address
, RegisterID dest
)
511 if (address
.offset
>= -32768 && address
.offset
<= 32764
514 sll addrTemp, address.index, address.scale
515 addu addrTemp, addrTemp, address.base
517 lwl dest, address.offset(addrTemp)
518 lwr dest, address.offset+3(addrTemp)
520 lwl dest, address.offset+3(addrTemp)
521 lwr dest, address.offset(addrTemp)
523 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
524 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
526 m_assembler
.lwl(dest
, addrTempRegister
, address
.offset
);
527 m_assembler
.lwr(dest
, addrTempRegister
, address
.offset
+ 3);
529 m_assembler
.lwl(dest
, addrTempRegister
, address
.offset
+ 3);
530 m_assembler
.lwr(dest
, addrTempRegister
, address
.offset
);
535 sll addrTemp, address.index, address.scale
536 addu addrTemp, addrTemp, address.base
537 lui immTemp, address.offset >> 16
538 ori immTemp, immTemp, address.offset & 0xffff
539 addu addrTemp, addrTemp, immTemp
547 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
548 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
549 m_assembler
.lui(immTempRegister
, address
.offset
>> 16);
550 m_assembler
.ori(immTempRegister
, immTempRegister
, address
.offset
);
551 m_assembler
.addu(addrTempRegister
, addrTempRegister
,
554 m_assembler
.lwl(dest
, addrTempRegister
, 0);
555 m_assembler
.lwr(dest
, addrTempRegister
, 3);
557 m_assembler
.lwl(dest
, addrTempRegister
, 3);
558 m_assembler
.lwr(dest
, addrTempRegister
, 0);
563 void load32(void* address
, RegisterID dest
)
569 move(ImmPtr(address
), addrTempRegister
);
570 m_assembler
.lw(dest
, addrTempRegister
, 0);
573 DataLabel32
load32WithAddressOffsetPatch(Address address
, RegisterID dest
)
577 lui addrTemp, address.offset >> 16
578 ori addrTemp, addrTemp, address.offset & 0xffff
579 addu addrTemp, addrTemp, address.base
582 DataLabel32
dataLabel(this);
583 move(Imm32(address
.offset
), addrTempRegister
);
584 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
585 m_assembler
.lw(dest
, addrTempRegister
, 0);
586 m_fixedWidth
= false;
590 Label
loadPtrWithPatchToLEA(Address address
, RegisterID dest
)
594 lui addrTemp, address.offset >> 16
595 ori addrTemp, addrTemp, address.offset & 0xffff
596 addu addrTemp, addrTemp, address.base
600 move(Imm32(address
.offset
), addrTempRegister
);
601 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
602 m_assembler
.lw(dest
, addrTempRegister
, 0);
603 m_fixedWidth
= false;
607 Label
loadPtrWithAddressOffsetPatch(Address address
, RegisterID dest
)
609 return loadPtrWithPatchToLEA(address
, dest
);
612 /* Need to use zero-extened load half-word for load16. */
613 void load16(BaseIndex address
, RegisterID dest
)
615 if (address
.offset
>= -32768 && address
.offset
<= 32767
618 sll addrTemp, address.index, address.scale
619 addu addrTemp, addrTemp, address.base
620 lhu dest, address.offset(addrTemp)
622 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
623 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
624 m_assembler
.lhu(dest
, addrTempRegister
, address
.offset
);
627 sll addrTemp, address.index, address.scale
628 addu addrTemp, addrTemp, address.base
629 lui immTemp, (address.offset + 0x8000) >> 16
630 addu addrTemp, addrTemp, immTemp
631 lhu dest, (address.offset & 0xffff)(addrTemp)
633 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
634 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
635 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
636 m_assembler
.addu(addrTempRegister
, addrTempRegister
,
638 m_assembler
.lhu(dest
, addrTempRegister
, address
.offset
);
642 DataLabel32
store32WithAddressOffsetPatch(RegisterID src
, Address address
)
646 lui addrTemp, address.offset >> 16
647 ori addrTemp, addrTemp, address.offset & 0xffff
648 addu addrTemp, addrTemp, address.base
651 DataLabel32
dataLabel(this);
652 move(Imm32(address
.offset
), addrTempRegister
);
653 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
654 m_assembler
.sw(src
, addrTempRegister
, 0);
655 m_fixedWidth
= false;
659 void store32(RegisterID src
, ImplicitAddress address
)
661 if (address
.offset
>= -32768 && address
.offset
<= 32767
663 m_assembler
.sw(src
, address
.base
, address
.offset
);
666 lui addrTemp, (offset + 0x8000) >> 16
667 addu addrTemp, addrTemp, base
668 sw src, (offset & 0xffff)(addrTemp)
670 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
671 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
672 m_assembler
.sw(src
, addrTempRegister
, address
.offset
);
676 void store32(RegisterID src
, BaseIndex address
)
678 if (address
.offset
>= -32768 && address
.offset
<= 32767
681 sll addrTemp, address.index, address.scale
682 addu addrTemp, addrTemp, address.base
683 sw src, address.offset(addrTemp)
685 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
686 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
687 m_assembler
.sw(src
, addrTempRegister
, address
.offset
);
690 sll addrTemp, address.index, address.scale
691 addu addrTemp, addrTemp, address.base
692 lui immTemp, (address.offset + 0x8000) >> 16
693 addu addrTemp, addrTemp, immTemp
694 sw src, (address.offset & 0xffff)(at)
696 m_assembler
.sll(addrTempRegister
, address
.index
, address
.scale
);
697 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
698 m_assembler
.lui(immTempRegister
, (address
.offset
+ 0x8000) >> 16);
699 m_assembler
.addu(addrTempRegister
, addrTempRegister
,
701 m_assembler
.sw(src
, addrTempRegister
, address
.offset
);
705 void store32(Imm32 imm
, ImplicitAddress address
)
707 if (address
.offset
>= -32768 && address
.offset
<= 32767
709 if (!imm
.m_isPointer
&& !imm
.m_value
)
710 m_assembler
.sw(MIPSRegisters::zero
, address
.base
,
713 move(imm
, immTempRegister
);
714 m_assembler
.sw(immTempRegister
, address
.base
, address
.offset
);
718 lui addrTemp, (offset + 0x8000) >> 16
719 addu addrTemp, addrTemp, base
720 sw immTemp, (offset & 0xffff)(addrTemp)
722 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
723 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
724 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
)
725 m_assembler
.sw(MIPSRegisters::zero
, addrTempRegister
,
728 move(imm
, immTempRegister
);
729 m_assembler
.sw(immTempRegister
, addrTempRegister
,
735 void store32(RegisterID src
, void* address
)
741 move(ImmPtr(address
), addrTempRegister
);
742 m_assembler
.sw(src
, addrTempRegister
, 0);
745 void store32(Imm32 imm
, void* address
)
752 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
) {
753 move(ImmPtr(address
), addrTempRegister
);
754 m_assembler
.sw(MIPSRegisters::zero
, addrTempRegister
, 0);
756 move(imm
, immTempRegister
);
757 move(ImmPtr(address
), addrTempRegister
);
758 m_assembler
.sw(immTempRegister
, addrTempRegister
, 0);
762 // Floating-point operations:
764 bool supportsFloatingPoint() const
766 #if WTF_MIPS_DOUBLE_FLOAT
773 bool supportsFloatingPointTruncate() const
775 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
782 // Stack manipulation operations:
784 // The ABI is assumed to provide a stack abstraction to memory,
785 // containing machine word sized units of data. Push and pop
786 // operations add and remove a single register sized unit of data
787 // to or from the stack. Peek and poke operations read or write
788 // values on the stack, without moving the current stack position.
790 void pop(RegisterID dest
)
792 m_assembler
.lw(dest
, MIPSRegisters::sp
, 0);
793 m_assembler
.addiu(MIPSRegisters::sp
, MIPSRegisters::sp
, 4);
796 void push(RegisterID src
)
798 m_assembler
.addiu(MIPSRegisters::sp
, MIPSRegisters::sp
, -4);
799 m_assembler
.sw(src
, MIPSRegisters::sp
, 0);
802 void push(Address address
)
804 load32(address
, dataTempRegister
);
805 push(dataTempRegister
);
810 move(imm
, immTempRegister
);
811 push(immTempRegister
);
814 // Register move operations:
816 // Move values in registers.
818 void move(Imm32 imm
, RegisterID dest
)
820 if (!imm
.m_isPointer
&& !imm
.m_value
&& !m_fixedWidth
)
821 move(MIPSRegisters::zero
, dest
);
822 else if (imm
.m_isPointer
|| m_fixedWidth
) {
823 m_assembler
.lui(dest
, imm
.m_value
>> 16);
824 m_assembler
.ori(dest
, dest
, imm
.m_value
);
826 m_assembler
.li(dest
, imm
.m_value
);
829 void move(RegisterID src
, RegisterID dest
)
831 if (src
!= dest
|| m_fixedWidth
)
832 m_assembler
.move(dest
, src
);
835 void move(ImmPtr imm
, RegisterID dest
)
837 move(Imm32(imm
), dest
);
840 void swap(RegisterID reg1
, RegisterID reg2
)
842 move(reg1
, immTempRegister
);
844 move(immTempRegister
, reg2
);
847 void signExtend32ToPtr(RegisterID src
, RegisterID dest
)
849 if (src
!= dest
|| m_fixedWidth
)
853 void zeroExtend32ToPtr(RegisterID src
, RegisterID dest
)
855 if (src
!= dest
|| m_fixedWidth
)
859 // Forwards / external control flow operations:
861 // This set of jump and conditional branch operations return a Jump
862 // object which may linked at a later point, allow forwards jump,
863 // or jumps that will require external linkage (after the code has been
866 // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
867 // respecitvely, for unsigned comparisons the names b, a, be, and ae are
868 // used (representing the names 'below' and 'above').
870 // Operands to the comparision are provided in the expected order, e.g.
871 // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when
872 // treated as a signed 32bit value, is less than or equal to 5.
874 // jz and jnz test whether the first operand is equal to zero, and take
875 // an optional second operand of a mask under which to perform the test.
877 Jump
branch8(Condition cond
, Address left
, Imm32 right
)
879 // Make sure the immediate value is unsigned 8 bits.
880 ASSERT(!(right
.m_value
& 0xFFFFFF00));
881 load8(left
, dataTempRegister
);
882 move(right
, immTempRegister
);
883 return branch32(cond
, dataTempRegister
, immTempRegister
);
886 Jump
branch32(Condition cond
, RegisterID left
, RegisterID right
)
888 if (cond
== Equal
|| cond
== Zero
)
889 return branchEqual(left
, right
);
890 if (cond
== NotEqual
|| cond
== NonZero
)
891 return branchNotEqual(left
, right
);
893 m_assembler
.sltu(cmpTempRegister
, right
, left
);
894 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
896 if (cond
== AboveOrEqual
) {
897 m_assembler
.sltu(cmpTempRegister
, left
, right
);
898 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
901 m_assembler
.sltu(cmpTempRegister
, left
, right
);
902 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
904 if (cond
== BelowOrEqual
) {
905 m_assembler
.sltu(cmpTempRegister
, right
, left
);
906 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
908 if (cond
== GreaterThan
) {
909 m_assembler
.slt(cmpTempRegister
, right
, left
);
910 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
912 if (cond
== GreaterThanOrEqual
) {
913 m_assembler
.slt(cmpTempRegister
, left
, right
);
914 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
916 if (cond
== LessThan
) {
917 m_assembler
.slt(cmpTempRegister
, left
, right
);
918 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
920 if (cond
== LessThanOrEqual
) {
921 m_assembler
.slt(cmpTempRegister
, right
, left
);
922 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
924 if (cond
== Overflow
) {
926 xor cmpTemp, left, right
927 bgez No_overflow, cmpTemp # same sign bit -> no overflow
929 subu cmpTemp, left, right
930 xor cmpTemp, cmpTemp, left
931 bgez No_overflow, cmpTemp # same sign bit -> no overflow
941 m_assembler
.xorInsn(cmpTempRegister
, left
, right
);
942 m_assembler
.bgez(cmpTempRegister
, 11);
944 m_assembler
.subu(cmpTempRegister
, left
, right
);
945 m_assembler
.xorInsn(cmpTempRegister
, cmpTempRegister
, left
);
946 m_assembler
.bgez(cmpTempRegister
, 7);
950 if (cond
== Signed
) {
951 m_assembler
.subu(cmpTempRegister
, left
, right
);
952 // Check if the result is negative.
953 m_assembler
.slt(cmpTempRegister
, cmpTempRegister
,
954 MIPSRegisters::zero
);
955 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
962 Jump
branch32(Condition cond
, RegisterID left
, Imm32 right
)
964 move(right
, immTempRegister
);
965 return branch32(cond
, left
, immTempRegister
);
968 Jump
branch32(Condition cond
, RegisterID left
, Address right
)
970 load32(right
, dataTempRegister
);
971 return branch32(cond
, left
, dataTempRegister
);
974 Jump
branch32(Condition cond
, Address left
, RegisterID right
)
976 load32(left
, dataTempRegister
);
977 return branch32(cond
, dataTempRegister
, right
);
980 Jump
branch32(Condition cond
, Address left
, Imm32 right
)
982 load32(left
, dataTempRegister
);
983 move(right
, immTempRegister
);
984 return branch32(cond
, dataTempRegister
, immTempRegister
);
987 Jump
branch32(Condition cond
, BaseIndex left
, Imm32 right
)
989 load32(left
, dataTempRegister
);
990 // Be careful that the previous load32() uses immTempRegister.
991 // So, we need to put move() after load32().
992 move(right
, immTempRegister
);
993 return branch32(cond
, dataTempRegister
, immTempRegister
);
996 Jump
branch32WithUnalignedHalfWords(Condition cond
, BaseIndex left
, Imm32 right
)
998 load32WithUnalignedHalfWords(left
, dataTempRegister
);
999 // Be careful that the previous load32WithUnalignedHalfWords()
1000 // uses immTempRegister.
1001 // So, we need to put move() after load32WithUnalignedHalfWords().
1002 move(right
, immTempRegister
);
1003 return branch32(cond
, dataTempRegister
, immTempRegister
);
1006 Jump
branch32(Condition cond
, AbsoluteAddress left
, RegisterID right
)
1008 load32(left
.m_ptr
, dataTempRegister
);
1009 return branch32(cond
, dataTempRegister
, right
);
1012 Jump
branch32(Condition cond
, AbsoluteAddress left
, Imm32 right
)
1014 load32(left
.m_ptr
, dataTempRegister
);
1015 move(right
, immTempRegister
);
1016 return branch32(cond
, dataTempRegister
, immTempRegister
);
1019 Jump
branch16(Condition cond
, BaseIndex left
, RegisterID right
)
1021 load16(left
, dataTempRegister
);
1022 return branch32(cond
, dataTempRegister
, right
);
1025 Jump
branch16(Condition cond
, BaseIndex left
, Imm32 right
)
1027 ASSERT(!(right
.m_value
& 0xFFFF0000));
1028 load16(left
, dataTempRegister
);
1029 // Be careful that the previous load16() uses immTempRegister.
1030 // So, we need to put move() after load16().
1031 move(right
, immTempRegister
);
1032 return branch32(cond
, dataTempRegister
, immTempRegister
);
1035 Jump
branchTest32(Condition cond
, RegisterID reg
, RegisterID mask
)
1037 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1038 m_assembler
.andInsn(cmpTempRegister
, reg
, mask
);
1040 return branchEqual(cmpTempRegister
, MIPSRegisters::zero
);
1041 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1044 Jump
branchTest32(Condition cond
, RegisterID reg
, Imm32 mask
= Imm32(-1))
1046 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1047 if (mask
.m_value
== -1 && !m_fixedWidth
) {
1049 return branchEqual(reg
, MIPSRegisters::zero
);
1050 return branchNotEqual(reg
, MIPSRegisters::zero
);
1052 move(mask
, immTempRegister
);
1053 return branchTest32(cond
, reg
, immTempRegister
);
1056 Jump
branchTest32(Condition cond
, Address address
, Imm32 mask
= Imm32(-1))
1058 load32(address
, dataTempRegister
);
1059 return branchTest32(cond
, dataTempRegister
, mask
);
1062 Jump
branchTest32(Condition cond
, BaseIndex address
, Imm32 mask
= Imm32(-1))
1064 load32(address
, dataTempRegister
);
1065 return branchTest32(cond
, dataTempRegister
, mask
);
1068 Jump
branchTest8(Condition cond
, Address address
, Imm32 mask
= Imm32(-1))
1070 load8(address
, dataTempRegister
);
1071 return branchTest32(cond
, dataTempRegister
, mask
);
1076 return branchEqual(MIPSRegisters::zero
, MIPSRegisters::zero
);
1079 void jump(RegisterID target
)
1081 m_assembler
.jr(target
);
1085 void jump(Address address
)
1087 m_fixedWidth
= true;
1088 load32(address
, MIPSRegisters::t9
);
1089 m_assembler
.jr(MIPSRegisters::t9
);
1091 m_fixedWidth
= false;
1094 // Arithmetic control flow operations:
1096 // This set of conditional branch operations branch based
1097 // on the result of an arithmetic operation. The operation
1098 // is performed as normal, storing the result.
1100 // * jz operations branch if the result is zero.
1101 // * jo operations branch if the (signed) arithmetic
1102 // operation caused an overflow to occur.
1104 Jump
branchAdd32(Condition cond
, RegisterID src
, RegisterID dest
)
1106 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1107 if (cond
== Overflow
) {
1110 xor cmpTemp, dataTemp, src
1111 bltz cmpTemp, No_overflow # diff sign bit -> no overflow
1112 addu dest, dataTemp, src
1113 xor cmpTemp, dest, dataTemp
1114 bgez cmpTemp, No_overflow # same sign big -> no overflow
1124 move(dest
, dataTempRegister
);
1125 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, src
);
1126 m_assembler
.bltz(cmpTempRegister
, 10);
1127 m_assembler
.addu(dest
, dataTempRegister
, src
);
1128 m_assembler
.xorInsn(cmpTempRegister
, dest
, dataTempRegister
);
1129 m_assembler
.bgez(cmpTempRegister
, 7);
1133 if (cond
== Signed
) {
1135 // Check if dest is negative.
1136 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1137 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1141 return branchEqual(dest
, MIPSRegisters::zero
);
1143 if (cond
== NonZero
) {
1145 return branchNotEqual(dest
, MIPSRegisters::zero
);
1151 Jump
branchAdd32(Condition cond
, Imm32 imm
, RegisterID dest
)
1153 move(imm
, immTempRegister
);
1154 return branchAdd32(cond
, immTempRegister
, dest
);
1157 Jump
branchMul32(Condition cond
, RegisterID src
, RegisterID dest
)
1159 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1160 if (cond
== Overflow
) {
1165 sra addrTemp, dest, 31
1166 beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow
1176 m_assembler
.mult(src
, dest
);
1177 m_assembler
.mfhi(dataTempRegister
);
1178 m_assembler
.mflo(dest
);
1179 m_assembler
.sra(addrTempRegister
, dest
, 31);
1180 m_assembler
.beq(dataTempRegister
, addrTempRegister
, 7);
1184 if (cond
== Signed
) {
1186 // Check if dest is negative.
1187 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1188 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1192 return branchEqual(dest
, MIPSRegisters::zero
);
1194 if (cond
== NonZero
) {
1196 return branchNotEqual(dest
, MIPSRegisters::zero
);
1202 Jump
branchMul32(Condition cond
, Imm32 imm
, RegisterID src
, RegisterID dest
)
1204 move(imm
, immTempRegister
);
1206 return branchMul32(cond
, immTempRegister
, dest
);
1209 Jump
branchSub32(Condition cond
, RegisterID src
, RegisterID dest
)
1211 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
1212 if (cond
== Overflow
) {
1215 xor cmpTemp, dataTemp, src
1216 bgez cmpTemp, No_overflow # same sign bit -> no overflow
1217 subu dest, dataTemp, src
1218 xor cmpTemp, dest, dataTemp
1219 bgez cmpTemp, No_overflow # same sign bit -> no overflow
1229 move(dest
, dataTempRegister
);
1230 m_assembler
.xorInsn(cmpTempRegister
, dataTempRegister
, src
);
1231 m_assembler
.bgez(cmpTempRegister
, 10);
1232 m_assembler
.subu(dest
, dataTempRegister
, src
);
1233 m_assembler
.xorInsn(cmpTempRegister
, dest
, dataTempRegister
);
1234 m_assembler
.bgez(cmpTempRegister
, 7);
1238 if (cond
== Signed
) {
1240 // Check if dest is negative.
1241 m_assembler
.slt(cmpTempRegister
, dest
, MIPSRegisters::zero
);
1242 return branchNotEqual(cmpTempRegister
, MIPSRegisters::zero
);
1246 return branchEqual(dest
, MIPSRegisters::zero
);
1248 if (cond
== NonZero
) {
1250 return branchNotEqual(dest
, MIPSRegisters::zero
);
1256 Jump
branchSub32(Condition cond
, Imm32 imm
, RegisterID dest
)
1258 move(imm
, immTempRegister
);
1259 return branchSub32(cond
, immTempRegister
, dest
);
1262 // Miscellaneous operations:
1271 /* We need two words for relaxation. */
1276 return Call(m_assembler
.newJmpSrc(), Call::LinkableNear
);
1281 m_assembler
.lui(MIPSRegisters::t9
, 0);
1282 m_assembler
.ori(MIPSRegisters::t9
, MIPSRegisters::t9
, 0);
1283 m_assembler
.jalr(MIPSRegisters::t9
);
1285 return Call(m_assembler
.newJmpSrc(), Call::Linkable
);
1288 Call
call(RegisterID target
)
1290 m_assembler
.jalr(target
);
1292 return Call(m_assembler
.newJmpSrc(), Call::None
);
1295 Call
call(Address address
)
1297 m_fixedWidth
= true;
1298 load32(address
, MIPSRegisters::t9
);
1299 m_assembler
.jalr(MIPSRegisters::t9
);
1301 m_fixedWidth
= false;
1302 return Call(m_assembler
.newJmpSrc(), Call::None
);
1307 m_assembler
.jr(MIPSRegisters::ra
);
1311 void set32(Condition cond
, RegisterID left
, RegisterID right
, RegisterID dest
)
1313 if (cond
== Equal
|| cond
== Zero
) {
1314 m_assembler
.xorInsn(dest
, left
, right
);
1315 m_assembler
.sltiu(dest
, dest
, 1);
1316 } else if (cond
== NotEqual
|| cond
== NonZero
) {
1317 m_assembler
.xorInsn(dest
, left
, right
);
1318 m_assembler
.sltu(dest
, MIPSRegisters::zero
, dest
);
1319 } else if (cond
== Above
)
1320 m_assembler
.sltu(dest
, right
, left
);
1321 else if (cond
== AboveOrEqual
) {
1322 m_assembler
.sltu(dest
, left
, right
);
1323 m_assembler
.xori(dest
, dest
, 1);
1324 } else if (cond
== Below
)
1325 m_assembler
.sltu(dest
, left
, right
);
1326 else if (cond
== BelowOrEqual
) {
1327 m_assembler
.sltu(dest
, right
, left
);
1328 m_assembler
.xori(dest
, dest
, 1);
1329 } else if (cond
== GreaterThan
)
1330 m_assembler
.slt(dest
, right
, left
);
1331 else if (cond
== GreaterThanOrEqual
) {
1332 m_assembler
.slt(dest
, left
, right
);
1333 m_assembler
.xori(dest
, dest
, 1);
1334 } else if (cond
== LessThan
)
1335 m_assembler
.slt(dest
, left
, right
);
1336 else if (cond
== LessThanOrEqual
) {
1337 m_assembler
.slt(dest
, right
, left
);
1338 m_assembler
.xori(dest
, dest
, 1);
1339 } else if (cond
== Overflow
) {
1341 xor cmpTemp, left, right
1342 bgez Done, cmpTemp # same sign bit -> no overflow
1344 subu cmpTemp, left, right
1345 xor cmpTemp, cmpTemp, left # diff sign bit -> overflow
1346 slt dest, cmpTemp, 0
1349 m_assembler
.xorInsn(cmpTempRegister
, left
, right
);
1350 m_assembler
.bgez(cmpTempRegister
, 4);
1351 m_assembler
.move(dest
, MIPSRegisters::zero
);
1352 m_assembler
.subu(cmpTempRegister
, left
, right
);
1353 m_assembler
.xorInsn(cmpTempRegister
, cmpTempRegister
, left
);
1354 m_assembler
.slt(dest
, cmpTempRegister
, MIPSRegisters::zero
);
1355 } else if (cond
== Signed
) {
1356 m_assembler
.subu(dest
, left
, right
);
1357 // Check if the result is negative.
1358 m_assembler
.slt(dest
, dest
, MIPSRegisters::zero
);
1362 void set32(Condition cond
, RegisterID left
, Imm32 right
, RegisterID dest
)
1364 move(right
, immTempRegister
);
1365 set32(cond
, left
, immTempRegister
, dest
);
1368 void setTest8(Condition cond
, Address address
, Imm32 mask
, RegisterID dest
)
1370 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1371 load8(address
, dataTempRegister
);
1372 if (mask
.m_value
== -1 && !m_fixedWidth
) {
1374 m_assembler
.sltiu(dest
, dataTempRegister
, 1);
1376 m_assembler
.sltu(dest
, MIPSRegisters::zero
, dataTempRegister
);
1378 move(mask
, immTempRegister
);
1379 m_assembler
.andInsn(cmpTempRegister
, dataTempRegister
,
1382 m_assembler
.sltiu(dest
, cmpTempRegister
, 1);
1384 m_assembler
.sltu(dest
, MIPSRegisters::zero
, cmpTempRegister
);
1388 void setTest32(Condition cond
, Address address
, Imm32 mask
, RegisterID dest
)
1390 ASSERT((cond
== Zero
) || (cond
== NonZero
));
1391 load32(address
, dataTempRegister
);
1392 if (mask
.m_value
== -1 && !m_fixedWidth
) {
1394 m_assembler
.sltiu(dest
, dataTempRegister
, 1);
1396 m_assembler
.sltu(dest
, MIPSRegisters::zero
, dataTempRegister
);
1398 move(mask
, immTempRegister
);
1399 m_assembler
.andInsn(cmpTempRegister
, dataTempRegister
,
1402 m_assembler
.sltiu(dest
, cmpTempRegister
, 1);
1404 m_assembler
.sltu(dest
, MIPSRegisters::zero
, cmpTempRegister
);
1408 DataLabel32
moveWithPatch(Imm32 imm
, RegisterID dest
)
1410 m_fixedWidth
= true;
1411 DataLabel32
label(this);
1413 m_fixedWidth
= false;
1417 DataLabelPtr
moveWithPatch(ImmPtr initialValue
, RegisterID dest
)
1419 m_fixedWidth
= true;
1420 DataLabelPtr
label(this);
1421 move(initialValue
, dest
);
1422 m_fixedWidth
= false;
1426 Jump
branchPtrWithPatch(Condition cond
, RegisterID left
, DataLabelPtr
& dataLabel
, ImmPtr initialRightValue
= ImmPtr(0))
1428 m_fixedWidth
= true;
1429 dataLabel
= moveWithPatch(initialRightValue
, immTempRegister
);
1430 Jump temp
= branch32(cond
, left
, immTempRegister
);
1431 m_fixedWidth
= false;
1435 Jump
branchPtrWithPatch(Condition cond
, Address left
, DataLabelPtr
& dataLabel
, ImmPtr initialRightValue
= ImmPtr(0))
1437 m_fixedWidth
= true;
1438 load32(left
, dataTempRegister
);
1439 dataLabel
= moveWithPatch(initialRightValue
, immTempRegister
);
1440 Jump temp
= branch32(cond
, dataTempRegister
, immTempRegister
);
1441 m_fixedWidth
= false;
1445 DataLabelPtr
storePtrWithPatch(ImmPtr initialValue
, ImplicitAddress address
)
1447 m_fixedWidth
= true;
1448 DataLabelPtr dataLabel
= moveWithPatch(initialValue
, dataTempRegister
);
1449 store32(dataTempRegister
, address
);
1450 m_fixedWidth
= false;
1454 DataLabelPtr
storePtrWithPatch(ImplicitAddress address
)
1456 return storePtrWithPatch(ImmPtr(0), address
);
1459 Call
tailRecursiveCall()
1461 // Like a normal call, but don't update the returned address register
1462 m_fixedWidth
= true;
1463 move(Imm32(0), MIPSRegisters::t9
);
1464 m_assembler
.jr(MIPSRegisters::t9
);
1466 m_fixedWidth
= false;
1467 return Call(m_assembler
.newJmpSrc(), Call::Linkable
);
1470 Call
makeTailRecursiveCall(Jump oldJump
)
1473 return tailRecursiveCall();
1476 void loadDouble(ImplicitAddress address
, FPRegisterID dest
)
1480 li addrTemp, address.offset
1481 addu addrTemp, addrTemp, base
1482 lwc1 dest, 0(addrTemp)
1483 lwc1 dest+1, 4(addrTemp)
1485 move(Imm32(address
.offset
), addrTempRegister
);
1486 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1487 m_assembler
.lwc1(dest
, addrTempRegister
, 0);
1488 m_assembler
.lwc1(FPRegisterID(dest
+ 1), addrTempRegister
, 4);
1490 if (address
.offset
>= -32768 && address
.offset
<= 32767
1492 m_assembler
.ldc1(dest
, address
.base
, address
.offset
);
1495 lui addrTemp, (offset + 0x8000) >> 16
1496 addu addrTemp, addrTemp, base
1497 ldc1 dest, (offset & 0xffff)(addrTemp)
1499 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
1500 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1501 m_assembler
.ldc1(dest
, addrTempRegister
, address
.offset
);
1506 void storeDouble(FPRegisterID src
, ImplicitAddress address
)
1510 li addrTemp, address.offset
1511 addu addrTemp, addrTemp, base
1512 swc1 dest, 0(addrTemp)
1513 swc1 dest+1, 4(addrTemp)
1515 move(Imm32(address
.offset
), addrTempRegister
);
1516 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1517 m_assembler
.swc1(src
, addrTempRegister
, 0);
1518 m_assembler
.swc1(FPRegisterID(src
+ 1), addrTempRegister
, 4);
1520 if (address
.offset
>= -32768 && address
.offset
<= 32767
1522 m_assembler
.sdc1(src
, address
.base
, address
.offset
);
1525 lui addrTemp, (offset + 0x8000) >> 16
1526 addu addrTemp, addrTemp, base
1527 sdc1 src, (offset & 0xffff)(addrTemp)
1529 m_assembler
.lui(addrTempRegister
, (address
.offset
+ 0x8000) >> 16);
1530 m_assembler
.addu(addrTempRegister
, addrTempRegister
, address
.base
);
1531 m_assembler
.sdc1(src
, addrTempRegister
, address
.offset
);
1536 void addDouble(FPRegisterID src
, FPRegisterID dest
)
1538 m_assembler
.addd(dest
, dest
, src
);
1541 void addDouble(Address src
, FPRegisterID dest
)
1543 loadDouble(src
, fpTempRegister
);
1544 m_assembler
.addd(dest
, dest
, fpTempRegister
);
1547 void subDouble(FPRegisterID src
, FPRegisterID dest
)
1549 m_assembler
.subd(dest
, dest
, src
);
1552 void subDouble(Address src
, FPRegisterID dest
)
1554 loadDouble(src
, fpTempRegister
);
1555 m_assembler
.subd(dest
, dest
, fpTempRegister
);
1558 void mulDouble(FPRegisterID src
, FPRegisterID dest
)
1560 m_assembler
.muld(dest
, dest
, src
);
1563 void mulDouble(Address src
, FPRegisterID dest
)
1565 loadDouble(src
, fpTempRegister
);
1566 m_assembler
.muld(dest
, dest
, fpTempRegister
);
1569 void convertInt32ToDouble(RegisterID src
, FPRegisterID dest
)
1571 m_assembler
.mtc1(src
, fpTempRegister
);
1572 m_assembler
.cvtdw(dest
, fpTempRegister
);
1575 void insertRelaxationWords()
1577 /* We need four words for relaxation. */
1578 m_assembler
.beq(MIPSRegisters::zero
, MIPSRegisters::zero
, 3); // Jump over nops;
1586 m_assembler
.appendJump();
1589 insertRelaxationWords();
1590 return Jump(m_assembler
.newJmpSrc());
1595 m_assembler
.appendJump();
1598 insertRelaxationWords();
1599 return Jump(m_assembler
.newJmpSrc());
1602 Jump
branchEqual(RegisterID rs
, RegisterID rt
)
1604 m_assembler
.appendJump();
1605 m_assembler
.beq(rs
, rt
, 0);
1607 insertRelaxationWords();
1608 return Jump(m_assembler
.newJmpSrc());
1611 Jump
branchNotEqual(RegisterID rs
, RegisterID rt
)
1613 m_assembler
.appendJump();
1614 m_assembler
.bne(rs
, rt
, 0);
1616 insertRelaxationWords();
1617 return Jump(m_assembler
.newJmpSrc());
1620 Jump
branchDouble(DoubleCondition cond
, FPRegisterID left
, FPRegisterID right
)
1622 if (cond
== DoubleEqual
) {
1623 m_assembler
.ceqd(left
, right
);
1624 return branchTrue();
1626 if (cond
== DoubleNotEqual
) {
1627 m_assembler
.ceqd(left
, right
);
1628 return branchFalse(); // false
1630 if (cond
== DoubleGreaterThan
) {
1631 m_assembler
.cngtd(left
, right
);
1632 return branchFalse(); // false
1634 if (cond
== DoubleGreaterThanOrEqual
) {
1635 m_assembler
.cnged(right
, left
);
1636 return branchFalse(); // false
1638 if (cond
== DoubleLessThan
) {
1639 m_assembler
.cltd(left
, right
);
1640 return branchTrue();
1642 if (cond
== DoubleLessThanOrEqual
) {
1643 m_assembler
.cled(left
, right
);
1644 return branchTrue();
1646 if (cond
== DoubleEqualOrUnordered
) {
1647 m_assembler
.cueqd(left
, right
);
1648 return branchTrue();
1650 if (cond
== DoubleGreaterThanOrUnordered
) {
1651 m_assembler
.coled(left
, right
);
1652 return branchFalse(); // false
1654 if (cond
== DoubleGreaterThanOrEqualOrUnordered
) {
1655 m_assembler
.coltd(left
, right
);
1656 return branchFalse(); // false
1658 if (cond
== DoubleLessThanOrUnordered
) {
1659 m_assembler
.cultd(left
, right
);
1660 return branchTrue();
1662 if (cond
== DoubleLessThanOrEqualOrUnordered
) {
1663 m_assembler
.culed(left
, right
);
1664 return branchTrue();
1671 // Truncates 'src' to an integer, and places the resulting 'dest'.
1672 // If the result is not representable as a 32 bit value, branch.
1673 // May also branch for some values that are representable in 32 bits
1674 // (specifically, in this case, INT_MAX 0x7fffffff).
1675 Jump
branchTruncateDoubleToInt32(FPRegisterID src
, RegisterID dest
)
1677 m_assembler
.truncwd(fpTempRegister
, src
);
1678 m_assembler
.mfc1(dest
, fpTempRegister
);
1679 return branch32(Equal
, dest
, Imm32(0x7fffffff));
1683 // If m_fixedWidth is true, we will generate a fixed number of instructions.
1684 // Otherwise, we can emit any number of instructions.
1687 friend class LinkBuffer
;
1688 friend class RepatchBuffer
;
1690 static void linkCall(void* code
, Call call
, FunctionPtr function
)
1692 MIPSAssembler::linkCall(code
, call
.m_jmp
, function
.value());
1695 static void repatchCall(CodeLocationCall call
, CodeLocationLabel destination
)
1697 MIPSAssembler::relinkCall(call
.dataLocation(), destination
.executableAddress());
1700 static void repatchCall(CodeLocationCall call
, FunctionPtr destination
)
1702 MIPSAssembler::relinkCall(call
.dataLocation(), destination
.executableAddress());
1709 #endif // ENABLE(ASSEMBLER) && CPU(MIPS)
1711 #endif // MacroAssemblerMIPS_h