3f270fedbff7ce300436f6ee997bbbeec4c700f3
[WebKit-https.git] / Source / JavaScriptCore / assembler / MacroAssemblerMIPS.h
1 /*
2  * Copyright (C) 2008-2018 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 MIPS Technologies, Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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.
25  */
26
27 #pragma once
28
29 #if ENABLE(ASSEMBLER) && CPU(MIPS)
30
31 #include "MIPSAssembler.h"
32 #include "AbstractMacroAssembler.h"
33
34 namespace JSC {
35
36 using Assembler = TARGET_ASSEMBLER;
37
38 class MacroAssemblerMIPS : public AbstractMacroAssembler<Assembler> {
39 public:
40     typedef MIPSRegisters::FPRegisterID FPRegisterID;
41     static const unsigned numGPRs = 32;
42     static const unsigned numFPRs = 32;
43
44     MacroAssemblerMIPS()
45         : m_fixedWidth(false)
46     {
47     }
48
49     static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value)
50     {
51         return value >= -2147483647 - 1 && value <= 2147483647;
52     }
53
54     static const Scale ScalePtr = TimesFour;
55
56     // For storing immediate number
57     static const RegisterID immTempRegister = MIPSRegisters::t0;
58     // For storing data loaded from the memory
59     static const RegisterID dataTempRegister = MIPSRegisters::t1;
60     // For storing address base
61     static const RegisterID addrTempRegister = MIPSRegisters::t7;
62     // For storing compare result
63     static const RegisterID cmpTempRegister = MIPSRegisters::t8;
64
65     // FP temp register
66     static const FPRegisterID fpTempRegister = MIPSRegisters::f16;
67
68     static const int MaximumCompactPtrAlignedAddressOffset = 0x7FFFFFFF;
69
70     enum RelationalCondition {
71         Equal,
72         NotEqual,
73         Above,
74         AboveOrEqual,
75         Below,
76         BelowOrEqual,
77         GreaterThan,
78         GreaterThanOrEqual,
79         LessThan,
80         LessThanOrEqual
81     };
82
83     enum ResultCondition {
84         Overflow,
85         Signed,
86         PositiveOrZero,
87         Zero,
88         NonZero
89     };
90
91     enum DoubleCondition {
92         DoubleEqual,
93         DoubleNotEqual,
94         DoubleGreaterThan,
95         DoubleGreaterThanOrEqual,
96         DoubleLessThan,
97         DoubleLessThanOrEqual,
98         DoubleEqualOrUnordered,
99         DoubleNotEqualOrUnordered,
100         DoubleGreaterThanOrUnordered,
101         DoubleGreaterThanOrEqualOrUnordered,
102         DoubleLessThanOrUnordered,
103         DoubleLessThanOrEqualOrUnordered
104     };
105
106     static const RegisterID stackPointerRegister = MIPSRegisters::sp;
107     static const RegisterID framePointerRegister = MIPSRegisters::fp;
108     static const RegisterID returnAddressRegister = MIPSRegisters::ra;
109
110     // Integer arithmetic operations:
111     //
112     // Operations are typically two operand - operation(source, srcDst)
113     // For many operations the source may be an TrustedImm32, the srcDst operand
114     // may often be a memory location (explictly described using an Address
115     // object).
116
117     void add32(RegisterID src, RegisterID dest)
118     {
119         m_assembler.addu(dest, dest, src);
120     }
121
122     void add32(RegisterID op1, RegisterID op2, RegisterID dest)
123     {
124         m_assembler.addu(dest, op1, op2);
125     }
126
127     void add32(TrustedImm32 imm, RegisterID dest)
128     {
129         add32(imm, dest, dest);
130     }
131
132     void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
133     {
134         if (imm.m_value >= -32768 && imm.m_value <= 32767
135             && !m_fixedWidth) {
136             /*
137               addiu     dest, src, imm
138             */
139             m_assembler.addiu(dest, src, imm.m_value);
140         } else {
141             /*
142               li        immTemp, imm
143               addu      dest, src, immTemp
144             */
145             move(imm, immTempRegister);
146             m_assembler.addu(dest, src, immTempRegister);
147         }
148     }
149
150     void add32(RegisterID src, TrustedImm32 imm, RegisterID dest)
151     {
152         add32(imm, src, dest);
153     }
154
155     void add32(TrustedImm32 imm, Address address)
156     {
157         if (address.offset >= -32768 && address.offset <= 32767
158             && !m_fixedWidth) {
159             /*
160               lw        dataTemp, offset(base)
161               li        immTemp, imm
162               addu      dataTemp, dataTemp, immTemp
163               sw        dataTemp, offset(base)
164             */
165             m_assembler.lw(dataTempRegister, address.base, address.offset);
166             if (imm.m_value >= -32768 && imm.m_value <= 32767
167                 && !m_fixedWidth)
168                 m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value);
169             else {
170                 move(imm, immTempRegister);
171                 m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister);
172             }
173             m_assembler.sw(dataTempRegister, address.base, address.offset);
174         } else {
175             /*
176               lui       addrTemp, (offset + 0x8000) >> 16
177               addu      addrTemp, addrTemp, base
178               lw        dataTemp, (offset & 0xffff)(addrTemp)
179               li        immtemp, imm
180               addu      dataTemp, dataTemp, immTemp
181               sw        dataTemp, (offset & 0xffff)(addrTemp)
182             */
183             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
184             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
185             m_assembler.lw(dataTempRegister, addrTempRegister, address.offset);
186
187             if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth)
188                 m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value);
189             else {
190                 move(imm, immTempRegister);
191                 m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister);
192             }
193             m_assembler.sw(dataTempRegister, addrTempRegister, address.offset);
194         }
195     }
196
197     void add32(Address src, RegisterID dest)
198     {
199         load32(src, dataTempRegister);
200         add32(dataTempRegister, dest);
201     }
202
203     void add32(AbsoluteAddress src, RegisterID dest)
204     {
205         load32(src.m_ptr, dataTempRegister);
206         add32(dataTempRegister, dest);
207     }
208
209     void add32(RegisterID src, Address dest)
210     {
211         if (dest.offset >= -32768 && dest.offset <= 32767 && !m_fixedWidth) {
212             /*
213               lw        dataTemp, offset(base)
214               addu      dataTemp, dataTemp, src
215               sw        dataTemp, offset(base)
216             */
217             m_assembler.lw(dataTempRegister, dest.base, dest.offset);
218             m_assembler.addu(dataTempRegister, dataTempRegister, src);
219             m_assembler.sw(dataTempRegister, dest.base, dest.offset);
220         } else {
221             /*
222               lui       addrTemp, (offset + 0x8000) >> 16
223               addu      addrTemp, addrTemp, base
224               lw        dataTemp, (offset & 0xffff)(addrTemp)
225               addu      dataTemp, dataTemp, src
226               sw        dataTemp, (offset & 0xffff)(addrTemp)
227             */
228             m_assembler.lui(addrTempRegister, (dest.offset + 0x8000) >> 16);
229             m_assembler.addu(addrTempRegister, addrTempRegister, dest.base);
230             m_assembler.lw(dataTempRegister, addrTempRegister, dest.offset);
231             m_assembler.addu(dataTempRegister, dataTempRegister, src);
232             m_assembler.sw(dataTempRegister, addrTempRegister, dest.offset);
233         }
234     }
235
236     void add32(TrustedImm32 imm, AbsoluteAddress address)
237     {
238         /*
239            li   addrTemp, address
240            li   immTemp, imm
241            lw   cmpTemp, 0(addrTemp)
242            addu dataTemp, cmpTemp, immTemp
243            sw   dataTemp, 0(addrTemp)
244         */
245         move(TrustedImmPtr(address.m_ptr), addrTempRegister);
246         m_assembler.lw(cmpTempRegister, addrTempRegister, 0);
247         if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth)
248             m_assembler.addiu(dataTempRegister, cmpTempRegister, imm.m_value);
249         else {
250             move(imm, immTempRegister);
251             m_assembler.addu(dataTempRegister, cmpTempRegister, immTempRegister);
252         }
253         m_assembler.sw(dataTempRegister, addrTempRegister, 0);
254     }
255
256     void add64(TrustedImm32 imm, AbsoluteAddress address)
257     {
258         /*
259             add32(imm, address)
260             sltu  immTemp, dataTemp, cmpTemp    # set carry-in bit
261             lw    dataTemp, 4(addrTemp)
262             addiu dataTemp, imm.m_value >> 31 ? -1 : 0
263             addu  dataTemp, dataTemp, immTemp
264             sw    dataTemp, 4(addrTemp)
265         */
266         add32(imm, address);
267         m_assembler.sltu(immTempRegister, dataTempRegister, cmpTempRegister);
268         m_assembler.lw(dataTempRegister, addrTempRegister, 4);
269         if (imm.m_value >> 31)
270             m_assembler.addiu(dataTempRegister, dataTempRegister, -1);
271         m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister);
272         m_assembler.sw(dataTempRegister, addrTempRegister, 4);
273     }
274
275     void getEffectiveAddress(BaseIndex address, RegisterID dest)
276     {
277         m_assembler.sll(addrTempRegister, address.index, address.scale);
278         m_assembler.addu(dest, addrTempRegister, address.base);
279         if (address.offset)
280             add32(TrustedImm32(address.offset), dest);
281     }
282
283     void and32(Address src, RegisterID dest)
284     {
285         load32(src, dataTempRegister);
286         and32(dataTempRegister, dest);
287     }
288
289     void and32(RegisterID src, RegisterID dest)
290     {
291         m_assembler.andInsn(dest, dest, src);
292     }
293
294     void and32(RegisterID op1, RegisterID op2, RegisterID dest)
295     {
296         m_assembler.andInsn(dest, op1, op2);
297     }
298
299     void and32(TrustedImm32 imm, RegisterID dest)
300     {
301         if (!imm.m_value && !m_fixedWidth)
302             move(MIPSRegisters::zero, dest);
303         else if (imm.m_value > 0 && imm.m_value <= 65535 && !m_fixedWidth)
304             m_assembler.andi(dest, dest, imm.m_value);
305         else {
306             /*
307               li        immTemp, imm
308               and       dest, dest, immTemp
309             */
310             move(imm, immTempRegister);
311             m_assembler.andInsn(dest, dest, immTempRegister);
312         }
313     }
314
315     void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
316     {
317         if (!imm.m_value && !m_fixedWidth)
318             move(MIPSRegisters::zero, dest);
319         else if (imm.m_value > 0 && imm.m_value <= 65535 && !m_fixedWidth)
320             m_assembler.andi(dest, src, imm.m_value);
321         else {
322             move(imm, immTempRegister);
323             m_assembler.andInsn(dest, src, immTempRegister);
324         }
325     }
326
327     void countLeadingZeros32(RegisterID src, RegisterID dest)
328     {
329 #if WTF_MIPS_ISA_AT_LEAST(32)
330         m_assembler.clz(dest, src);
331 #else
332         static_assert(false, "CLZ opcode is not available for this ISA");
333 #endif
334     }
335
336     void lshift32(RegisterID shiftAmount, RegisterID dest)
337     {
338         m_assembler.sllv(dest, dest, shiftAmount);
339     }
340
341     void lshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
342     {
343         m_assembler.sllv(dest, src, shiftAmount);
344     }
345
346     void lshift32(TrustedImm32 imm, RegisterID dest)
347     {
348         move(imm, immTempRegister);
349         m_assembler.sllv(dest, dest, immTempRegister);
350     }
351
352     void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
353     {
354         move(imm, immTempRegister);
355         m_assembler.sllv(dest, src, immTempRegister);
356     }
357
358     void mul32(RegisterID src, RegisterID dest)
359     {
360         m_assembler.mul(dest, dest, src);
361     }
362
363     void mul32(RegisterID op1, RegisterID op2, RegisterID dest)
364     {
365         m_assembler.mul(dest, op1, op2);
366     }
367
368     void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
369     {
370         if (!imm.m_value && !m_fixedWidth)
371             move(MIPSRegisters::zero, dest);
372         else if (imm.m_value == 1 && !m_fixedWidth)
373             move(src, dest);
374         else {
375             /*
376                 li      dataTemp, imm
377                 mul     dest, src, dataTemp
378             */
379             move(imm, dataTempRegister);
380             m_assembler.mul(dest, src, dataTempRegister);
381         }
382     }
383
384     void neg32(RegisterID srcDest)
385     {
386         m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest);
387     }
388
389     void neg32(RegisterID src, RegisterID dest)
390     {
391         m_assembler.subu(dest, MIPSRegisters::zero, src);
392     }
393
394     void or32(RegisterID src, RegisterID dest)
395     {
396         m_assembler.orInsn(dest, dest, src);
397     }
398
399     void or32(RegisterID op1, RegisterID op2, RegisterID dest)
400     {
401         m_assembler.orInsn(dest, op1, op2);
402     }
403
404     void or32(TrustedImm32 imm, AbsoluteAddress dest)
405     {
406         if (!imm.m_value && !m_fixedWidth)
407             return;
408
409         // TODO: Swap dataTempRegister and immTempRegister usage
410         load32(dest.m_ptr, immTempRegister);
411         or32(imm, immTempRegister);
412         store32(immTempRegister, dest.m_ptr);
413     }
414
415     void or32(TrustedImm32 imm, RegisterID dest)
416     {
417         if (!imm.m_value && !m_fixedWidth)
418             return;
419
420         if (imm.m_value > 0 && imm.m_value <= 65535
421             && !m_fixedWidth) {
422             m_assembler.ori(dest, dest, imm.m_value);
423             return;
424         }
425
426         /*
427             li      dataTemp, imm
428             or      dest, dest, dataTemp
429         */
430         move(imm, dataTempRegister);
431         m_assembler.orInsn(dest, dest, dataTempRegister);
432     }
433
434     void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
435     {
436         if (!imm.m_value && !m_fixedWidth) {
437             move(src, dest);
438             return;
439         }
440
441         if (imm.m_value > 0 && imm.m_value <= 65535 && !m_fixedWidth) {
442             m_assembler.ori(dest, src, imm.m_value);
443             return;
444         }
445
446         /*
447             li      dataTemp, imm
448             or      dest, src, dataTemp
449         */
450         move(imm, dataTempRegister);
451         m_assembler.orInsn(dest, src, dataTempRegister);
452     }
453
454     void or32(RegisterID src, AbsoluteAddress dest)
455     {
456         load32(dest.m_ptr, dataTempRegister);
457         m_assembler.orInsn(dataTempRegister, dataTempRegister, src);
458         store32(dataTempRegister, dest.m_ptr);
459     }
460
461     void or32(TrustedImm32 imm, Address address)
462     {
463         if (address.offset >= -32768 && address.offset <= 32767
464             && !m_fixedWidth) {
465             /*
466               lw        dataTemp, offset(base)
467               li        immTemp, imm
468               or        dataTemp, dataTemp, immTemp
469               sw        dataTemp, offset(base)
470             */
471             m_assembler.lw(dataTempRegister, address.base, address.offset);
472             if (imm.m_value >= 0 && imm.m_value <= 65535 && !m_fixedWidth)
473                 m_assembler.ori(dataTempRegister, dataTempRegister, imm.m_value);
474             else {
475                 move(imm, immTempRegister);
476                 m_assembler.orInsn(dataTempRegister, dataTempRegister, immTempRegister);
477             }
478             m_assembler.sw(dataTempRegister, address.base, address.offset);
479         } else {
480             /*
481               lui       addrTemp, (offset + 0x8000) >> 16
482               addu      addrTemp, addrTemp, base
483               lw        dataTemp, (offset & 0xffff)(addrTemp)
484               li        immtemp, imm
485               or        dataTemp, dataTemp, immTemp
486               sw        dataTemp, (offset & 0xffff)(addrTemp)
487             */
488             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
489             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
490             m_assembler.lw(dataTempRegister, addrTempRegister, address.offset);
491
492             if (imm.m_value >= 0 && imm.m_value <= 65535 && !m_fixedWidth)
493                 m_assembler.ori(dataTempRegister, dataTempRegister, imm.m_value);
494             else {
495                 move(imm, immTempRegister);
496                 m_assembler.orInsn(dataTempRegister, dataTempRegister, immTempRegister);
497             }
498             m_assembler.sw(dataTempRegister, addrTempRegister, address.offset);
499         }
500     }
501
502     void rshift32(RegisterID shiftAmount, RegisterID dest)
503     {
504         m_assembler.srav(dest, dest, shiftAmount);
505     }
506
507     void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
508     {
509         m_assembler.srav(dest, src, shiftAmount);
510     }
511
512     void rshift32(TrustedImm32 imm, RegisterID dest)
513     {
514         m_assembler.sra(dest, dest, imm.m_value);
515     }
516
517     void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
518     {
519         m_assembler.sra(dest, src, imm.m_value);
520     }
521
522     void urshift32(RegisterID shiftAmount, RegisterID dest)
523     {
524         m_assembler.srlv(dest, dest, shiftAmount);
525     }
526
527     void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
528     {
529         m_assembler.srlv(dest, src, shiftAmount);
530     }
531
532     void urshift32(TrustedImm32 imm, RegisterID dest)
533     {
534         m_assembler.srl(dest, dest, imm.m_value);
535     }
536
537     void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
538     {
539         m_assembler.srl(dest, src, imm.m_value);
540     }
541
542     void sub32(RegisterID src, RegisterID dest)
543     {
544         m_assembler.subu(dest, dest, src);
545     }
546
547     void sub32(RegisterID op1, RegisterID op2, RegisterID dest)
548     {
549         m_assembler.subu(dest, op1, op2);
550     }
551
552     void sub32(TrustedImm32 imm, RegisterID dest)
553     {
554         if (imm.m_value >= -32767 && imm.m_value <= 32768
555             && !m_fixedWidth) {
556             /*
557               addiu     dest, src, imm
558             */
559             m_assembler.addiu(dest, dest, -imm.m_value);
560         } else {
561             /*
562               li        immTemp, imm
563               subu      dest, src, immTemp
564             */
565             move(imm, immTempRegister);
566             m_assembler.subu(dest, dest, immTempRegister);
567         }
568     }
569
570     void sub32(RegisterID src, TrustedImm32 imm, RegisterID dest)
571     {
572         if (imm.m_value >= -32767 && imm.m_value <= 32768
573             && !m_fixedWidth) {
574             /*
575               addiu     dest, src, imm
576             */
577             m_assembler.addiu(dest, src, -imm.m_value);
578         } else {
579             /*
580               li        immTemp, imm
581               subu      dest, src, immTemp
582             */
583             move(imm, immTempRegister);
584             m_assembler.subu(dest, src, immTempRegister);
585         }
586     }
587
588     void sub32(TrustedImm32 imm, Address address)
589     {
590         if (address.offset >= -32768 && address.offset <= 32767
591             && !m_fixedWidth) {
592             /*
593               lw        dataTemp, offset(base)
594               li        immTemp, imm
595               subu      dataTemp, dataTemp, immTemp
596               sw        dataTemp, offset(base)
597             */
598             m_assembler.lw(dataTempRegister, address.base, address.offset);
599             if (imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth)
600                 m_assembler.addiu(dataTempRegister, dataTempRegister, -imm.m_value);
601             else {
602                 move(imm, immTempRegister);
603                 m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister);
604             }
605             m_assembler.sw(dataTempRegister, address.base, address.offset);
606         } else {
607             /*
608               lui       addrTemp, (offset + 0x8000) >> 16
609               addu      addrTemp, addrTemp, base
610               lw        dataTemp, (offset & 0xffff)(addrTemp)
611               li        immtemp, imm
612               subu      dataTemp, dataTemp, immTemp
613               sw        dataTemp, (offset & 0xffff)(addrTemp)
614             */
615             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
616             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
617             m_assembler.lw(dataTempRegister, addrTempRegister, address.offset);
618
619             if (imm.m_value >= -32767 && imm.m_value <= 32768
620                 && !m_fixedWidth)
621                 m_assembler.addiu(dataTempRegister, dataTempRegister, -imm.m_value);
622             else {
623                 move(imm, immTempRegister);
624                 m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister);
625             }
626             m_assembler.sw(dataTempRegister, addrTempRegister, address.offset);
627         }
628     }
629
630     void sub32(Address src, RegisterID dest)
631     {
632         load32(src, dataTempRegister);
633         sub32(dataTempRegister, dest);
634     }
635
636     void sub32(TrustedImm32 imm, AbsoluteAddress address)
637     {
638         /*
639            li   addrTemp, address
640            li   immTemp, imm
641            lw   dataTemp, 0(addrTemp)
642            subu dataTemp, dataTemp, immTemp
643            sw   dataTemp, 0(addrTemp)
644         */
645         move(TrustedImmPtr(address.m_ptr), addrTempRegister);
646         m_assembler.lw(dataTempRegister, addrTempRegister, 0);
647
648         if (imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth)
649             m_assembler.addiu(dataTempRegister, dataTempRegister, -imm.m_value);
650         else {
651             move(imm, immTempRegister);
652             m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister);
653         }
654         m_assembler.sw(dataTempRegister, addrTempRegister, 0);
655     }
656
657     void xor32(RegisterID src, RegisterID dest)
658     {
659         m_assembler.xorInsn(dest, dest, src);
660     }
661
662     void xor32(RegisterID op1, RegisterID op2, RegisterID dest)
663     {
664         m_assembler.xorInsn(dest, op1, op2);
665     }
666
667     void xor32(Address src, RegisterID dest)
668     {
669         load32(src, dataTempRegister);
670         xor32(dataTempRegister, dest);
671     }
672
673     void xor32(TrustedImm32 imm, RegisterID dest)
674     {
675         if (imm.m_value == -1) {
676             m_assembler.nor(dest, dest, MIPSRegisters::zero);
677             return;
678         }
679
680         /*
681             li  immTemp, imm
682             xor dest, dest, immTemp
683         */
684         move(imm, immTempRegister);
685         m_assembler.xorInsn(dest, dest, immTempRegister);
686     }
687
688     void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
689     {
690         if (imm.m_value == -1) {
691             m_assembler.nor(dest, src, MIPSRegisters::zero);
692             return;
693         }
694
695         /*
696             li  immTemp, imm
697             xor dest, dest, immTemp
698         */
699         move(imm, immTempRegister);
700         m_assembler.xorInsn(dest, src, immTempRegister);
701     }
702
703     void sqrtDouble(FPRegisterID src, FPRegisterID dst)
704     {
705         m_assembler.sqrtd(dst, src);
706     }
707
708     void absDouble(FPRegisterID src, FPRegisterID dst)
709     {
710         m_assembler.absd(dst, src);
711     }
712
713     NO_RETURN_DUE_TO_CRASH void ceilDouble(FPRegisterID, FPRegisterID)
714     {
715         ASSERT(!supportsFloatingPointRounding());
716         CRASH();
717     }
718
719     NO_RETURN_DUE_TO_CRASH void floorDouble(FPRegisterID, FPRegisterID)
720     {
721         ASSERT(!supportsFloatingPointRounding());
722         CRASH();
723     }
724
725     NO_RETURN_DUE_TO_CRASH void roundTowardZeroDouble(FPRegisterID, FPRegisterID)
726     {
727         ASSERT(!supportsFloatingPointRounding());
728         CRASH();
729     }
730
731     ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest)
732     {
733         ConvertibleLoadLabel result(this);
734         /*
735             lui     addrTemp, (offset + 0x8000) >> 16
736             addu    addrTemp, addrTemp, base
737             lw      dest, (offset & 0xffff)(addrTemp)
738         */
739         m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
740         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
741         m_assembler.lw(dest, addrTempRegister, address.offset);
742         return result;
743     }
744
745     // Memory access operations:
746     //
747     // Loads are of the form load(address, destination) and stores of the form
748     // store(source, address). The source for a store may be an TrustedImm32. Address
749     // operand objects to loads and store will be implicitly constructed if a
750     // register is passed.
751
752     /* Need to use zero-extened load byte for load8.  */
753     void load8(ImplicitAddress address, RegisterID dest)
754     {
755         if (address.offset >= -32768 && address.offset <= 32767
756             && !m_fixedWidth)
757             m_assembler.lbu(dest, address.base, address.offset);
758         else {
759             /*
760                 lui     addrTemp, (offset + 0x8000) >> 16
761                 addu    addrTemp, addrTemp, base
762                 lbu     dest, (offset & 0xffff)(addrTemp)
763               */
764             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
765             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
766             m_assembler.lbu(dest, addrTempRegister, address.offset);
767         }
768     }
769
770     void load8(BaseIndex address, RegisterID dest)
771     {
772         if (address.offset >= -32768 && address.offset <= 32767
773             && !m_fixedWidth) {
774             /*
775              sll     addrTemp, address.index, address.scale
776              addu    addrTemp, addrTemp, address.base
777              lbu     dest, address.offset(addrTemp)
778              */
779             m_assembler.sll(addrTempRegister, address.index, address.scale);
780             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
781             m_assembler.lbu(dest, addrTempRegister, address.offset);
782         } else {
783             /*
784              sll     addrTemp, address.index, address.scale
785              addu    addrTemp, addrTemp, address.base
786              lui     immTemp, (address.offset + 0x8000) >> 16
787              addu    addrTemp, addrTemp, immTemp
788              lbu     dest, (address.offset & 0xffff)(at)
789              */
790             m_assembler.sll(addrTempRegister, address.index, address.scale);
791             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
792             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
793             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
794             m_assembler.lbu(dest, addrTempRegister, address.offset);
795         }
796     }
797
798     ALWAYS_INLINE void load8(AbsoluteAddress address, RegisterID dest)
799     {
800         load8(address.m_ptr, dest);
801     }
802
803     void load8(const void* address, RegisterID dest)
804     {
805         /*
806             li  addrTemp, address
807             lbu dest, 0(addrTemp)
808         */
809         move(TrustedImmPtr(address), addrTempRegister);
810         m_assembler.lbu(dest, addrTempRegister, 0);
811     }
812
813     void load8SignedExtendTo32(ImplicitAddress address, RegisterID dest)
814     {
815         if (address.offset >= -32768 && address.offset <= 32767
816             && !m_fixedWidth)
817             m_assembler.lb(dest, address.base, address.offset);
818         else {
819             /*
820                 lui     addrTemp, (offset + 0x8000) >> 16
821                 addu    addrTemp, addrTemp, base
822                 lb      dest, (offset & 0xffff)(addrTemp)
823               */
824             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
825             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
826             m_assembler.lb(dest, addrTempRegister, address.offset);
827         }
828     }
829
830     void load8SignedExtendTo32(BaseIndex address, RegisterID dest)
831     {
832         if (address.offset >= -32768 && address.offset <= 32767
833             && !m_fixedWidth) {
834             /*
835                 sll     addrTemp, address.index, address.scale
836                 addu    addrTemp, addrTemp, address.base
837                 lb      dest, address.offset(addrTemp)
838             */
839             m_assembler.sll(addrTempRegister, address.index, address.scale);
840             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
841             m_assembler.lb(dest, addrTempRegister, address.offset);
842         } else {
843             /*
844                 sll     addrTemp, address.index, address.scale
845                 addu    addrTemp, addrTemp, address.base
846                 lui     immTemp, (address.offset + 0x8000) >> 16
847                 addu    addrTemp, addrTemp, immTemp
848                 lb     dest, (address.offset & 0xffff)(at)
849             */
850             m_assembler.sll(addrTempRegister, address.index, address.scale);
851             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
852             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
853             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
854             m_assembler.lb(dest, addrTempRegister, address.offset);
855         }
856     }
857
858     ALWAYS_INLINE void load8SignedExtendTo32(AbsoluteAddress address, RegisterID dest)
859     {
860         load8SignedExtendTo32(address.m_ptr, dest);
861     }
862
863     void load8SignedExtendTo32(const void* address, RegisterID dest)
864     {
865         /*
866             li  addrTemp, address
867             lb  dest, 0(addrTemp)
868         */
869         move(TrustedImmPtr(address), addrTempRegister);
870         m_assembler.lb(dest, addrTempRegister, 0);
871     }
872
873
874     void load32(ImplicitAddress address, RegisterID dest)
875     {
876         if (address.offset >= -32768 && address.offset <= 32767
877             && !m_fixedWidth)
878             m_assembler.lw(dest, address.base, address.offset);
879         else {
880             /*
881                 lui     addrTemp, (offset + 0x8000) >> 16
882                 addu    addrTemp, addrTemp, base
883                 lw      dest, (offset & 0xffff)(addrTemp)
884               */
885             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
886             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
887             m_assembler.lw(dest, addrTempRegister, address.offset);
888         }
889     }
890
891     void load32(BaseIndex address, RegisterID dest)
892     {
893         if (address.offset >= -32768 && address.offset <= 32767
894             && !m_fixedWidth) {
895             /*
896                 sll     addrTemp, address.index, address.scale
897                 addu    addrTemp, addrTemp, address.base
898                 lw      dest, address.offset(addrTemp)
899             */
900             m_assembler.sll(addrTempRegister, address.index, address.scale);
901             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
902             m_assembler.lw(dest, addrTempRegister, address.offset);
903         } else {
904             /*
905                 sll     addrTemp, address.index, address.scale
906                 addu    addrTemp, addrTemp, address.base
907                 lui     immTemp, (address.offset + 0x8000) >> 16
908                 addu    addrTemp, addrTemp, immTemp
909                 lw      dest, (address.offset & 0xffff)(at)
910             */
911             m_assembler.sll(addrTempRegister, address.index, address.scale);
912             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
913             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
914             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
915             m_assembler.lw(dest, addrTempRegister, address.offset);
916         }
917     }
918
919     void load16Unaligned(BaseIndex address, RegisterID dest)
920     {
921         if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) {
922             /*
923                 sll     addrtemp, address.index, address.scale
924                 addu    addrtemp, addrtemp, address.base
925                 lbu     immTemp, address.offset+x(addrtemp) (x=0 for LE, x=1 for BE)
926                 lbu     dest, address.offset+x(addrtemp)    (x=1 for LE, x=0 for BE)
927                 sll     dest, dest, 8
928                 or      dest, dest, immTemp
929             */
930             m_assembler.sll(addrTempRegister, address.index, address.scale);
931             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
932 #if CPU(BIG_ENDIAN)
933             m_assembler.lbu(immTempRegister, addrTempRegister, address.offset + 1);
934             m_assembler.lbu(dest, addrTempRegister, address.offset);
935 #else
936             m_assembler.lbu(immTempRegister, addrTempRegister, address.offset);
937             m_assembler.lbu(dest, addrTempRegister, address.offset + 1);
938 #endif
939             m_assembler.sll(dest, dest, 8);
940             m_assembler.orInsn(dest, dest, immTempRegister);
941         } else {
942             /*
943                 sll     addrTemp, address.index, address.scale
944                 addu    addrTemp, addrTemp, address.base
945                 lui     immTemp, address.offset >> 16
946                 ori     immTemp, immTemp, address.offset & 0xffff
947                 addu    addrTemp, addrTemp, immTemp
948                 lbu     immTemp, x(addrtemp) (x=0 for LE, x=1 for BE)
949                 lbu     dest, x(addrtemp)    (x=1 for LE, x=0 for BE)
950                 sll     dest, dest, 8
951                 or      dest, dest, immTemp
952             */
953             m_assembler.sll(addrTempRegister, address.index, address.scale);
954             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
955             m_assembler.lui(immTempRegister, address.offset >> 16);
956             m_assembler.ori(immTempRegister, immTempRegister, address.offset);
957             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
958 #if CPU(BIG_ENDIAN)
959             m_assembler.lbu(immTempRegister, addrTempRegister, 1);
960             m_assembler.lbu(dest, addrTempRegister, 0);
961 #else
962             m_assembler.lbu(immTempRegister, addrTempRegister, 0);
963             m_assembler.lbu(dest, addrTempRegister, 1);
964 #endif
965             m_assembler.sll(dest, dest, 8);
966             m_assembler.orInsn(dest, dest, immTempRegister);
967         }
968     }
969
970     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
971     {
972         if (address.offset >= -32768 && address.offset <= 32764
973             && !m_fixedWidth) {
974             /*
975                 sll     addrTemp, address.index, address.scale
976                 addu    addrTemp, addrTemp, address.base
977                 (Big-Endian)
978                 lwl     dest, address.offset(addrTemp)
979                 lwr     dest, address.offset+3(addrTemp)
980                 (Little-Endian)
981                 lwl     dest, address.offset+3(addrTemp)
982                 lwr     dest, address.offset(addrTemp)
983             */
984             m_assembler.sll(addrTempRegister, address.index, address.scale);
985             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
986 #if CPU(BIG_ENDIAN)
987             m_assembler.lwl(dest, addrTempRegister, address.offset);
988             m_assembler.lwr(dest, addrTempRegister, address.offset + 3);
989 #else
990             m_assembler.lwl(dest, addrTempRegister, address.offset + 3);
991             m_assembler.lwr(dest, addrTempRegister, address.offset);
992
993 #endif
994         } else {
995             /*
996                 sll     addrTemp, address.index, address.scale
997                 addu    addrTemp, addrTemp, address.base
998                 lui     immTemp, address.offset >> 16
999                 ori     immTemp, immTemp, address.offset & 0xffff
1000                 addu    addrTemp, addrTemp, immTemp
1001                 (Big-Endian)
1002                 lw      dest, 0(at)
1003                 lw      dest, 3(at)
1004                 (Little-Endian)
1005                 lw      dest, 3(at)
1006                 lw      dest, 0(at)
1007             */
1008             m_assembler.sll(addrTempRegister, address.index, address.scale);
1009             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1010             m_assembler.lui(immTempRegister, address.offset >> 16);
1011             m_assembler.ori(immTempRegister, immTempRegister, address.offset);
1012             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
1013 #if CPU(BIG_ENDIAN)
1014             m_assembler.lwl(dest, addrTempRegister, 0);
1015             m_assembler.lwr(dest, addrTempRegister, 3);
1016 #else
1017             m_assembler.lwl(dest, addrTempRegister, 3);
1018             m_assembler.lwr(dest, addrTempRegister, 0);
1019 #endif
1020         }
1021     }
1022
1023     void load32(const void* address, RegisterID dest)
1024     {
1025         /*
1026             li  addrTemp, address
1027             lw  dest, 0(addrTemp)
1028         */
1029         move(TrustedImmPtr(address), addrTempRegister);
1030         m_assembler.lw(dest, addrTempRegister, 0);
1031     }
1032
1033     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
1034     {
1035         m_fixedWidth = true;
1036         /*
1037             lui addrTemp, address.offset >> 16
1038             ori addrTemp, addrTemp, address.offset & 0xffff
1039             addu        addrTemp, addrTemp, address.base
1040             lw  dest, 0(addrTemp)
1041         */
1042         DataLabel32 dataLabel(this);
1043         move(TrustedImm32(address.offset), addrTempRegister);
1044         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1045         m_assembler.lw(dest, addrTempRegister, 0);
1046         m_fixedWidth = false;
1047         return dataLabel;
1048     }
1049     
1050     DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
1051     {
1052         DataLabelCompact dataLabel(this);
1053         load32WithAddressOffsetPatch(address, dest);
1054         return dataLabel;
1055     }
1056
1057     /* Need to use zero-extened load half-word for load16.  */
1058     void load16(ImplicitAddress address, RegisterID dest)
1059     {
1060         if (address.offset >= -32768 && address.offset <= 32767
1061             && !m_fixedWidth)
1062             m_assembler.lhu(dest, address.base, address.offset);
1063         else {
1064             /*
1065                 lui     addrTemp, (offset + 0x8000) >> 16
1066                 addu    addrTemp, addrTemp, base
1067                 lhu     dest, (offset & 0xffff)(addrTemp)
1068               */
1069             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
1070             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1071             m_assembler.lhu(dest, addrTempRegister, address.offset);
1072         }
1073     }
1074
1075     /* Need to use zero-extened load half-word for load16.  */
1076     void load16(BaseIndex address, RegisterID dest)
1077     {
1078         if (address.offset >= -32768 && address.offset <= 32767
1079             && !m_fixedWidth) {
1080             /*
1081                 sll     addrTemp, address.index, address.scale
1082                 addu    addrTemp, addrTemp, address.base
1083                 lhu     dest, address.offset(addrTemp)
1084             */
1085             m_assembler.sll(addrTempRegister, address.index, address.scale);
1086             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1087             m_assembler.lhu(dest, addrTempRegister, address.offset);
1088         } else {
1089             /*
1090                 sll     addrTemp, address.index, address.scale
1091                 addu    addrTemp, addrTemp, address.base
1092                 lui     immTemp, (address.offset + 0x8000) >> 16
1093                 addu    addrTemp, addrTemp, immTemp
1094                 lhu     dest, (address.offset & 0xffff)(addrTemp)
1095             */
1096             m_assembler.sll(addrTempRegister, address.index, address.scale);
1097             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1098             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
1099             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
1100             m_assembler.lhu(dest, addrTempRegister, address.offset);
1101         }
1102     }
1103
1104     void load16SignedExtendTo32(BaseIndex address, RegisterID dest)
1105     {
1106         if (address.offset >= -32768 && address.offset <= 32767
1107             && !m_fixedWidth) {
1108             /*
1109                 sll     addrTemp, address.index, address.scale
1110                 addu    addrTemp, addrTemp, address.base
1111                 lh     dest, address.offset(addrTemp)
1112             */
1113             m_assembler.sll(addrTempRegister, address.index, address.scale);
1114             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1115             m_assembler.lh(dest, addrTempRegister, address.offset);
1116         } else {
1117             /*
1118                 sll     addrTemp, address.index, address.scale
1119                 addu    addrTemp, addrTemp, address.base
1120                 lui     immTemp, (address.offset + 0x8000) >> 16
1121                 addu    addrTemp, addrTemp, immTemp
1122                 lh     dest, (address.offset & 0xffff)(addrTemp)
1123             */
1124             m_assembler.sll(addrTempRegister, address.index, address.scale);
1125             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1126             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
1127             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
1128             m_assembler.lh(dest, addrTempRegister, address.offset);
1129         }
1130     }
1131
1132     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
1133     {
1134         m_fixedWidth = true;
1135         /*
1136             lui addrTemp, address.offset >> 16
1137             ori addrTemp, addrTemp, address.offset & 0xffff
1138             addu        addrTemp, addrTemp, address.base
1139             sw  src, 0(addrTemp)
1140         */
1141         DataLabel32 dataLabel(this);
1142         move(TrustedImm32(address.offset), addrTempRegister);
1143         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1144         m_assembler.sw(src, addrTempRegister, 0);
1145         m_fixedWidth = false;
1146         return dataLabel;
1147     }
1148
1149     void store8(RegisterID src, BaseIndex address)
1150     {
1151         if (address.offset >= -32768 && address.offset <= 32767
1152             && !m_fixedWidth) {
1153             /*
1154                 sll     addrTemp, address.index, address.scale
1155                 addu    addrTemp, addrTemp, address.base
1156                 sb      src, address.offset(addrTemp)
1157             */
1158             m_assembler.sll(addrTempRegister, address.index, address.scale);
1159             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1160             m_assembler.sb(src, addrTempRegister, address.offset);
1161         } else {
1162             /*
1163                 sll     addrTemp, address.index, address.scale
1164                 addu    addrTemp, addrTemp, address.base
1165                 lui     immTemp, (address.offset + 0x8000) >> 16
1166                 addu    addrTemp, addrTemp, immTemp
1167                 sb      src, (address.offset & 0xffff)(at)
1168             */
1169             m_assembler.sll(addrTempRegister, address.index, address.scale);
1170             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1171             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
1172             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
1173             m_assembler.sb(src, addrTempRegister, address.offset);
1174         }
1175     }
1176
1177     void store8(RegisterID src, void* address)
1178     {
1179         move(TrustedImmPtr(address), addrTempRegister);
1180         m_assembler.sb(src, addrTempRegister, 0);
1181     }
1182
1183     void store8(TrustedImm32 imm, void* address)
1184     {
1185         /*
1186             li  immTemp, imm
1187             li  addrTemp, address
1188             sb  src, 0(addrTemp)
1189         */
1190         TrustedImm32 imm8(static_cast<int8_t>(imm.m_value));
1191         if (!imm8.m_value && !m_fixedWidth) {
1192             move(TrustedImmPtr(address), addrTempRegister);
1193             m_assembler.sb(MIPSRegisters::zero, addrTempRegister, 0);
1194         } else {
1195             move(imm8, immTempRegister);
1196             move(TrustedImmPtr(address), addrTempRegister);
1197             m_assembler.sb(immTempRegister, addrTempRegister, 0);
1198         }
1199     }
1200
1201     void store8(TrustedImm32 imm, ImplicitAddress address)
1202     {
1203         TrustedImm32 imm8(static_cast<int8_t>(imm.m_value));
1204         if (address.offset >= -32768 && address.offset <= 32767
1205             && !m_fixedWidth) {
1206             if (!imm8.m_value)
1207                 m_assembler.sb(MIPSRegisters::zero, address.base, address.offset);
1208             else {
1209                 move(imm8, immTempRegister);
1210                 m_assembler.sb(immTempRegister, address.base, address.offset);
1211             }
1212         } else {
1213             /*
1214                 lui     addrTemp, (offset + 0x8000) >> 16
1215                 addu    addrTemp, addrTemp, base
1216                 sb      immTemp, (offset & 0xffff)(addrTemp)
1217               */
1218             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
1219             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1220             if (!imm8.m_value && !m_fixedWidth)
1221                 m_assembler.sb(MIPSRegisters::zero, addrTempRegister, address.offset);
1222             else {
1223                 move(imm8, immTempRegister);
1224                 m_assembler.sb(immTempRegister, addrTempRegister, address.offset);
1225             }
1226         }
1227     }
1228
1229     void store16(RegisterID src, BaseIndex address)
1230     {
1231         if (address.offset >= -32768 && address.offset <= 32767
1232             && !m_fixedWidth) {
1233             /*
1234                 sll     addrTemp, address.index, address.scale
1235                 addu    addrTemp, addrTemp, address.base
1236                 sh      src, address.offset(addrTemp)
1237             */
1238             m_assembler.sll(addrTempRegister, address.index, address.scale);
1239             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1240             m_assembler.sh(src, addrTempRegister, address.offset);
1241         } else {
1242             /*
1243                 sll     addrTemp, address.index, address.scale
1244                 addu    addrTemp, addrTemp, address.base
1245                 lui     immTemp, (address.offset + 0x8000) >> 16
1246                 addu    addrTemp, addrTemp, immTemp
1247                 sh      src, (address.offset & 0xffff)(at)
1248             */
1249             m_assembler.sll(addrTempRegister, address.index, address.scale);
1250             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1251             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
1252             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
1253             m_assembler.sh(src, addrTempRegister, address.offset);
1254         }
1255     }
1256
1257     void store32(RegisterID src, ImplicitAddress address)
1258     {
1259         if (address.offset >= -32768 && address.offset <= 32767
1260             && !m_fixedWidth)
1261             m_assembler.sw(src, address.base, address.offset);
1262         else {
1263             /*
1264                 lui     addrTemp, (offset + 0x8000) >> 16
1265                 addu    addrTemp, addrTemp, base
1266                 sw      src, (offset & 0xffff)(addrTemp)
1267               */
1268             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
1269             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1270             m_assembler.sw(src, addrTempRegister, address.offset);
1271         }
1272     }
1273
1274     void store32(RegisterID src, BaseIndex address)
1275     {
1276         if (address.offset >= -32768 && address.offset <= 32767
1277             && !m_fixedWidth) {
1278             /*
1279                 sll     addrTemp, address.index, address.scale
1280                 addu    addrTemp, addrTemp, address.base
1281                 sw      src, address.offset(addrTemp)
1282             */
1283             m_assembler.sll(addrTempRegister, address.index, address.scale);
1284             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1285             m_assembler.sw(src, addrTempRegister, address.offset);
1286         } else {
1287             /*
1288                 sll     addrTemp, address.index, address.scale
1289                 addu    addrTemp, addrTemp, address.base
1290                 lui     immTemp, (address.offset + 0x8000) >> 16
1291                 addu    addrTemp, addrTemp, immTemp
1292                 sw      src, (address.offset & 0xffff)(at)
1293             */
1294             m_assembler.sll(addrTempRegister, address.index, address.scale);
1295             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1296             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
1297             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
1298             m_assembler.sw(src, addrTempRegister, address.offset);
1299         }
1300     }
1301
1302     void store32(TrustedImm32 imm, ImplicitAddress address)
1303     {
1304         if (address.offset >= -32768 && address.offset <= 32767
1305             && !m_fixedWidth) {
1306             if (!imm.m_value)
1307                 m_assembler.sw(MIPSRegisters::zero, address.base, address.offset);
1308             else {
1309                 move(imm, immTempRegister);
1310                 m_assembler.sw(immTempRegister, address.base, address.offset);
1311             }
1312         } else {
1313             /*
1314                 lui     addrTemp, (offset + 0x8000) >> 16
1315                 addu    addrTemp, addrTemp, base
1316                 sw      immTemp, (offset & 0xffff)(addrTemp)
1317               */
1318             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
1319             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1320             if (!imm.m_value && !m_fixedWidth)
1321                 m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset);
1322             else {
1323                 move(imm, immTempRegister);
1324                 m_assembler.sw(immTempRegister, addrTempRegister, address.offset);
1325             }
1326         }
1327     }
1328
1329     void store32(TrustedImm32 imm, BaseIndex address)
1330     {
1331         if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) {
1332             /*
1333                 sll     addrTemp, address.index, address.scale
1334                 addu    addrTemp, addrTemp, address.base
1335                 sw      src, address.offset(addrTemp)
1336             */
1337             m_assembler.sll(addrTempRegister, address.index, address.scale);
1338             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1339             if (!imm.m_value)
1340                 m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset);
1341             else {
1342                 move(imm, immTempRegister);
1343                 m_assembler.sw(immTempRegister, addrTempRegister, address.offset);
1344             }
1345         } else {
1346             /*
1347                 sll     addrTemp, address.index, address.scale
1348                 addu    addrTemp, addrTemp, address.base
1349                 lui     immTemp, (address.offset + 0x8000) >> 16
1350                 addu    addrTemp, addrTemp, immTemp
1351                 sw      src, (address.offset & 0xffff)(at)
1352             */
1353             m_assembler.sll(addrTempRegister, address.index, address.scale);
1354             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1355             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
1356             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
1357             if (!imm.m_value && !m_fixedWidth)
1358                 m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset);
1359             else {
1360                 move(imm, immTempRegister);
1361                 m_assembler.sw(immTempRegister, addrTempRegister, address.offset);
1362             }
1363         }
1364     }
1365
1366
1367     void store32(RegisterID src, const void* address)
1368     {
1369         /*
1370             li  addrTemp, address
1371             sw  src, 0(addrTemp)
1372         */
1373         move(TrustedImmPtr(address), addrTempRegister);
1374         m_assembler.sw(src, addrTempRegister, 0);
1375     }
1376
1377     void store32(TrustedImm32 imm, const void* address)
1378     {
1379         /*
1380             li  immTemp, imm
1381             li  addrTemp, address
1382             sw  src, 0(addrTemp)
1383         */
1384         if (!imm.m_value && !m_fixedWidth) {
1385             move(TrustedImmPtr(address), addrTempRegister);
1386             m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0);
1387         } else {
1388             move(imm, immTempRegister);
1389             move(TrustedImmPtr(address), addrTempRegister);
1390             m_assembler.sw(immTempRegister, addrTempRegister, 0);
1391         }
1392     }
1393
1394     // Floating-point operations:
1395
1396     static bool supportsFloatingPoint()
1397     {
1398 #if WTF_MIPS_DOUBLE_FLOAT
1399         return true;
1400 #else
1401         return false;
1402 #endif
1403     }
1404
1405     static bool supportsFloatingPointTruncate()
1406     {
1407 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
1408         return true;
1409 #else
1410         return false;
1411 #endif
1412     }
1413
1414     static bool supportsFloatingPointSqrt()
1415     {
1416 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
1417         return true;
1418 #else
1419         return false;
1420 #endif
1421     }
1422
1423     static bool supportsFloatingPointAbs()
1424     {
1425 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
1426         return true;
1427 #else
1428         return false;
1429 #endif
1430     }
1431
1432     static bool supportsFloatingPointRounding() { return false; }
1433
1434     // Stack manipulation operations:
1435     //
1436     // The ABI is assumed to provide a stack abstraction to memory,
1437     // containing machine word sized units of data. Push and pop
1438     // operations add and remove a single register sized unit of data
1439     // to or from the stack. Peek and poke operations read or write
1440     // values on the stack, without moving the current stack position.
1441
1442     void pop(RegisterID dest)
1443     {
1444         m_assembler.lw(dest, MIPSRegisters::sp, 0);
1445         m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, 4);
1446     }
1447
1448     void popPair(RegisterID dest1, RegisterID dest2)
1449     {
1450         m_assembler.lw(dest1, MIPSRegisters::sp, 0);
1451         m_assembler.lw(dest2, MIPSRegisters::sp, 4);
1452         m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, 8);
1453     }
1454
1455     void push(RegisterID src)
1456     {
1457         m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, -4);
1458         m_assembler.sw(src, MIPSRegisters::sp, 0);
1459     }
1460
1461     void push(Address address)
1462     {
1463         load32(address, dataTempRegister);
1464         push(dataTempRegister);
1465     }
1466
1467     void push(TrustedImm32 imm)
1468     {
1469         move(imm, immTempRegister);
1470         push(immTempRegister);
1471     }
1472
1473     void pushPair(RegisterID src1, RegisterID src2)
1474     {
1475         m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, -8);
1476         m_assembler.sw(src2, MIPSRegisters::sp, 4);
1477         m_assembler.sw(src1, MIPSRegisters::sp, 0);
1478     }
1479
1480     // Register move operations:
1481     //
1482     // Move values in registers.
1483
1484     void move(TrustedImm32 imm, RegisterID dest)
1485     {
1486         if (!imm.m_value && !m_fixedWidth)
1487             move(MIPSRegisters::zero, dest);
1488         else if (m_fixedWidth) {
1489             m_assembler.lui(dest, imm.m_value >> 16);
1490             m_assembler.ori(dest, dest, imm.m_value);
1491         } else
1492             m_assembler.li(dest, imm.m_value);
1493     }
1494
1495     void move(RegisterID src, RegisterID dest)
1496     {
1497         if (src != dest || m_fixedWidth)
1498             m_assembler.move(dest, src);
1499     }
1500
1501     void move(TrustedImmPtr imm, RegisterID dest)
1502     {
1503         move(TrustedImm32(imm), dest);
1504     }
1505
1506     void swap(RegisterID reg1, RegisterID reg2)
1507     {
1508         move(reg1, immTempRegister);
1509         move(reg2, reg1);
1510         move(immTempRegister, reg2);
1511     }
1512
1513     void signExtend32ToPtr(RegisterID src, RegisterID dest)
1514     {
1515         if (src != dest || m_fixedWidth)
1516             move(src, dest);
1517     }
1518
1519     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
1520     {
1521         if (src != dest || m_fixedWidth)
1522             move(src, dest);
1523     }
1524
1525     // Forwards / external control flow operations:
1526     //
1527     // This set of jump and conditional branch operations return a Jump
1528     // object which may linked at a later point, allow forwards jump,
1529     // or jumps that will require external linkage (after the code has been
1530     // relocated).
1531     //
1532     // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
1533     // respecitvely, for unsigned comparisons the names b, a, be, and ae are
1534     // used (representing the names 'below' and 'above').
1535     //
1536     // Operands to the comparision are provided in the expected order, e.g.
1537     // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when
1538     // treated as a signed 32bit value, is less than or equal to 5.
1539     //
1540     // jz and jnz test whether the first operand is equal to zero, and take
1541     // an optional second operand of a mask under which to perform the test.
1542
1543     Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
1544     {
1545         TrustedImm32 right8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, right);
1546         MacroAssemblerHelpers::load8OnCondition(*this, cond, left, dataTempRegister);
1547         move(right8, immTempRegister);
1548         return branch32(cond, dataTempRegister, immTempRegister);
1549     }
1550
1551     Jump branch8(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
1552     {
1553         TrustedImm32 right8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, right);
1554         MacroAssemblerHelpers::load8OnCondition(*this, cond, left, dataTempRegister);
1555         move(right8, immTempRegister);
1556         return branch32(cond, dataTempRegister, immTempRegister);
1557     }
1558
1559     void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
1560     {
1561         TrustedImm32 right8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, right);
1562         MacroAssemblerHelpers::load8OnCondition(*this, cond, left, dataTempRegister);
1563         move(right8, immTempRegister);
1564         compare32(cond, dataTempRegister, immTempRegister, dest);
1565     }
1566
1567     Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1568     {
1569         TrustedImm32 right8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, right);
1570         MacroAssemblerHelpers::load8OnCondition(*this, cond, left, dataTempRegister);
1571         // Be careful that the previous load8() uses immTempRegister.
1572         // So, we need to put move() after load8().
1573         move(right8, immTempRegister);
1574         return branch32(cond, dataTempRegister, immTempRegister);
1575     }
1576
1577     Jump branchPtr(RelationalCondition cond, BaseIndex left, RegisterID right)
1578     {
1579         load32(left, dataTempRegister);
1580         return branch32(cond, dataTempRegister, right);
1581     }
1582
1583     Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
1584     {
1585         if (cond == Equal)
1586             return branchEqual(left, right);
1587         if (cond == NotEqual)
1588             return branchNotEqual(left, right);
1589         if (cond == Above) {
1590             m_assembler.sltu(cmpTempRegister, right, left);
1591             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1592         }
1593         if (cond == AboveOrEqual) {
1594             m_assembler.sltu(cmpTempRegister, left, right);
1595             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
1596         }
1597         if (cond == Below) {
1598             m_assembler.sltu(cmpTempRegister, left, right);
1599             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1600         }
1601         if (cond == BelowOrEqual) {
1602             m_assembler.sltu(cmpTempRegister, right, left);
1603             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
1604         }
1605         if (cond == GreaterThan) {
1606             m_assembler.slt(cmpTempRegister, right, left);
1607             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1608         }
1609         if (cond == GreaterThanOrEqual) {
1610             m_assembler.slt(cmpTempRegister, left, right);
1611             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
1612         }
1613         if (cond == LessThan) {
1614             m_assembler.slt(cmpTempRegister, left, right);
1615             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1616         }
1617         if (cond == LessThanOrEqual) {
1618             m_assembler.slt(cmpTempRegister, right, left);
1619             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
1620         }
1621         ASSERT(0);
1622
1623         return Jump();
1624     }
1625
1626     Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
1627     {
1628         move(right, immTempRegister);
1629         return branch32(cond, left, immTempRegister);
1630     }
1631
1632     Jump branch32(RelationalCondition cond, RegisterID left, Address right)
1633     {
1634         load32(right, dataTempRegister);
1635         return branch32(cond, left, dataTempRegister);
1636     }
1637
1638     Jump branch32(RelationalCondition cond, Address left, RegisterID right)
1639     {
1640         load32(left, dataTempRegister);
1641         return branch32(cond, dataTempRegister, right);
1642     }
1643
1644     Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
1645     {
1646         load32(left, dataTempRegister);
1647         move(right, immTempRegister);
1648         return branch32(cond, dataTempRegister, immTempRegister);
1649     }
1650
1651     Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1652     {
1653         load32(left, dataTempRegister);
1654         // Be careful that the previous load32() uses immTempRegister.
1655         // So, we need to put move() after load32().
1656         move(right, immTempRegister);
1657         return branch32(cond, dataTempRegister, immTempRegister);
1658     }
1659
1660     Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1661     {
1662         load32WithUnalignedHalfWords(left, dataTempRegister);
1663         // Be careful that the previous load32WithUnalignedHalfWords()
1664         // uses immTempRegister.
1665         // So, we need to put move() after load32WithUnalignedHalfWords().
1666         move(right, immTempRegister);
1667         return branch32(cond, dataTempRegister, immTempRegister);
1668     }
1669
1670     Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
1671     {
1672         load32(left.m_ptr, dataTempRegister);
1673         return branch32(cond, dataTempRegister, right);
1674     }
1675
1676     Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
1677     {
1678         load32(left.m_ptr, dataTempRegister);
1679         move(right, immTempRegister);
1680         return branch32(cond, dataTempRegister, immTempRegister);
1681     }
1682
1683     Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
1684     {
1685         ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed));
1686         m_assembler.andInsn(cmpTempRegister, reg, mask);
1687         switch (cond) {
1688         case Zero:
1689             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
1690         case NonZero:
1691             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1692         case Signed:
1693             m_assembler.slt(cmpTempRegister, cmpTempRegister, MIPSRegisters::zero);
1694             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1695         default:
1696             RELEASE_ASSERT_NOT_REACHED();
1697         }
1698     }
1699
1700     Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
1701     {
1702         ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed));
1703         if (mask.m_value == -1 && !m_fixedWidth) {
1704             switch (cond) {
1705             case Zero:
1706                 return branchEqual(reg, MIPSRegisters::zero);
1707             case NonZero:
1708                 return branchNotEqual(reg, MIPSRegisters::zero);
1709             case Signed:
1710                 m_assembler.slt(cmpTempRegister, reg, MIPSRegisters::zero);
1711                 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1712             default:
1713                 RELEASE_ASSERT_NOT_REACHED();
1714             }
1715         }
1716         move(mask, immTempRegister);
1717         return branchTest32(cond, reg, immTempRegister);
1718     }
1719
1720     Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1721     {
1722         load32(address, dataTempRegister);
1723         return branchTest32(cond, dataTempRegister, mask);
1724     }
1725
1726     Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
1727     {
1728         load32(address, dataTempRegister);
1729         return branchTest32(cond, dataTempRegister, mask);
1730     }
1731
1732     Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
1733     {
1734         TrustedImm32 mask8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, mask);
1735         MacroAssemblerHelpers::load8OnCondition(*this, cond, address, dataTempRegister);
1736         return branchTest32(cond, dataTempRegister, mask8);
1737     }
1738
1739     Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1740     {
1741         TrustedImm32 mask8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, mask);
1742         MacroAssemblerHelpers::load8OnCondition(*this, cond, address, dataTempRegister);
1743         return branchTest32(cond, dataTempRegister, mask8);
1744     }
1745
1746     Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
1747     {
1748         TrustedImm32 mask8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, mask);
1749         move(TrustedImmPtr(address.m_ptr), dataTempRegister);
1750         MacroAssemblerHelpers::load8OnCondition(*this, cond, Address(dataTempRegister), dataTempRegister);
1751         return branchTest32(cond, dataTempRegister, mask8);
1752     }
1753
1754     Jump jump()
1755     {
1756         return branchEqual(MIPSRegisters::zero, MIPSRegisters::zero);
1757     }
1758
1759     void jump(RegisterID target)
1760     {
1761         move(target, MIPSRegisters::t9);
1762         m_assembler.jr(MIPSRegisters::t9);
1763         m_assembler.nop();
1764     }
1765
1766     void jump(Address address)
1767     {
1768         m_fixedWidth = true;
1769         load32(address, MIPSRegisters::t9);
1770         m_assembler.jr(MIPSRegisters::t9);
1771         m_assembler.nop();
1772         m_fixedWidth = false;
1773     }
1774
1775     void jump(AbsoluteAddress address)
1776     {
1777         m_fixedWidth = true;
1778         load32(address.m_ptr, MIPSRegisters::t9);
1779         m_assembler.jr(MIPSRegisters::t9);
1780         m_assembler.nop();
1781         m_fixedWidth = false;
1782     }
1783
1784     void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2)
1785     {
1786         m_assembler.vmov(dest1, dest2, src);
1787     }
1788
1789     void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID scratch)
1790     {
1791         UNUSED_PARAM(scratch);
1792         m_assembler.vmov(dest, src1, src2);
1793     }
1794
1795     // Arithmetic control flow operations:
1796     //
1797     // This set of conditional branch operations branch based
1798     // on the result of an arithmetic operation. The operation
1799     // is performed as normal, storing the result.
1800     //
1801     // * jz operations branch if the result is zero.
1802     // * jo operations branch if the (signed) arithmetic
1803     //   operation caused an overflow to occur.
1804
1805     Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
1806     {
1807         ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
1808         if (cond == Overflow) {
1809             /*
1810                 move    dest, dataTemp
1811                 xor     cmpTemp, dataTemp, src
1812                 bltz    cmpTemp, No_overflow    # diff sign bit -> no overflow
1813                 addu    dest, dataTemp, src
1814                 xor     cmpTemp, dest, dataTemp
1815                 bgez    cmpTemp, No_overflow    # same sign big -> no overflow
1816                 nop
1817                 b       Overflow
1818                 nop
1819                 nop
1820                 nop
1821                 nop
1822                 nop
1823             No_overflow:
1824             */
1825             move(dest, dataTempRegister);
1826             m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src);
1827             m_assembler.bltz(cmpTempRegister, 12);
1828             m_assembler.addu(dest, dataTempRegister, src);
1829             m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
1830             m_assembler.bgez(cmpTempRegister, 9);
1831             m_assembler.nop();
1832             return jump();
1833         }
1834         if (cond == Signed) {
1835             add32(src, dest);
1836             // Check if dest is negative.
1837             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
1838             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1839         }
1840         if (cond == PositiveOrZero) {
1841             add32(src, dest);
1842             // Check if dest is not negative.
1843             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
1844             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
1845         }
1846         if (cond == Zero) {
1847             add32(src, dest);
1848             return branchEqual(dest, MIPSRegisters::zero);
1849         }
1850         if (cond == NonZero) {
1851             add32(src, dest);
1852             return branchNotEqual(dest, MIPSRegisters::zero);
1853         }
1854         ASSERT(0);
1855         return Jump();
1856     }
1857
1858     Jump branchAdd32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest)
1859     {
1860         ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
1861         if (cond == Overflow) {
1862             /*
1863                 move    dataTemp, op1
1864                 xor     cmpTemp, dataTemp, op2
1865                 bltz    cmpTemp, No_overflow    # diff sign bit -> no overflow
1866                 addu    dest, dataTemp, op2
1867                 xor     cmpTemp, dest, dataTemp
1868                 bgez    cmpTemp, No_overflow    # same sign big -> no overflow
1869                 nop
1870                 b       Overflow
1871                 nop
1872                 nop
1873                 nop
1874                 nop
1875                 nop
1876             No_overflow:
1877             */
1878             move(op1, dataTempRegister);
1879             m_assembler.xorInsn(cmpTempRegister, dataTempRegister, op2);
1880             m_assembler.bltz(cmpTempRegister, 12);
1881             m_assembler.addu(dest, dataTempRegister, op2);
1882             m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
1883             m_assembler.bgez(cmpTempRegister, 9);
1884             m_assembler.nop();
1885             return jump();
1886         }
1887         if (cond == Signed) {
1888             add32(op1, op2, dest);
1889             // Check if dest is negative.
1890             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
1891             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1892         }
1893         if (cond == PositiveOrZero) {
1894             add32(op1, op2, dest);
1895             // Check if dest is not negative.
1896             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
1897             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
1898         }
1899         if (cond == Zero) {
1900             add32(op1, op2, dest);
1901             return branchEqual(dest, MIPSRegisters::zero);
1902         }
1903         if (cond == NonZero) {
1904             add32(op1, op2, dest);
1905             return branchNotEqual(dest, MIPSRegisters::zero);
1906         }
1907         ASSERT(0);
1908         return Jump();
1909     }
1910
1911     Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
1912     {
1913         move(imm, immTempRegister);
1914         return branchAdd32(cond, immTempRegister, dest);
1915     }
1916
1917     Jump branchAdd32(ResultCondition cond, Address address, RegisterID dest)
1918     {
1919         load32(address, immTempRegister);
1920         return branchAdd32(cond, immTempRegister, dest);
1921     }
1922
1923     Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
1924     {
1925         move(imm, immTempRegister);
1926         move(src, dest);
1927         return branchAdd32(cond, immTempRegister, dest);
1928     }
1929
1930     Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
1931     {
1932         ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
1933         if (cond == Overflow) {
1934             /*
1935                 move    dataTemp, dest
1936                 xori    cmpTemp, dataTemp, imm
1937                 bltz    cmpTemp, No_overflow    # diff sign bit -> no overflow
1938                 addiu   dataTemp, dataTemp, imm
1939                 move    dest, dataTemp
1940                 xori    cmpTemp, dataTemp, imm
1941                 bgez    cmpTemp, No_overflow    # same sign big -> no overflow
1942                 nop
1943                 b       Overflow
1944                 nop
1945                 nop
1946                 nop
1947                 nop
1948                 nop
1949             No_overflow:
1950             */
1951             if (imm.m_value >= -32768 && imm.m_value  <= 32767 && !m_fixedWidth) {
1952                 load32(dest.m_ptr, dataTempRegister);
1953                 m_assembler.xori(cmpTempRegister, dataTempRegister, imm.m_value);
1954                 m_assembler.bltz(cmpTempRegister, 14);
1955                 m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value);
1956                 store32(dataTempRegister, dest.m_ptr);
1957                 m_assembler.xori(cmpTempRegister, dataTempRegister, imm.m_value);
1958                 m_assembler.bgez(cmpTempRegister, 9);
1959                 m_assembler.nop();
1960             } else {
1961                 load32(dest.m_ptr, dataTempRegister);
1962                 move(imm, immTempRegister);
1963                 m_assembler.xorInsn(cmpTempRegister, dataTempRegister, immTempRegister);
1964                 m_assembler.bltz(cmpTempRegister, 14);
1965                 m_assembler.addiu(dataTempRegister, dataTempRegister, immTempRegister);
1966                 store32(dataTempRegister, dest.m_ptr);
1967                 m_assembler.xori(cmpTempRegister, dataTempRegister, immTempRegister);
1968                 m_assembler.bgez(cmpTempRegister, 9);
1969                 m_assembler.nop();
1970             }
1971             return jump();
1972         }
1973         move(imm, immTempRegister);
1974         load32(dest.m_ptr, dataTempRegister);
1975         add32(immTempRegister, dataTempRegister);
1976         store32(dataTempRegister, dest.m_ptr);
1977         if (cond == Signed) {
1978             // Check if dest is negative.
1979             m_assembler.slt(cmpTempRegister, dataTempRegister, MIPSRegisters::zero);
1980             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1981         }
1982         if (cond == PositiveOrZero) {
1983             // Check if dest is not negative.
1984             m_assembler.slt(cmpTempRegister, dataTempRegister, MIPSRegisters::zero);
1985             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
1986         }
1987         if (cond == Zero)
1988             return branchEqual(dataTempRegister, MIPSRegisters::zero);
1989         if (cond == NonZero)
1990             return branchNotEqual(dataTempRegister, MIPSRegisters::zero);
1991         ASSERT(0);
1992         return Jump();
1993     }
1994
1995     Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
1996     {
1997         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1998         if (cond == Overflow) {
1999             /*
2000                 mult    src, dest
2001                 mfhi    dataTemp
2002                 mflo    dest
2003                 sra     addrTemp, dest, 31
2004                 beq     dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow
2005                 nop
2006                 b       Overflow
2007                 nop
2008                 nop
2009                 nop
2010                 nop
2011                 nop
2012             No_overflow:
2013             */
2014             m_assembler.mult(src1, src2);
2015             m_assembler.mfhi(dataTempRegister);
2016             m_assembler.mflo(dest);
2017             m_assembler.sra(addrTempRegister, dest, 31);
2018             m_assembler.beq(dataTempRegister, addrTempRegister, 9);
2019             m_assembler.nop();
2020             return jump();
2021         }
2022         if (cond == Signed) {
2023             mul32(src1, src2, dest);
2024             // Check if dest is negative.
2025             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
2026             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
2027         }
2028         if (cond == Zero) {
2029             mul32(src1, src2, dest);
2030             return branchEqual(dest, MIPSRegisters::zero);
2031         }
2032         if (cond == NonZero) {
2033             mul32(src1, src2, dest);
2034             return branchNotEqual(dest, MIPSRegisters::zero);
2035         }
2036         ASSERT(0);
2037         return Jump();
2038     }
2039
2040     Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
2041     {
2042         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2043         if (cond == Overflow) {
2044             /*
2045                 mult    src, dest
2046                 mfhi    dataTemp
2047                 mflo    dest
2048                 sra     addrTemp, dest, 31
2049                 beq     dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow
2050                 nop
2051                 b       Overflow
2052                 nop
2053                 nop
2054                 nop
2055                 nop
2056                 nop
2057             No_overflow:
2058             */
2059             m_assembler.mult(src, dest);
2060             m_assembler.mfhi(dataTempRegister);
2061             m_assembler.mflo(dest);
2062             m_assembler.sra(addrTempRegister, dest, 31);
2063             m_assembler.beq(dataTempRegister, addrTempRegister, 9);
2064             m_assembler.nop();
2065             return jump();
2066         }
2067         if (cond == Signed) {
2068             mul32(src, dest);
2069             // Check if dest is negative.
2070             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
2071             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
2072         }
2073         if (cond == Zero) {
2074             mul32(src, dest);
2075             return branchEqual(dest, MIPSRegisters::zero);
2076         }
2077         if (cond == NonZero) {
2078             mul32(src, dest);
2079             return branchNotEqual(dest, MIPSRegisters::zero);
2080         }
2081         ASSERT(0);
2082         return Jump();
2083     }
2084
2085     Jump branchMul32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
2086     {
2087         move(imm, immTempRegister);
2088         return branchMul32(cond, immTempRegister, src, dest);
2089     }
2090
2091     Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
2092     {
2093         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2094         if (cond == Overflow) {
2095             /*
2096                 move    dest, dataTemp
2097                 xor     cmpTemp, dataTemp, src
2098                 bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
2099                 subu    dest, dataTemp, src
2100                 xor     cmpTemp, dest, dataTemp
2101                 bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
2102                 nop
2103                 b       Overflow
2104                 nop
2105                 nop
2106                 nop
2107                 nop
2108                 nop
2109             No_overflow:
2110             */
2111             move(dest, dataTempRegister);
2112             m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src);
2113             m_assembler.bgez(cmpTempRegister, 12);
2114             m_assembler.subu(dest, dataTempRegister, src);
2115             m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
2116             m_assembler.bgez(cmpTempRegister, 9);
2117             m_assembler.nop();
2118             return jump();
2119         }
2120         if (cond == Signed) {
2121             sub32(src, dest);
2122             // Check if dest is negative.
2123             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
2124             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
2125         }
2126         if (cond == Zero) {
2127             sub32(src, dest);
2128             return branchEqual(dest, MIPSRegisters::zero);
2129         }
2130         if (cond == NonZero) {
2131             sub32(src, dest);
2132             return branchNotEqual(dest, MIPSRegisters::zero);
2133         }
2134         ASSERT(0);
2135         return Jump();
2136     }
2137
2138     Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
2139     {
2140         move(imm, immTempRegister);
2141         return branchSub32(cond, immTempRegister, dest);
2142     }
2143
2144     Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
2145     {
2146         move(imm, immTempRegister);
2147         return branchSub32(cond, src, immTempRegister, dest);
2148     }
2149
2150     Jump branchSub32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest)
2151     {
2152         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2153         if (cond == Overflow) {
2154             /*
2155                 move    dataTemp, op1
2156                 xor     cmpTemp, dataTemp, op2
2157                 bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
2158                 subu    dest, dataTemp, op2
2159                 xor     cmpTemp, dest, dataTemp
2160                 bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
2161                 nop
2162                 b       Overflow
2163                 nop
2164                 nop
2165                 nop
2166                 nop
2167                 nop
2168             No_overflow:
2169             */
2170             move(op1, dataTempRegister);
2171             m_assembler.xorInsn(cmpTempRegister, dataTempRegister, op2);
2172             m_assembler.bgez(cmpTempRegister, 12);
2173             m_assembler.subu(dest, dataTempRegister, op2);
2174             m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
2175             m_assembler.bgez(cmpTempRegister, 9);
2176             m_assembler.nop();
2177             return jump();
2178         }
2179         if (cond == Signed) {
2180             sub32(op1, op2, dest);
2181             // Check if dest is negative.
2182             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
2183             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
2184         }
2185         if (cond == Zero) {
2186             sub32(op1, op2, dest);
2187             return branchEqual(dest, MIPSRegisters::zero);
2188         }
2189         if (cond == NonZero) {
2190             sub32(op1, op2, dest);
2191             return branchNotEqual(dest, MIPSRegisters::zero);
2192         }
2193         ASSERT(0);
2194         return Jump();
2195     }
2196
2197     Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
2198     {
2199         m_assembler.li(dataTempRegister, -1);
2200         return branchMul32(cond, dataTempRegister, srcDest);
2201     }
2202
2203     Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
2204     {
2205         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
2206         if (cond == Signed) {
2207             or32(src, dest);
2208             // Check if dest is negative.
2209             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
2210             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
2211         }
2212         if (cond == Zero) {
2213             or32(src, dest);
2214             return branchEqual(dest, MIPSRegisters::zero);
2215         }
2216         if (cond == NonZero) {
2217             or32(src, dest);
2218             return branchNotEqual(dest, MIPSRegisters::zero);
2219         }
2220         ASSERT(0);
2221         return Jump();
2222     }
2223
2224     // Miscellaneous operations:
2225
2226     void breakpoint()
2227     {
2228         m_assembler.bkpt();
2229     }
2230
2231     static bool isBreakpoint(void* address) { return MIPSAssembler::isBkpt(address); }
2232
2233     Call nearCall()
2234     {
2235         /* We need two words for relaxation. */
2236         m_assembler.nop();
2237         m_assembler.nop();
2238         m_assembler.jal();
2239         m_assembler.nop();
2240         return Call(m_assembler.label(), Call::LinkableNear);
2241     }
2242
2243     Call nearTailCall()
2244     {
2245         m_assembler.nop();
2246         m_assembler.nop();
2247         m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 0);
2248         m_assembler.nop();
2249         insertRelaxationWords();
2250         return Call(m_assembler.label(), Call::LinkableNearTail);
2251     }
2252
2253     Call call()
2254     {
2255         m_assembler.lui(MIPSRegisters::t9, 0);
2256         m_assembler.ori(MIPSRegisters::t9, MIPSRegisters::t9, 0);
2257         m_assembler.jalr(MIPSRegisters::t9);
2258         m_assembler.nop();
2259         return Call(m_assembler.label(), Call::Linkable);
2260     }
2261
2262     Call call(RegisterID target)
2263     {
2264         move(target, MIPSRegisters::t9);
2265         m_assembler.jalr(MIPSRegisters::t9);
2266         m_assembler.nop();
2267         return Call(m_assembler.label(), Call::None);
2268     }
2269
2270     Call call(Address address)
2271     {
2272         m_fixedWidth = true;
2273         load32(address, MIPSRegisters::t9);
2274         m_assembler.jalr(MIPSRegisters::t9);
2275         m_assembler.nop();
2276         m_fixedWidth = false;
2277         return Call(m_assembler.label(), Call::None);
2278     }
2279
2280     void ret()
2281     {
2282         m_assembler.jr(MIPSRegisters::ra);
2283         m_assembler.nop();
2284     }
2285
2286     void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
2287     {
2288         if (cond == Equal) {
2289             m_assembler.xorInsn(dest, left, right);
2290             m_assembler.sltiu(dest, dest, 1);
2291         } else if (cond == NotEqual) {
2292             m_assembler.xorInsn(dest, left, right);
2293             m_assembler.sltu(dest, MIPSRegisters::zero, dest);
2294         } else if (cond == Above)
2295             m_assembler.sltu(dest, right, left);
2296         else if (cond == AboveOrEqual) {
2297             m_assembler.sltu(dest, left, right);
2298             m_assembler.xori(dest, dest, 1);
2299         } else if (cond == Below)
2300             m_assembler.sltu(dest, left, right);
2301         else if (cond == BelowOrEqual) {
2302             m_assembler.sltu(dest, right, left);
2303             m_assembler.xori(dest, dest, 1);
2304         } else if (cond == GreaterThan)
2305             m_assembler.slt(dest, right, left);
2306         else if (cond == GreaterThanOrEqual) {
2307             m_assembler.slt(dest, left, right);
2308             m_assembler.xori(dest, dest, 1);
2309         } else if (cond == LessThan)
2310             m_assembler.slt(dest, left, right);
2311         else if (cond == LessThanOrEqual) {
2312             m_assembler.slt(dest, right, left);
2313             m_assembler.xori(dest, dest, 1);
2314         }
2315     }
2316
2317     void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
2318     {
2319         move(right, immTempRegister);
2320         compare32(cond, left, immTempRegister, dest);
2321     }
2322
2323     void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
2324     {
2325         ASSERT((cond == Zero) || (cond == NonZero));
2326         TrustedImm32 mask8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, mask);
2327         MacroAssemblerHelpers::load8OnCondition(*this, cond, address, dataTempRegister);
2328         if ((mask8.m_value & 0xff) == 0xff && !m_fixedWidth) {
2329             if (cond == Zero)
2330                 m_assembler.sltiu(dest, dataTempRegister, 1);
2331             else
2332                 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister);
2333         } else {
2334             move(mask8, immTempRegister);
2335             m_assembler.andInsn(cmpTempRegister, dataTempRegister, immTempRegister);
2336             if (cond == Zero)
2337                 m_assembler.sltiu(dest, cmpTempRegister, 1);
2338             else
2339                 m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister);
2340         }
2341     }
2342
2343     void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
2344     {
2345         ASSERT((cond == Zero) || (cond == NonZero));
2346         load32(address, dataTempRegister);
2347         if (mask.m_value == -1 && !m_fixedWidth) {
2348             if (cond == Zero)
2349                 m_assembler.sltiu(dest, dataTempRegister, 1);
2350             else
2351                 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister);
2352         } else {
2353             move(mask, immTempRegister);
2354             m_assembler.andInsn(cmpTempRegister, dataTempRegister, immTempRegister);
2355             if (cond == Zero)
2356                 m_assembler.sltiu(dest, cmpTempRegister, 1);
2357             else
2358                 m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister);
2359         }
2360     }
2361
2362     DataLabel32 moveWithPatch(TrustedImm32 imm, RegisterID dest)
2363     {
2364         m_fixedWidth = true;
2365         DataLabel32 label(this);
2366         move(imm, dest);
2367         m_fixedWidth = false;
2368         return label;
2369     }
2370
2371     DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
2372     {
2373         m_fixedWidth = true;
2374         DataLabelPtr label(this);
2375         move(initialValue, dest);
2376         m_fixedWidth = false;
2377         return label;
2378     }
2379
2380     Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(nullptr))
2381     {
2382         m_fixedWidth = true;
2383         dataLabel = moveWithPatch(initialRightValue, immTempRegister);
2384         Jump temp = branch32(cond, left, immTempRegister);
2385         m_fixedWidth = false;
2386         return temp;
2387     }
2388
2389     Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(nullptr))
2390     {
2391         m_fixedWidth = true;
2392         load32(left, dataTempRegister);
2393         dataLabel = moveWithPatch(initialRightValue, immTempRegister);
2394         Jump temp = branch32(cond, dataTempRegister, immTempRegister);
2395         m_fixedWidth = false;
2396         return temp;
2397     }
2398
2399     Jump branch32WithPatch(RelationalCondition cond, Address left, DataLabel32& dataLabel, TrustedImm32 initialRightValue = TrustedImm32(0))
2400     {
2401         m_fixedWidth = true;
2402         load32(left, dataTempRegister);
2403         dataLabel = moveWithPatch(initialRightValue, immTempRegister);
2404         Jump temp = branch32(cond, dataTempRegister, immTempRegister);
2405         m_fixedWidth = false;
2406         return temp;
2407     }
2408
2409     DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
2410     {
2411         m_fixedWidth = true;
2412         DataLabelPtr dataLabel = moveWithPatch(initialValue, dataTempRegister);
2413         store32(dataTempRegister, address);
2414         m_fixedWidth = false;
2415         return dataLabel;
2416     }
2417
2418     DataLabelPtr storePtrWithPatch(ImplicitAddress address)
2419     {
2420         return storePtrWithPatch(TrustedImmPtr(nullptr), address);
2421     }
2422
2423     Call tailRecursiveCall()
2424     {
2425         // Like a normal call, but don't update the returned address register
2426         m_fixedWidth = true;
2427         move(TrustedImm32(0), MIPSRegisters::t9);
2428         m_assembler.jr(MIPSRegisters::t9);
2429         m_assembler.nop();
2430         m_fixedWidth = false;
2431         return Call(m_assembler.label(), Call::Linkable);
2432     }
2433
2434     Call makeTailRecursiveCall(Jump oldJump)
2435     {
2436         oldJump.link(this);
2437         return tailRecursiveCall();
2438     }
2439
2440     void loadFloat(BaseIndex address, FPRegisterID dest)
2441     {
2442         if (address.offset >= -32768 && address.offset <= 32767
2443             && !m_fixedWidth) {
2444             /*
2445                 sll     addrTemp, address.index, address.scale
2446                 addu    addrTemp, addrTemp, address.base
2447                 lwc1    dest, address.offset(addrTemp)
2448             */
2449             m_assembler.sll(addrTempRegister, address.index, address.scale);
2450             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2451             m_assembler.lwc1(dest, addrTempRegister, address.offset);
2452         } else {
2453             /*
2454                 sll     addrTemp, address.index, address.scale
2455                 addu    addrTemp, addrTemp, address.base
2456                 lui     immTemp, (address.offset + 0x8000) >> 16
2457                 addu    addrTemp, addrTemp, immTemp
2458                 lwc1    dest, (address.offset & 0xffff)(at)
2459             */
2460             m_assembler.sll(addrTempRegister, address.index, address.scale);
2461             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2462             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
2463             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
2464             m_assembler.lwc1(dest, addrTempRegister, address.offset);
2465         }
2466     }
2467
2468     void loadFloat(ImplicitAddress address, FPRegisterID dest)
2469     {
2470         if (address.offset >= -32768 && address.offset <= 32767
2471             && !m_fixedWidth) {
2472             m_assembler.lwc1(dest, address.base, address.offset);
2473         } else {
2474             /*
2475                lui     addrTemp, (offset + 0x8000) >> 16
2476                addu    addrTemp, addrTemp, base
2477                lwc1    dest, (offset & 0xffff)(addrTemp)
2478                */
2479             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
2480             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2481             m_assembler.lwc1(dest, addrTempRegister, address.offset);
2482         }
2483     }
2484
2485     void loadDouble(ImplicitAddress address, FPRegisterID dest)
2486     {
2487 #if WTF_MIPS_ISA(1)
2488         /*
2489             li          addrTemp, address.offset
2490             addu        addrTemp, addrTemp, base
2491             lwc1        dest, 0(addrTemp)
2492             lwc1        dest+1, 4(addrTemp)
2493          */
2494         move(TrustedImm32(address.offset), addrTempRegister);
2495         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2496         m_assembler.lwc1(dest, addrTempRegister, 0);
2497         m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4);
2498 #else
2499         if (address.offset >= -32768 && address.offset <= 32767
2500             && !m_fixedWidth) {
2501             m_assembler.ldc1(dest, address.base, address.offset);
2502         } else {
2503             /*
2504                 lui     addrTemp, (offset + 0x8000) >> 16
2505                 addu    addrTemp, addrTemp, base
2506                 ldc1    dest, (offset & 0xffff)(addrTemp)
2507               */
2508             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
2509             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2510             m_assembler.ldc1(dest, addrTempRegister, address.offset);
2511         }
2512 #endif
2513     }
2514
2515     void loadDouble(BaseIndex address, FPRegisterID dest)
2516     {
2517 #if WTF_MIPS_ISA(1)
2518         if (address.offset >= -32768 && address.offset <= 32767
2519             && !m_fixedWidth) {
2520             /*
2521                 sll     addrTemp, address.index, address.scale
2522                 addu    addrTemp, addrTemp, address.base
2523                 lwc1    dest, address.offset(addrTemp)
2524                 lwc1    dest+1, (address.offset+4)(addrTemp)
2525             */
2526             m_assembler.sll(addrTempRegister, address.index, address.scale);
2527             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2528             m_assembler.lwc1(dest, addrTempRegister, address.offset);
2529             m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, address.offset + 4);
2530         } else {
2531             /*
2532                 sll     addrTemp, address.index, address.scale
2533                 addu    addrTemp, addrTemp, address.base
2534                 lui     immTemp, (address.offset + 0x8000) >> 16
2535                 addu    addrTemp, addrTemp, immTemp
2536                 lwc1    dest, (address.offset & 0xffff)(at)
2537                 lwc1    dest+1, (address.offset & 0xffff + 4)(at)
2538             */
2539             m_assembler.sll(addrTempRegister, address.index, address.scale);
2540             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2541             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
2542             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
2543             m_assembler.lwc1(dest, addrTempRegister, address.offset);
2544             m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, address.offset + 4);
2545         }
2546 #else
2547         if (address.offset >= -32768 && address.offset <= 32767
2548             && !m_fixedWidth) {
2549             /*
2550                 sll     addrTemp, address.index, address.scale
2551                 addu    addrTemp, addrTemp, address.base
2552                 ldc1    dest, address.offset(addrTemp)
2553             */
2554             m_assembler.sll(addrTempRegister, address.index, address.scale);
2555             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2556             m_assembler.ldc1(dest, addrTempRegister, address.offset);
2557         } else {
2558             /*
2559                 sll     addrTemp, address.index, address.scale
2560                 addu    addrTemp, addrTemp, address.base
2561                 lui     immTemp, (address.offset + 0x8000) >> 16
2562                 addu    addrTemp, addrTemp, immTemp
2563                 ldc1    dest, (address.offset & 0xffff)(at)
2564             */
2565             m_assembler.sll(addrTempRegister, address.index, address.scale);
2566             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2567             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
2568             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
2569             m_assembler.ldc1(dest, addrTempRegister, address.offset);
2570         }
2571 #endif
2572     }
2573
2574     void loadDouble(TrustedImmPtr address, FPRegisterID dest)
2575     {
2576 #if WTF_MIPS_ISA(1)
2577         /*
2578             li          addrTemp, address
2579             lwc1        dest, 0(addrTemp)
2580             lwc1        dest+1, 4(addrTemp)
2581          */
2582         move(address, addrTempRegister);
2583         m_assembler.lwc1(dest, addrTempRegister, 0);
2584         m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4);
2585 #else
2586         /*
2587             li          addrTemp, address
2588             ldc1        dest, 0(addrTemp)
2589         */
2590         move(address, addrTempRegister);
2591         m_assembler.ldc1(dest, addrTempRegister, 0);
2592 #endif
2593     }
2594
2595     void storeFloat(FPRegisterID src, BaseIndex address)
2596     {
2597         if (address.offset >= -32768 && address.offset <= 32767
2598             && !m_fixedWidth) {
2599             /*
2600                 sll     addrTemp, address.index, address.scale
2601                 addu    addrTemp, addrTemp, address.base
2602                 swc1    src, address.offset(addrTemp)
2603             */
2604             m_assembler.sll(addrTempRegister, address.index, address.scale);
2605             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2606             m_assembler.swc1(src, addrTempRegister, address.offset);
2607         } else {
2608             /*
2609                 sll     addrTemp, address.index, address.scale
2610                 addu    addrTemp, addrTemp, address.base
2611                 lui     immTemp, (address.offset + 0x8000) >> 16
2612                 addu    addrTemp, addrTemp, immTemp
2613                 swc1    src, (address.offset & 0xffff)(at)
2614             */
2615             m_assembler.sll(addrTempRegister, address.index, address.scale);
2616             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2617             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
2618             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
2619             m_assembler.swc1(src, addrTempRegister, address.offset);
2620         }
2621     }
2622
2623     void storeFloat(FPRegisterID src, ImplicitAddress address)
2624     {
2625         if (address.offset >= -32768 && address.offset <= 32767
2626             && !m_fixedWidth)
2627             m_assembler.swc1(src, address.base, address.offset);
2628         else {
2629             /*
2630                 lui     addrTemp, (offset + 0x8000) >> 16
2631                 addu    addrTemp, addrTemp, base
2632                 swc1    src, (offset & 0xffff)(addrTemp)
2633               */
2634             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
2635             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2636             m_assembler.swc1(src, addrTempRegister, address.offset);
2637         }
2638     }
2639
2640     void storeDouble(FPRegisterID src, ImplicitAddress address)
2641     {
2642 #if WTF_MIPS_ISA(1)
2643         /*
2644             li          addrTemp, address.offset
2645             addu        addrTemp, addrTemp, base
2646             swc1        dest, 0(addrTemp)
2647             swc1        dest+1, 4(addrTemp)
2648          */
2649         move(TrustedImm32(address.offset), addrTempRegister);
2650         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2651         m_assembler.swc1(src, addrTempRegister, 0);
2652         m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4);
2653 #else
2654         if (address.offset >= -32768 && address.offset <= 32767
2655             && !m_fixedWidth)
2656             m_assembler.sdc1(src, address.base, address.offset);
2657         else {
2658             /*
2659                 lui     addrTemp, (offset + 0x8000) >> 16
2660                 addu    addrTemp, addrTemp, base
2661                 sdc1    src, (offset & 0xffff)(addrTemp)
2662               */
2663             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
2664             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2665             m_assembler.sdc1(src, addrTempRegister, address.offset);
2666         }
2667 #endif
2668     }
2669
2670     void storeDouble(FPRegisterID src, BaseIndex address)
2671     {
2672 #if WTF_MIPS_ISA(1)
2673         if (address.offset >= -32768 && address.offset <= 32767
2674             && !m_fixedWidth) {
2675             /*
2676                 sll     addrTemp, address.index, address.scale
2677                 addu    addrTemp, addrTemp, address.base
2678                 swc1    src, address.offset(addrTemp)
2679                 swc1    src+1, (address.offset + 4)(addrTemp)
2680             */
2681             m_assembler.sll(addrTempRegister, address.index, address.scale);
2682             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2683             m_assembler.swc1(src, addrTempRegister, address.offset);
2684             m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, address.offset + 4);
2685         } else {
2686             /*
2687                 sll     addrTemp, address.index, address.scale
2688                 addu    addrTemp, addrTemp, address.base
2689                 lui     immTemp, (address.offset + 0x8000) >> 16
2690                 addu    addrTemp, addrTemp, immTemp
2691                 swc1    src, (address.offset & 0xffff)(at)
2692                 swc1    src+1, (address.offset & 0xffff + 4)(at)
2693             */
2694             m_assembler.sll(addrTempRegister, address.index, address.scale);
2695             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2696             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
2697             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
2698             m_assembler.swc1(src, addrTempRegister, address.offset);
2699             m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, address.offset + 4);
2700         }
2701 #else
2702         if (address.offset >= -32768 && address.offset <= 32767
2703             && !m_fixedWidth) {
2704             /*
2705                 sll     addrTemp, address.index, address.scale
2706                 addu    addrTemp, addrTemp, address.base
2707                 sdc1    src, address.offset(addrTemp)
2708             */
2709             m_assembler.sll(addrTempRegister, address.index, address.scale);
2710             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2711             m_assembler.sdc1(src, addrTempRegister, address.offset);
2712         } else {
2713             /*
2714                 sll     addrTemp, address.index, address.scale
2715                 addu    addrTemp, addrTemp, address.base
2716                 lui     immTemp, (address.offset + 0x8000) >> 16
2717                 addu    addrTemp, addrTemp, immTemp
2718                 sdc1    src, (address.offset & 0xffff)(at)
2719             */
2720             m_assembler.sll(addrTempRegister, address.index, address.scale);
2721             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
2722             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
2723             m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
2724             m_assembler.sdc1(src, addrTempRegister, address.offset);
2725         }
2726 #endif
2727     }
2728
2729     void storeDouble(FPRegisterID src, TrustedImmPtr address)
2730     {
2731 #if WTF_MIPS_ISA(1)
2732         move(address, addrTempRegister);
2733         m_assembler.swc1(src, addrTempRegister, 0);
2734         m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4);
2735 #else
2736         move(address, addrTempRegister);
2737         m_assembler.sdc1(src, addrTempRegister, 0);
2738 #endif
2739     }
2740
2741     void moveDouble(FPRegisterID src, FPRegisterID dest)
2742     {
2743         if (src != dest || m_fixedWidth)
2744             m_assembler.movd(dest, src);
2745     }
2746
2747     void moveZeroToDouble(FPRegisterID reg)
2748     {
2749         convertInt32ToDouble(MIPSRegisters::zero, reg);
2750     }
2751
2752     void swapDouble(FPRegisterID fr1, FPRegisterID fr2)
2753     {
2754         moveDouble(fr1, fpTempRegister);
2755         moveDouble(fr2, fr1);
2756         moveDouble(fpTempRegister, fr2);
2757     }
2758
2759     void addDouble(FPRegisterID src, FPRegisterID dest)
2760     {
2761         m_assembler.addd(dest, dest, src);
2762     }
2763
2764     void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
2765     {
2766         m_assembler.addd(dest, op1, op2);
2767     }
2768
2769     void addDouble(Address src, FPRegisterID dest)
2770     {
2771         loadDouble(src, fpTempRegister);
2772         m_assembler.addd(dest, dest, fpTempRegister);
2773     }
2774
2775     void addDouble(AbsoluteAddress address, FPRegisterID dest)
2776     {
2777         loadDouble(TrustedImmPtr(address.m_ptr), fpTempRegister);
2778         m_assembler.addd(dest, dest, fpTempRegister);
2779     }
2780
2781     void subDouble(FPRegisterID src, FPRegisterID dest)
2782     {
2783         m_assembler.subd(dest, dest, src);
2784     }
2785
2786     void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
2787     {
2788         m_assembler.subd(dest, op1, op2);
2789     }
2790
2791     void subDouble(Address src, FPRegisterID dest)
2792     {
2793         loadDouble(src, fpTempRegister);
2794         m_assembler.subd(dest, dest, fpTempRegister);
2795     }
2796
2797     void mulDouble(FPRegisterID src, FPRegisterID dest)
2798     {
2799         m_assembler.muld(dest, dest, src);
2800     }
2801
2802     void mulDouble(Address src, FPRegisterID dest)
2803     {
2804         loadDouble(src, fpTempRegister);
2805         m_assembler.muld(dest, dest, fpTempRegister);
2806     }
2807
2808     void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
2809     {
2810         m_assembler.muld(dest, op1, op2);
2811     }
2812
2813     void divDouble(FPRegisterID src, FPRegisterID dest)
2814     {
2815         m_assembler.divd(dest, dest, src);
2816     }
2817
2818     void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
2819     {
2820         m_assembler.divd(dest, op1, op2);
2821     }
2822
2823     void divDouble(Address src, FPRegisterID dest)
2824     {
2825         loadDouble(src, fpTempRegister);
2826         m_assembler.divd(dest, dest, fpTempRegister);
2827     }
2828
2829     void negateDouble(FPRegisterID src, FPRegisterID dest)
2830     {
2831         m_assembler.negd(dest, src);
2832     }
2833
2834     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
2835     {
2836         m_assembler.mtc1(src, fpTempRegister);
2837         m_assembler.cvtdw(dest, fpTempRegister);
2838     }
2839
2840     void convertInt32ToDouble(Address src, FPRegisterID dest)
2841     {
2842         load32(src, dataTempRegister);
2843         m_assembler.mtc1(dataTempRegister, fpTempRegister);
2844         m_assembler.cvtdw(dest, fpTempRegister);
2845     }
2846
2847     void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
2848     {
2849         load32(src.m_ptr, dataTempRegister);
2850         m_assembler.mtc1(dataTempRegister, fpTempRegister);
2851         m_assembler.cvtdw(dest, fpTempRegister);
2852     }
2853
2854     void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
2855     {
2856         m_assembler.cvtds(dst, src);
2857     }
2858
2859     void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst)
2860     {
2861         m_assembler.cvtsd(dst, src);
2862     }
2863
2864     void insertRelaxationWords()
2865     {
2866         /* We need four words for relaxation. */
2867         m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 3); // Jump over nops;
2868         m_assembler.nop();
2869         m_assembler.nop();
2870         m_assembler.nop();
2871     }
2872
2873     Jump branchTrue()
2874     {
2875         m_assembler.appendJump();
2876         m_assembler.bc1t();
2877         m_assembler.nop();
2878         insertRelaxationWords();
2879         return Jump(m_assembler.label());
2880     }
2881
2882     Jump branchFalse()
2883     {
2884         m_assembler.appendJump();
2885         m_assembler.bc1f();
2886         m_assembler.nop();
2887         insertRelaxationWords();
2888         return Jump(m_assembler.label());
2889     }
2890
2891     Jump branchEqual(RegisterID rs, RegisterID rt)
2892     {
2893         m_assembler.nop();
2894         m_assembler.nop();
2895         m_assembler.appendJump();
2896         m_assembler.beq(rs, rt, 0);
2897         m_assembler.nop();
2898         insertRelaxationWords();
2899         return Jump(m_assembler.label());
2900     }
2901
2902     Jump branchNotEqual(RegisterID rs, RegisterID rt)
2903     {
2904         m_assembler.nop();
2905         m_assembler.nop();
2906         m_assembler.appendJump();
2907         m_assembler.bne(rs, rt, 0);
2908         m_assembler.nop();
2909         insertRelaxationWords();
2910         return Jump(m_assembler.label());
2911     }
2912
2913     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
2914     {
2915         if (cond == DoubleEqual) {
2916             m_assembler.ceqd(left, right);
2917             return branchTrue();
2918         }
2919         if (cond == DoubleNotEqual) {
2920             m_assembler.cueqd(left, right);
2921             return branchFalse(); // false
2922         }
2923         if (cond == DoubleGreaterThan) {
2924             m_assembler.cngtd(left, right);
2925             return branchFalse(); // false
2926         }
2927         if (cond == DoubleGreaterThanOrEqual) {
2928             m_assembler.cnged(left, right);
2929             return branchFalse(); // false
2930         }
2931         if (cond == DoubleLessThan) {
2932             m_assembler.cltd(left, right);
2933             return branchTrue();
2934         }
2935         if (cond == DoubleLessThanOrEqual) {
2936             m_assembler.cled(left, right);
2937             return branchTrue();
2938         }
2939         if (cond == DoubleEqualOrUnordered) {
2940             m_assembler.cueqd(left, right);
2941             return branchTrue();
2942         }
2943         if (cond == DoubleNotEqualOrUnordered) {
2944             m_assembler.ceqd(left, right);
2945             return branchFalse(); // false
2946         }
2947         if (cond == DoubleGreaterThanOrUnordered) {
2948             m_assembler.coled(left, right);
2949             return branchFalse(); // false
2950         }
2951         if (cond == DoubleGreaterThanOrEqualOrUnordered) {
2952             m_assembler.coltd(left, right);
2953             return branchFalse(); // false
2954         }
2955         if (cond == DoubleLessThanOrUnordered) {
2956             m_assembler.cultd(left, right);
2957             return branchTrue();
2958         }
2959         if (cond == DoubleLessThanOrEqualOrUnordered) {
2960             m_assembler.culed(left, right);
2961             return branchTrue();
2962         }
2963         ASSERT(0);
2964
2965         return Jump();
2966     }
2967
2968     // Truncates 'src' to an integer, and places the resulting 'dest'.
2969     // If the result is not representable as a 32 bit value, branch.
2970     enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
2971
2972     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
2973     {
2974         m_assembler.truncwd(fpTempRegister, src);
2975         m_assembler.cfc1(dataTempRegister, MIPSRegisters::fcsr);
2976         m_assembler.mfc1(dest, fpTempRegister);
2977         and32(TrustedImm32(MIPSAssembler::FP_CAUSE_INVALID_OPERATION), dataTempRegister);
2978         return branch32(branchType == BranchIfTruncateFailed ? NotEqual : Equal, dataTempRegister, MIPSRegisters::zero);
2979     }
2980
2981     // Result is undefined if the value is outside of the integer range.
2982     void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
2983     {
2984         m_assembler.truncwd(fpTempRegister, src);
2985         m_assembler.mfc1(dest, fpTempRegister);
2986     }
2987
2988     // Result is undefined if src > 2^31
2989     void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
2990     {
2991         m_assembler.truncwd(fpTempRegister, src);
2992         m_assembler.mfc1(dest, fpTempRegister);
2993     }
2994
2995     // Convert 'src' to an integer, and places the resulting 'dest'.
2996     // If the result is not representable as a 32 bit value, branch.
2997     // May also branch for some values that are representable in 32 bits
2998     // (specifically, in this case, 0).
2999     void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp, bool negZeroCheck = true)
3000     {
3001         m_assembler.cvtwd(fpTempRegister, src);
3002         m_assembler.mfc1(dest, fpTempRegister);
3003
3004         // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
3005         if (negZeroCheck)
3006             failureCases.append(branch32(Equal, dest, MIPSRegisters::zero));
3007
3008         // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
3009         convertInt32ToDouble(dest, fpTemp);
3010         failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fpTemp, src));
3011     }
3012
3013     Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
3014     {
3015         m_assembler.vmov(scratch, MIPSRegisters::zero, MIPSRegisters::zero);
3016         return branchDouble(DoubleNotEqual, reg, scratch);
3017     }
3018
3019     Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
3020     {
3021         m_assembler.vmov(scratch, MIPSRegisters::zero, MIPSRegisters::zero);
3022         return branchDouble(DoubleEqualOrUnordered, reg, scratch);
3023     }
3024
3025     // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc.
3026     static RelationalCondition invert(RelationalCondition cond)
3027     {
3028         RelationalCondition r;
3029         if (cond == Equal)
3030             r = NotEqual;
3031         else if (cond == NotEqual)
3032             r = Equal;
3033         else if (cond == Above)
3034             r = BelowOrEqual;
3035         else if (cond == AboveOrEqual)
3036             r = Below;
3037         else if (cond == Below)
3038             r = AboveOrEqual;
3039         else if (cond == BelowOrEqual)
3040             r = Above;
3041         else if (cond == GreaterThan)
3042             r = LessThanOrEqual;
3043         else if (cond == GreaterThanOrEqual)
3044             r = LessThan;
3045         else if (cond == LessThan)
3046             r = GreaterThanOrEqual;
3047         else if (cond == LessThanOrEqual)
3048             r = GreaterThan;
3049         return r;
3050     }
3051
3052     void nop()
3053     {
3054         m_assembler.nop();
3055     }
3056
3057     void memoryFence()
3058     {
3059         m_assembler.sync();
3060     }
3061
3062     void abortWithReason(AbortReason reason)
3063     {
3064         move(TrustedImm32(reason), dataTempRegister);
3065         breakpoint();
3066     }
3067
3068     void storeFence()
3069     {
3070         m_assembler.sync();
3071     }
3072
3073     void abortWithReason(AbortReason reason, intptr_t misc)
3074     {
3075         move(TrustedImm32(misc), immTempRegister);
3076         abortWithReason(reason);
3077     }
3078
3079     static FunctionPtr readCallTarget(CodeLocationCall call)
3080     {
3081         return FunctionPtr(reinterpret_cast<void(*)()>(MIPSAssembler::readCallTarget(call.dataLocation())));
3082     }
3083
3084     static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
3085     {
3086         MIPSAssembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation());
3087     }
3088     
3089     static ptrdiff_t maxJumpReplacementSize()
3090     {
3091         MIPSAssembler::maxJumpReplacementSize();
3092         return 0;
3093     }
3094
3095     static ptrdiff_t patchableJumpSize()
3096     {
3097         return MIPSAssembler::patchableJumpSize();
3098     }
3099
3100     static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; }
3101     static bool canJumpReplacePatchableBranch32WithPatch() { return false; }
3102
3103     static CodeLocationLabel startOfPatchableBranch32WithPatchOnAddress(CodeLocationDataLabel32)
3104     {
3105         UNREACHABLE_FOR_PLATFORM();
3106         return CodeLocationLabel();
3107     }
3108
3109     static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label)
3110     {
3111         return label.labelAtOffset(0);
3112     }
3113
3114     static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID, void* initialValue)
3115     {
3116         MIPSAssembler::revertJumpToMove(instructionStart.dataLocation(), immTempRegister, reinterpret_cast<int>(initialValue) & 0xffff);
3117     }
3118
3119     static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr)
3120     {
3121         UNREACHABLE_FOR_PLATFORM();
3122         return CodeLocationLabel();
3123     }
3124
3125     static void revertJumpReplacementToPatchableBranch32WithPatch(CodeLocationLabel, Address, int32_t)
3126     {
3127         UNREACHABLE_FOR_PLATFORM();
3128     }
3129
3130     static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel, Address, void*)
3131     {
3132         UNREACHABLE_FOR_PLATFORM();
3133     }
3134
3135     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
3136     {
3137         MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
3138     }
3139
3140     static void repatchCall(CodeLocationCall call, FunctionPtr destination)
3141     {
3142         MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
3143     }
3144
3145 private:
3146     // If m_fixedWidth is true, we will generate a fixed number of instructions.
3147     // Otherwise, we can emit any number of instructions.
3148     bool m_fixedWidth;
3149
3150     friend class LinkBuffer;
3151
3152     static void linkCall(void* code, Call call, FunctionPtr function)
3153     {
3154         if (call.isFlagSet(Call::Tail))
3155             MIPSAssembler::linkJump(code, call.m_label, function.value());
3156         else
3157             MIPSAssembler::linkCall(code, call.m_label, function.value());
3158     }
3159
3160 };
3161
3162 } // namespace JSC
3163
3164 #endif // ENABLE(ASSEMBLER) && CPU(MIPS)