Tizen 2.1 base
[framework/web/webkit-efl.git] / Source / JavaScriptCore / assembler / MacroAssemblerMIPS.h
1 /*
2  * Copyright (C) 2008 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 #ifndef MacroAssemblerMIPS_h
28 #define MacroAssemblerMIPS_h
29
30 #if ENABLE(ASSEMBLER) && CPU(MIPS)
31
32 #include "MIPSAssembler.h"
33 #include "AbstractMacroAssembler.h"
34
35 namespace JSC {
36
37 class MacroAssemblerMIPS : public AbstractMacroAssembler<MIPSAssembler> {
38 public:
39     typedef MIPSRegisters::FPRegisterID FPRegisterID;
40
41     MacroAssemblerMIPS()
42         : m_fixedWidth(false)
43     {
44     }
45
46     static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value)
47     {
48         return value >= -2147483647 - 1 && value <= 2147483647;
49     }
50
51     static const Scale ScalePtr = TimesFour;
52
53     // For storing immediate number
54     static const RegisterID immTempRegister = MIPSRegisters::t0;
55     // For storing data loaded from the memory
56     static const RegisterID dataTempRegister = MIPSRegisters::t1;
57     // For storing address base
58     static const RegisterID addrTempRegister = MIPSRegisters::t2;
59     // For storing compare result
60     static const RegisterID cmpTempRegister = MIPSRegisters::t3;
61
62     // FP temp register
63     static const FPRegisterID fpTempRegister = MIPSRegisters::f16;
64
65     static const int MaximumCompactPtrAlignedAddressOffset = 0x7FFFFFFF;
66
67     enum RelationalCondition {
68         Equal,
69         NotEqual,
70         Above,
71         AboveOrEqual,
72         Below,
73         BelowOrEqual,
74         GreaterThan,
75         GreaterThanOrEqual,
76         LessThan,
77         LessThanOrEqual
78     };
79
80     enum ResultCondition {
81         Overflow,
82         Signed,
83         Zero,
84         NonZero
85     };
86
87     enum DoubleCondition {
88         DoubleEqual,
89         DoubleNotEqual,
90         DoubleGreaterThan,
91         DoubleGreaterThanOrEqual,
92         DoubleLessThan,
93         DoubleLessThanOrEqual,
94         DoubleEqualOrUnordered,
95         DoubleNotEqualOrUnordered,
96         DoubleGreaterThanOrUnordered,
97         DoubleGreaterThanOrEqualOrUnordered,
98         DoubleLessThanOrUnordered,
99         DoubleLessThanOrEqualOrUnordered
100     };
101
102     static const RegisterID stackPointerRegister = MIPSRegisters::sp;
103     static const RegisterID returnAddressRegister = MIPSRegisters::ra;
104
105     // Integer arithmetic operations:
106     //
107     // Operations are typically two operand - operation(source, srcDst)
108     // For many operations the source may be an TrustedImm32, the srcDst operand
109     // may often be a memory location (explictly described using an Address
110     // object).
111
112     void add32(RegisterID src, RegisterID dest)
113     {
114         m_assembler.addu(dest, dest, src);
115     }
116
117     void add32(TrustedImm32 imm, RegisterID dest)
118     {
119         add32(imm, dest, dest);
120     }
121
122     void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
123     {
124         if (imm.m_value >= -32768 && imm.m_value <= 32767
125             && !m_fixedWidth) {
126             /*
127               addiu     dest, src, imm
128             */
129             m_assembler.addiu(dest, src, imm.m_value);
130         } else {
131             /*
132               li        immTemp, imm
133               addu      dest, src, immTemp
134             */
135             move(imm, immTempRegister);
136             m_assembler.addu(dest, src, immTempRegister);
137         }
138     }
139
140     void add32(RegisterID src, TrustedImm32 imm, RegisterID dest)
141     {
142         add32(imm, src, dest);
143     }
144
145     void add32(TrustedImm32 imm, Address address)
146     {
147         if (address.offset >= -32768 && address.offset <= 32767
148             && !m_fixedWidth) {
149             /*
150               lw        dataTemp, offset(base)
151               li        immTemp, imm
152               addu      dataTemp, dataTemp, immTemp
153               sw        dataTemp, offset(base)
154             */
155             m_assembler.lw(dataTempRegister, address.base, address.offset);
156             if (imm.m_value >= -32768 && imm.m_value <= 32767
157                 && !m_fixedWidth)
158                 m_assembler.addiu(dataTempRegister, dataTempRegister,
159                                   imm.m_value);
160             else {
161                 move(imm, immTempRegister);
162                 m_assembler.addu(dataTempRegister, dataTempRegister,
163                                  immTempRegister);
164             }
165             m_assembler.sw(dataTempRegister, address.base, address.offset);
166         } else {
167             /*
168               lui       addrTemp, (offset + 0x8000) >> 16
169               addu      addrTemp, addrTemp, base
170               lw        dataTemp, (offset & 0xffff)(addrTemp)
171               li        immtemp, imm
172               addu      dataTemp, dataTemp, immTemp
173               sw        dataTemp, (offset & 0xffff)(addrTemp)
174             */
175             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
176             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
177             m_assembler.lw(dataTempRegister, addrTempRegister, address.offset);
178
179             if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth)
180                 m_assembler.addiu(dataTempRegister, dataTempRegister,
181                                   imm.m_value);
182             else {
183                 move(imm, immTempRegister);
184                 m_assembler.addu(dataTempRegister, dataTempRegister,
185                                  immTempRegister);
186             }
187             m_assembler.sw(dataTempRegister, addrTempRegister, address.offset);
188         }
189     }
190
191     void add32(Address src, RegisterID dest)
192     {
193         load32(src, dataTempRegister);
194         add32(dataTempRegister, dest);
195     }
196
197     void add32(AbsoluteAddress src, RegisterID dest)
198     {
199         load32(src.m_ptr, dataTempRegister);
200         add32(dataTempRegister, dest);
201     }
202
203     void add32(RegisterID src, Address dest)
204     {
205         if (dest.offset >= -32768 && dest.offset <= 32767 && !m_fixedWidth) {
206             /*
207               lw        dataTemp, offset(base)
208               addu      dataTemp, dataTemp, src
209               sw        dataTemp, offset(base)
210             */
211             m_assembler.lw(dataTempRegister, dest.base, dest.offset);
212             m_assembler.addu(dataTempRegister, dataTempRegister, src);
213             m_assembler.sw(dataTempRegister, dest.base, dest.offset);
214         } else {
215             /*
216               lui       addrTemp, (offset + 0x8000) >> 16
217               addu      addrTemp, addrTemp, base
218               lw        dataTemp, (offset & 0xffff)(addrTemp)
219               addu      dataTemp, dataTemp, src
220               sw        dataTemp, (offset & 0xffff)(addrTemp)
221             */
222             m_assembler.lui(addrTempRegister, (dest.offset + 0x8000) >> 16);
223             m_assembler.addu(addrTempRegister, addrTempRegister, dest.base);
224             m_assembler.lw(dataTempRegister, addrTempRegister, dest.offset);
225             m_assembler.addu(dataTempRegister, dataTempRegister, src);
226             m_assembler.sw(dataTempRegister, addrTempRegister, dest.offset);
227         }
228     }
229
230     void add32(TrustedImm32 imm, AbsoluteAddress address)
231     {
232         /*
233            li   addrTemp, address
234            li   immTemp, imm
235            lw   dataTemp, 0(addrTemp)
236            addu dataTemp, dataTemp, immTemp
237            sw   dataTemp, 0(addrTemp)
238         */
239         move(TrustedImmPtr(address.m_ptr), addrTempRegister);
240         m_assembler.lw(dataTempRegister, addrTempRegister, 0);
241         if (imm.m_value >= -32768 && imm.m_value <= 32767
242             && !m_fixedWidth)
243             m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value);
244         else {
245             move(imm, immTempRegister);
246             m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister);
247         }
248         m_assembler.sw(dataTempRegister, addrTempRegister, 0);
249     }
250
251     void and32(RegisterID src, RegisterID dest)
252     {
253         m_assembler.andInsn(dest, dest, src);
254     }
255
256     void and32(TrustedImm32 imm, RegisterID dest)
257     {
258         if (!imm.m_value && !m_fixedWidth)
259             move(MIPSRegisters::zero, dest);
260         else if (imm.m_value > 0 && imm.m_value < 65535
261                  && !m_fixedWidth)
262             m_assembler.andi(dest, dest, imm.m_value);
263         else {
264             /*
265               li        immTemp, imm
266               and       dest, dest, immTemp
267             */
268             move(imm, immTempRegister);
269             m_assembler.andInsn(dest, dest, immTempRegister);
270         }
271     }
272
273     void lshift32(TrustedImm32 imm, RegisterID dest)
274     {
275         m_assembler.sll(dest, dest, imm.m_value);
276     }
277
278     void lshift32(RegisterID shiftAmount, RegisterID dest)
279     {
280         m_assembler.sllv(dest, dest, shiftAmount);
281     }
282
283     void mul32(RegisterID src, RegisterID dest)
284     {
285         m_assembler.mul(dest, dest, src);
286     }
287
288     void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
289     {
290         if (!imm.m_value && !m_fixedWidth)
291             move(MIPSRegisters::zero, dest);
292         else if (imm.m_value == 1 && !m_fixedWidth)
293             move(src, dest);
294         else {
295             /*
296                 li      dataTemp, imm
297                 mul     dest, src, dataTemp
298             */
299             move(imm, dataTempRegister);
300             m_assembler.mul(dest, src, dataTempRegister);
301         }
302     }
303
304     void neg32(RegisterID srcDest)
305     {
306         m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest);
307     }
308
309     void or32(RegisterID src, RegisterID dest)
310     {
311         m_assembler.orInsn(dest, dest, src);
312     }
313
314     void or32(RegisterID op1, RegisterID op2, RegisterID dest)
315     {
316         m_assembler.orInsn(dest, op1, op2);
317     }
318
319     void or32(TrustedImm32 imm, RegisterID dest)
320     {
321         if (!imm.m_value && !m_fixedWidth)
322             return;
323
324         if (imm.m_value > 0 && imm.m_value < 65535
325             && !m_fixedWidth) {
326             m_assembler.ori(dest, dest, imm.m_value);
327             return;
328         }
329
330         /*
331             li      dataTemp, imm
332             or      dest, dest, dataTemp
333         */
334         move(imm, dataTempRegister);
335         m_assembler.orInsn(dest, dest, dataTempRegister);
336     }
337
338     void rshift32(RegisterID shiftAmount, RegisterID dest)
339     {
340         m_assembler.srav(dest, dest, shiftAmount);
341     }
342
343     void rshift32(TrustedImm32 imm, RegisterID dest)
344     {
345         m_assembler.sra(dest, dest, imm.m_value);
346     }
347
348     void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
349     {
350         m_assembler.sra(dest, src, imm.m_value);
351     }
352
353     void urshift32(RegisterID shiftAmount, RegisterID dest)
354     {
355         m_assembler.srlv(dest, dest, shiftAmount);
356     }
357
358     void urshift32(TrustedImm32 imm, RegisterID dest)
359     {
360         m_assembler.srl(dest, dest, imm.m_value);
361     }
362
363     void sub32(RegisterID src, RegisterID dest)
364     {
365         m_assembler.subu(dest, dest, src);
366     }
367
368     void sub32(TrustedImm32 imm, RegisterID dest)
369     {
370         if (imm.m_value >= -32767 && imm.m_value <= 32768
371             && !m_fixedWidth) {
372             /*
373               addiu     dest, src, imm
374             */
375             m_assembler.addiu(dest, dest, -imm.m_value);
376         } else {
377             /*
378               li        immTemp, imm
379               subu      dest, src, immTemp
380             */
381             move(imm, immTempRegister);
382             m_assembler.subu(dest, dest, immTempRegister);
383         }
384     }
385
386     void sub32(RegisterID src, TrustedImm32 imm, RegisterID dest)
387     {
388         if (imm.m_value >= -32767 && imm.m_value <= 32768
389             && !m_fixedWidth) {
390             /*
391               addiu     dest, src, imm
392             */
393             m_assembler.addiu(dest, src, -imm.m_value);
394         } else {
395             /*
396               li        immTemp, imm
397               subu      dest, src, immTemp
398             */
399             move(imm, immTempRegister);
400             m_assembler.subu(dest, src, immTempRegister);
401         }
402     }
403
404     void sub32(TrustedImm32 imm, Address address)
405     {
406         if (address.offset >= -32768 && address.offset <= 32767
407             && !m_fixedWidth) {
408             /*
409               lw        dataTemp, offset(base)
410               li        immTemp, imm
411               subu      dataTemp, dataTemp, immTemp
412               sw        dataTemp, offset(base)
413             */
414             m_assembler.lw(dataTempRegister, address.base, address.offset);
415             if (imm.m_value >= -32767 && imm.m_value <= 32768
416                 && !m_fixedWidth)
417                 m_assembler.addiu(dataTempRegister, dataTempRegister,
418                                   -imm.m_value);
419             else {
420                 move(imm, immTempRegister);
421                 m_assembler.subu(dataTempRegister, dataTempRegister,
422                                  immTempRegister);
423             }
424             m_assembler.sw(dataTempRegister, address.base, address.offset);
425         } else {
426             /*
427               lui       addrTemp, (offset + 0x8000) >> 16
428               addu      addrTemp, addrTemp, base
429               lw        dataTemp, (offset & 0xffff)(addrTemp)
430               li        immtemp, imm
431               subu      dataTemp, dataTemp, immTemp
432               sw        dataTemp, (offset & 0xffff)(addrTemp)
433             */
434             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
435             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
436             m_assembler.lw(dataTempRegister, addrTempRegister, address.offset);
437
438             if (imm.m_value >= -32767 && imm.m_value <= 32768
439                 && !m_fixedWidth)
440                 m_assembler.addiu(dataTempRegister, dataTempRegister,
441                                   -imm.m_value);
442             else {
443                 move(imm, immTempRegister);
444                 m_assembler.subu(dataTempRegister, dataTempRegister,
445                                  immTempRegister);
446             }
447             m_assembler.sw(dataTempRegister, addrTempRegister, address.offset);
448         }
449     }
450
451     void sub32(Address src, RegisterID dest)
452     {
453         load32(src, dataTempRegister);
454         sub32(dataTempRegister, dest);
455     }
456
457     void sub32(TrustedImm32 imm, AbsoluteAddress address)
458     {
459         /*
460            li   addrTemp, address
461            li   immTemp, imm
462            lw   dataTemp, 0(addrTemp)
463            subu dataTemp, dataTemp, immTemp
464            sw   dataTemp, 0(addrTemp)
465         */
466         move(TrustedImmPtr(address.m_ptr), addrTempRegister);
467         m_assembler.lw(dataTempRegister, addrTempRegister, 0);
468
469         if (imm.m_value >= -32767 && imm.m_value <= 32768
470             && !m_fixedWidth) {
471             m_assembler.addiu(dataTempRegister, dataTempRegister,
472                               -imm.m_value);
473         } else {
474             move(imm, immTempRegister);
475             m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister);
476         }
477         m_assembler.sw(dataTempRegister, addrTempRegister, 0);
478     }
479
480     void xor32(RegisterID src, RegisterID dest)
481     {
482         m_assembler.xorInsn(dest, dest, src);
483     }
484
485     void xor32(TrustedImm32 imm, RegisterID dest)
486     {
487         if (imm.m_value == -1) {
488             m_assembler.nor(dest, dest, MIPSRegisters::zero);
489             return;
490         }
491
492         /*
493             li  immTemp, imm
494             xor dest, dest, immTemp
495         */
496         move(imm, immTempRegister);
497         m_assembler.xorInsn(dest, dest, immTempRegister);
498     }
499
500     void sqrtDouble(FPRegisterID src, FPRegisterID dst)
501     {
502         m_assembler.sqrtd(dst, src);
503     }
504     
505     void absDouble(FPRegisterID, FPRegisterID)
506     {
507         ASSERT_NOT_REACHED();
508     }
509
510     ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest)
511     {
512         ConvertibleLoadLabel result(this);
513         /*
514             lui     addrTemp, (offset + 0x8000) >> 16
515             addu    addrTemp, addrTemp, base
516             lw      dest, (offset & 0xffff)(addrTemp)
517         */
518         m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
519         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
520         m_assembler.lw(dest, addrTempRegister, address.offset);
521         return result;
522     }
523
524     // Memory access operations:
525     //
526     // Loads are of the form load(address, destination) and stores of the form
527     // store(source, address).  The source for a store may be an TrustedImm32.  Address
528     // operand objects to loads and store will be implicitly constructed if a
529     // register is passed.
530
531     /* Need to use zero-extened load byte for load8.  */
532     void load8(ImplicitAddress address, RegisterID dest)
533     {
534         if (address.offset >= -32768 && address.offset <= 32767
535             && !m_fixedWidth)
536             m_assembler.lbu(dest, address.base, address.offset);
537         else {
538             /*
539                 lui     addrTemp, (offset + 0x8000) >> 16
540                 addu    addrTemp, addrTemp, base
541                 lbu     dest, (offset & 0xffff)(addrTemp)
542               */
543             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
544             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
545             m_assembler.lbu(dest, addrTempRegister, address.offset);
546         }
547     }
548
549     void load8(BaseIndex address, RegisterID dest)
550     {
551         if (address.offset >= -32768 && address.offset <= 32767
552             && !m_fixedWidth) {
553             /*
554              sll     addrTemp, address.index, address.scale
555              addu    addrTemp, addrTemp, address.base
556              lbu     dest, address.offset(addrTemp)
557              */
558             m_assembler.sll(addrTempRegister, address.index, address.scale);
559             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
560             m_assembler.lbu(dest, addrTempRegister, address.offset);
561         } else {
562             /*
563              sll     addrTemp, address.index, address.scale
564              addu    addrTemp, addrTemp, address.base
565              lui     immTemp, (address.offset + 0x8000) >> 16
566              addu    addrTemp, addrTemp, immTemp
567              lbu     dest, (address.offset & 0xffff)(at)
568              */
569             m_assembler.sll(addrTempRegister, address.index, address.scale);
570             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
571             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
572             m_assembler.addu(addrTempRegister, addrTempRegister,
573                              immTempRegister);
574             m_assembler.lbu(dest, addrTempRegister, address.offset);
575         }
576     }
577
578     void load32(ImplicitAddress address, RegisterID dest)
579     {
580         if (address.offset >= -32768 && address.offset <= 32767
581             && !m_fixedWidth)
582             m_assembler.lw(dest, address.base, address.offset);
583         else {
584             /*
585                 lui     addrTemp, (offset + 0x8000) >> 16
586                 addu    addrTemp, addrTemp, base
587                 lw      dest, (offset & 0xffff)(addrTemp)
588               */
589             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
590             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
591             m_assembler.lw(dest, addrTempRegister, address.offset);
592         }
593     }
594
595     void load32(BaseIndex address, RegisterID dest)
596     {
597         if (address.offset >= -32768 && address.offset <= 32767
598             && !m_fixedWidth) {
599             /*
600                 sll     addrTemp, address.index, address.scale
601                 addu    addrTemp, addrTemp, address.base
602                 lw      dest, address.offset(addrTemp)
603             */
604             m_assembler.sll(addrTempRegister, address.index, address.scale);
605             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
606             m_assembler.lw(dest, addrTempRegister, address.offset);
607         } else {
608             /*
609                 sll     addrTemp, address.index, address.scale
610                 addu    addrTemp, addrTemp, address.base
611                 lui     immTemp, (address.offset + 0x8000) >> 16
612                 addu    addrTemp, addrTemp, immTemp
613                 lw      dest, (address.offset & 0xffff)(at)
614             */
615             m_assembler.sll(addrTempRegister, address.index, address.scale);
616             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
617             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
618             m_assembler.addu(addrTempRegister, addrTempRegister,
619                              immTempRegister);
620             m_assembler.lw(dest, addrTempRegister, address.offset);
621         }
622     }
623
624     void load16Unaligned(BaseIndex address, RegisterID dest)
625     {
626         load16(address, dest);
627     }
628
629     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
630     {
631         if (address.offset >= -32768 && address.offset <= 32764
632             && !m_fixedWidth) {
633             /*
634                 sll     addrTemp, address.index, address.scale
635                 addu    addrTemp, addrTemp, address.base
636                 (Big-Endian)
637                 lwl     dest, address.offset(addrTemp)
638                 lwr     dest, address.offset+3(addrTemp)
639                 (Little-Endian)
640                 lwl     dest, address.offset+3(addrTemp)
641                 lwr     dest, address.offset(addrTemp)
642             */
643             m_assembler.sll(addrTempRegister, address.index, address.scale);
644             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
645 #if CPU(BIG_ENDIAN)
646             m_assembler.lwl(dest, addrTempRegister, address.offset);
647             m_assembler.lwr(dest, addrTempRegister, address.offset + 3);
648 #else
649             m_assembler.lwl(dest, addrTempRegister, address.offset + 3);
650             m_assembler.lwr(dest, addrTempRegister, address.offset);
651
652 #endif
653         } else {
654             /*
655                 sll     addrTemp, address.index, address.scale
656                 addu    addrTemp, addrTemp, address.base
657                 lui     immTemp, address.offset >> 16
658                 ori     immTemp, immTemp, address.offset & 0xffff
659                 addu    addrTemp, addrTemp, immTemp
660                 (Big-Endian)
661                 lw      dest, 0(at)
662                 lw      dest, 3(at)
663                 (Little-Endian)
664                 lw      dest, 3(at)
665                 lw      dest, 0(at)
666             */
667             m_assembler.sll(addrTempRegister, address.index, address.scale);
668             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
669             m_assembler.lui(immTempRegister, address.offset >> 16);
670             m_assembler.ori(immTempRegister, immTempRegister, address.offset);
671             m_assembler.addu(addrTempRegister, addrTempRegister,
672                              immTempRegister);
673 #if CPU(BIG_ENDIAN)
674             m_assembler.lwl(dest, addrTempRegister, 0);
675             m_assembler.lwr(dest, addrTempRegister, 3);
676 #else
677             m_assembler.lwl(dest, addrTempRegister, 3);
678             m_assembler.lwr(dest, addrTempRegister, 0);
679 #endif
680         }
681     }
682
683     void load32(const void* address, RegisterID dest)
684     {
685         /*
686             li  addrTemp, address
687             lw  dest, 0(addrTemp)
688         */
689         move(TrustedImmPtr(address), addrTempRegister);
690         m_assembler.lw(dest, addrTempRegister, 0);
691     }
692
693     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
694     {
695         m_fixedWidth = true;
696         /*
697             lui addrTemp, address.offset >> 16
698             ori addrTemp, addrTemp, address.offset & 0xffff
699             addu        addrTemp, addrTemp, address.base
700             lw  dest, 0(addrTemp)
701         */
702         DataLabel32 dataLabel(this);
703         move(TrustedImm32(address.offset), addrTempRegister);
704         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
705         m_assembler.lw(dest, addrTempRegister, 0);
706         m_fixedWidth = false;
707         return dataLabel;
708     }
709     
710     DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
711     {
712         DataLabelCompact dataLabel(this);
713         load32WithAddressOffsetPatch(address, dest);
714         return dataLabel;
715     }
716
717     /* Need to use zero-extened load half-word for load16.  */
718     void load16(ImplicitAddress address, RegisterID dest)
719     {
720         if (address.offset >= -32768 && address.offset <= 32767
721             && !m_fixedWidth)
722             m_assembler.lhu(dest, address.base, address.offset);
723         else {
724             /*
725                 lui     addrTemp, (offset + 0x8000) >> 16
726                 addu    addrTemp, addrTemp, base
727                 lhu     dest, (offset & 0xffff)(addrTemp)
728               */
729             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
730             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
731             m_assembler.lhu(dest, addrTempRegister, address.offset);
732         }
733     }
734
735     /* Need to use zero-extened load half-word for load16.  */
736     void load16(BaseIndex address, RegisterID dest)
737     {
738         if (address.offset >= -32768 && address.offset <= 32767
739             && !m_fixedWidth) {
740             /*
741                 sll     addrTemp, address.index, address.scale
742                 addu    addrTemp, addrTemp, address.base
743                 lhu     dest, address.offset(addrTemp)
744             */
745             m_assembler.sll(addrTempRegister, address.index, address.scale);
746             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
747             m_assembler.lhu(dest, addrTempRegister, address.offset);
748         } else {
749             /*
750                 sll     addrTemp, address.index, address.scale
751                 addu    addrTemp, addrTemp, address.base
752                 lui     immTemp, (address.offset + 0x8000) >> 16
753                 addu    addrTemp, addrTemp, immTemp
754                 lhu     dest, (address.offset & 0xffff)(addrTemp)
755             */
756             m_assembler.sll(addrTempRegister, address.index, address.scale);
757             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
758             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
759             m_assembler.addu(addrTempRegister, addrTempRegister,
760                              immTempRegister);
761             m_assembler.lhu(dest, addrTempRegister, address.offset);
762         }
763     }
764
765     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
766     {
767         m_fixedWidth = true;
768         /*
769             lui addrTemp, address.offset >> 16
770             ori addrTemp, addrTemp, address.offset & 0xffff
771             addu        addrTemp, addrTemp, address.base
772             sw  src, 0(addrTemp)
773         */
774         DataLabel32 dataLabel(this);
775         move(TrustedImm32(address.offset), addrTempRegister);
776         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
777         m_assembler.sw(src, addrTempRegister, 0);
778         m_fixedWidth = false;
779         return dataLabel;
780     }
781
782     void store32(RegisterID src, ImplicitAddress address)
783     {
784         if (address.offset >= -32768 && address.offset <= 32767
785             && !m_fixedWidth)
786             m_assembler.sw(src, address.base, address.offset);
787         else {
788             /*
789                 lui     addrTemp, (offset + 0x8000) >> 16
790                 addu    addrTemp, addrTemp, base
791                 sw      src, (offset & 0xffff)(addrTemp)
792               */
793             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
794             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
795             m_assembler.sw(src, addrTempRegister, address.offset);
796         }
797     }
798
799     void store32(RegisterID src, BaseIndex address)
800     {
801         if (address.offset >= -32768 && address.offset <= 32767
802             && !m_fixedWidth) {
803             /*
804                 sll     addrTemp, address.index, address.scale
805                 addu    addrTemp, addrTemp, address.base
806                 sw      src, address.offset(addrTemp)
807             */
808             m_assembler.sll(addrTempRegister, address.index, address.scale);
809             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
810             m_assembler.sw(src, addrTempRegister, address.offset);
811         } else {
812             /*
813                 sll     addrTemp, address.index, address.scale
814                 addu    addrTemp, addrTemp, address.base
815                 lui     immTemp, (address.offset + 0x8000) >> 16
816                 addu    addrTemp, addrTemp, immTemp
817                 sw      src, (address.offset & 0xffff)(at)
818             */
819             m_assembler.sll(addrTempRegister, address.index, address.scale);
820             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
821             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
822             m_assembler.addu(addrTempRegister, addrTempRegister,
823                              immTempRegister);
824             m_assembler.sw(src, addrTempRegister, address.offset);
825         }
826     }
827
828     void store32(TrustedImm32 imm, ImplicitAddress address)
829     {
830         if (address.offset >= -32768 && address.offset <= 32767
831             && !m_fixedWidth) {
832             if (!imm.m_value)
833                 m_assembler.sw(MIPSRegisters::zero, address.base,
834                                address.offset);
835             else {
836                 move(imm, immTempRegister);
837                 m_assembler.sw(immTempRegister, address.base, address.offset);
838             }
839         } else {
840             /*
841                 lui     addrTemp, (offset + 0x8000) >> 16
842                 addu    addrTemp, addrTemp, base
843                 sw      immTemp, (offset & 0xffff)(addrTemp)
844               */
845             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
846             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
847             if (!imm.m_value && !m_fixedWidth)
848                 m_assembler.sw(MIPSRegisters::zero, addrTempRegister,
849                                address.offset);
850             else {
851                 move(imm, immTempRegister);
852                 m_assembler.sw(immTempRegister, addrTempRegister,
853                                address.offset);
854             }
855         }
856     }
857
858     void store32(RegisterID src, const void* address)
859     {
860         /*
861             li  addrTemp, address
862             sw  src, 0(addrTemp)
863         */
864         move(TrustedImmPtr(address), addrTempRegister);
865         m_assembler.sw(src, addrTempRegister, 0);
866     }
867
868     void store32(TrustedImm32 imm, const void* address)
869     {
870         /*
871             li  immTemp, imm
872             li  addrTemp, address
873             sw  src, 0(addrTemp)
874         */
875         if (!imm.m_value && !m_fixedWidth) {
876             move(TrustedImmPtr(address), addrTempRegister);
877             m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0);
878         } else {
879             move(imm, immTempRegister);
880             move(TrustedImmPtr(address), addrTempRegister);
881             m_assembler.sw(immTempRegister, addrTempRegister, 0);
882         }
883     }
884
885     // Floating-point operations:
886
887     static bool supportsFloatingPoint()
888     {
889 #if WTF_MIPS_DOUBLE_FLOAT
890         return true;
891 #else
892         return false;
893 #endif
894     }
895
896     static bool supportsFloatingPointTruncate()
897     {
898 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
899         return true;
900 #else
901         return false;
902 #endif
903     }
904
905     static bool supportsFloatingPointSqrt()
906     {
907 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
908         return true;
909 #else
910         return false;
911 #endif
912     }
913     static bool supportsFloatingPointAbs() { return false; }
914
915     // Stack manipulation operations:
916     //
917     // The ABI is assumed to provide a stack abstraction to memory,
918     // containing machine word sized units of data.  Push and pop
919     // operations add and remove a single register sized unit of data
920     // to or from the stack.  Peek and poke operations read or write
921     // values on the stack, without moving the current stack position.
922
923     void pop(RegisterID dest)
924     {
925         m_assembler.lw(dest, MIPSRegisters::sp, 0);
926         m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, 4);
927     }
928
929     void push(RegisterID src)
930     {
931         m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, -4);
932         m_assembler.sw(src, MIPSRegisters::sp, 0);
933     }
934
935     void push(Address address)
936     {
937         load32(address, dataTempRegister);
938         push(dataTempRegister);
939     }
940
941     void push(TrustedImm32 imm)
942     {
943         move(imm, immTempRegister);
944         push(immTempRegister);
945     }
946
947     // Register move operations:
948     //
949     // Move values in registers.
950
951     void move(TrustedImm32 imm, RegisterID dest)
952     {
953         if (!imm.m_value && !m_fixedWidth)
954             move(MIPSRegisters::zero, dest);
955         else if (m_fixedWidth) {
956             m_assembler.lui(dest, imm.m_value >> 16);
957             m_assembler.ori(dest, dest, imm.m_value);
958         } else
959             m_assembler.li(dest, imm.m_value);
960     }
961
962     void move(RegisterID src, RegisterID dest)
963     {
964         if (src != dest || m_fixedWidth)
965             m_assembler.move(dest, src);
966     }
967
968     void move(TrustedImmPtr imm, RegisterID dest)
969     {
970         move(TrustedImm32(imm), dest);
971     }
972
973     void swap(RegisterID reg1, RegisterID reg2)
974     {
975         move(reg1, immTempRegister);
976         move(reg2, reg1);
977         move(immTempRegister, reg2);
978     }
979
980     void signExtend32ToPtr(RegisterID src, RegisterID dest)
981     {
982         if (src != dest || m_fixedWidth)
983             move(src, dest);
984     }
985
986     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
987     {
988         if (src != dest || m_fixedWidth)
989             move(src, dest);
990     }
991
992     // Forwards / external control flow operations:
993     //
994     // This set of jump and conditional branch operations return a Jump
995     // object which may linked at a later point, allow forwards jump,
996     // or jumps that will require external linkage (after the code has been
997     // relocated).
998     //
999     // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
1000     // respecitvely, for unsigned comparisons the names b, a, be, and ae are
1001     // used (representing the names 'below' and 'above').
1002     //
1003     // Operands to the comparision are provided in the expected order, e.g.
1004     // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when
1005     // treated as a signed 32bit value, is less than or equal to 5.
1006     //
1007     // jz and jnz test whether the first operand is equal to zero, and take
1008     // an optional second operand of a mask under which to perform the test.
1009
1010     Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
1011     {
1012         // Make sure the immediate value is unsigned 8 bits.
1013         ASSERT(!(right.m_value & 0xFFFFFF00));
1014         load8(left, dataTempRegister);
1015         move(right, immTempRegister);
1016         return branch32(cond, dataTempRegister, immTempRegister);
1017     }
1018
1019     void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
1020     {
1021         // Make sure the immediate value is unsigned 8 bits.
1022         ASSERT(!(right.m_value & 0xFFFFFF00));
1023         load8(left, dataTempRegister);
1024         move(right, immTempRegister);
1025         compare32(cond, dataTempRegister, immTempRegister, dest);
1026     }
1027
1028     Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1029     {
1030         ASSERT(!(right.m_value & 0xFFFFFF00));
1031         load8(left, dataTempRegister);
1032         // Be careful that the previous load8() uses immTempRegister.
1033         // So, we need to put move() after load8().
1034         move(right, immTempRegister);
1035         return branch32(cond, dataTempRegister, immTempRegister);
1036     }
1037
1038     Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
1039     {
1040         if (cond == Equal)
1041             return branchEqual(left, right);
1042         if (cond == NotEqual)
1043             return branchNotEqual(left, right);
1044         if (cond == Above) {
1045             m_assembler.sltu(cmpTempRegister, right, left);
1046             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1047         }
1048         if (cond == AboveOrEqual) {
1049             m_assembler.sltu(cmpTempRegister, left, right);
1050             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
1051         }
1052         if (cond == Below) {
1053             m_assembler.sltu(cmpTempRegister, left, right);
1054             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1055         }
1056         if (cond == BelowOrEqual) {
1057             m_assembler.sltu(cmpTempRegister, right, left);
1058             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
1059         }
1060         if (cond == GreaterThan) {
1061             m_assembler.slt(cmpTempRegister, right, left);
1062             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1063         }
1064         if (cond == GreaterThanOrEqual) {
1065             m_assembler.slt(cmpTempRegister, left, right);
1066             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
1067         }
1068         if (cond == LessThan) {
1069             m_assembler.slt(cmpTempRegister, left, right);
1070             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1071         }
1072         if (cond == LessThanOrEqual) {
1073             m_assembler.slt(cmpTempRegister, right, left);
1074             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
1075         }
1076         ASSERT(0);
1077
1078         return Jump();
1079     }
1080
1081     Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
1082     {
1083         move(right, immTempRegister);
1084         return branch32(cond, left, immTempRegister);
1085     }
1086
1087     Jump branch32(RelationalCondition cond, RegisterID left, Address right)
1088     {
1089         load32(right, dataTempRegister);
1090         return branch32(cond, left, dataTempRegister);
1091     }
1092
1093     Jump branch32(RelationalCondition cond, Address left, RegisterID right)
1094     {
1095         load32(left, dataTempRegister);
1096         return branch32(cond, dataTempRegister, right);
1097     }
1098
1099     Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
1100     {
1101         load32(left, dataTempRegister);
1102         move(right, immTempRegister);
1103         return branch32(cond, dataTempRegister, immTempRegister);
1104     }
1105
1106     Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1107     {
1108         load32(left, dataTempRegister);
1109         // Be careful that the previous load32() uses immTempRegister.
1110         // So, we need to put move() after load32().
1111         move(right, immTempRegister);
1112         return branch32(cond, dataTempRegister, immTempRegister);
1113     }
1114
1115     Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1116     {
1117         load32WithUnalignedHalfWords(left, dataTempRegister);
1118         // Be careful that the previous load32WithUnalignedHalfWords()
1119         // uses immTempRegister.
1120         // So, we need to put move() after load32WithUnalignedHalfWords().
1121         move(right, immTempRegister);
1122         return branch32(cond, dataTempRegister, immTempRegister);
1123     }
1124
1125     Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
1126     {
1127         load32(left.m_ptr, dataTempRegister);
1128         return branch32(cond, dataTempRegister, right);
1129     }
1130
1131     Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
1132     {
1133         load32(left.m_ptr, dataTempRegister);
1134         move(right, immTempRegister);
1135         return branch32(cond, dataTempRegister, immTempRegister);
1136     }
1137
1138     Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
1139     {
1140         ASSERT((cond == Zero) || (cond == NonZero));
1141         m_assembler.andInsn(cmpTempRegister, reg, mask);
1142         if (cond == Zero)
1143             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
1144         return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1145     }
1146
1147     Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
1148     {
1149         ASSERT((cond == Zero) || (cond == NonZero));
1150         if (mask.m_value == -1 && !m_fixedWidth) {
1151             if (cond == Zero)
1152                 return branchEqual(reg, MIPSRegisters::zero);
1153             return branchNotEqual(reg, MIPSRegisters::zero);
1154         }
1155         move(mask, immTempRegister);
1156         return branchTest32(cond, reg, immTempRegister);
1157     }
1158
1159     Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1160     {
1161         load32(address, dataTempRegister);
1162         return branchTest32(cond, dataTempRegister, mask);
1163     }
1164
1165     Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
1166     {
1167         load32(address, dataTempRegister);
1168         return branchTest32(cond, dataTempRegister, mask);
1169     }
1170
1171     Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1172     {
1173         load8(address, dataTempRegister);
1174         return branchTest32(cond, dataTempRegister, mask);
1175     }
1176
1177     Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
1178     {
1179         move(TrustedImmPtr(address.m_ptr), dataTempRegister);
1180         load8(Address(dataTempRegister), dataTempRegister);
1181         return branchTest32(cond, dataTempRegister, mask);
1182     }
1183
1184     Jump jump()
1185     {
1186         return branchEqual(MIPSRegisters::zero, MIPSRegisters::zero);
1187     }
1188
1189     void jump(RegisterID target)
1190     {
1191         m_assembler.jr(target);
1192         m_assembler.nop();
1193     }
1194
1195     void jump(Address address)
1196     {
1197         m_fixedWidth = true;
1198         load32(address, MIPSRegisters::t9);
1199         m_assembler.jr(MIPSRegisters::t9);
1200         m_assembler.nop();
1201         m_fixedWidth = false;
1202     }
1203
1204     // Arithmetic control flow operations:
1205     //
1206     // This set of conditional branch operations branch based
1207     // on the result of an arithmetic operation.  The operation
1208     // is performed as normal, storing the result.
1209     //
1210     // * jz operations branch if the result is zero.
1211     // * jo operations branch if the (signed) arithmetic
1212     //   operation caused an overflow to occur.
1213
1214     Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
1215     {
1216         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1217         if (cond == Overflow) {
1218             /*
1219                 move    dest, dataTemp
1220                 xor     cmpTemp, dataTemp, src
1221                 bltz    cmpTemp, No_overflow    # diff sign bit -> no overflow
1222                 addu    dest, dataTemp, src
1223                 xor     cmpTemp, dest, dataTemp
1224                 bgez    cmpTemp, No_overflow    # same sign big -> no overflow
1225                 nop
1226                 b       Overflow
1227                 nop
1228                 nop
1229                 nop
1230                 nop
1231                 nop
1232             No_overflow:
1233             */
1234             move(dest, dataTempRegister);
1235             m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src);
1236             m_assembler.bltz(cmpTempRegister, 10);
1237             m_assembler.addu(dest, dataTempRegister, src);
1238             m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
1239             m_assembler.bgez(cmpTempRegister, 7);
1240             m_assembler.nop();
1241             return jump();
1242         }
1243         if (cond == Signed) {
1244             add32(src, dest);
1245             // Check if dest is negative.
1246             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
1247             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1248         }
1249         if (cond == Zero) {
1250             add32(src, dest);
1251             return branchEqual(dest, MIPSRegisters::zero);
1252         }
1253         if (cond == NonZero) {
1254             add32(src, dest);
1255             return branchNotEqual(dest, MIPSRegisters::zero);
1256         }
1257         ASSERT(0);
1258         return Jump();
1259     }
1260
1261     Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
1262     {
1263         move(imm, immTempRegister);
1264         return branchAdd32(cond, immTempRegister, dest);
1265     }
1266
1267     Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
1268     {
1269         move(imm, immTempRegister);
1270         move(src, dest);
1271         return branchAdd32(cond, immTempRegister, dest);
1272     }
1273
1274     Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
1275     {
1276         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1277         if (cond == Overflow) {
1278             /*
1279                 mult    src, dest
1280                 mfhi    dataTemp
1281                 mflo    dest
1282                 sra     addrTemp, dest, 31
1283                 beq     dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow
1284                 nop
1285                 b       Overflow
1286                 nop
1287                 nop
1288                 nop
1289                 nop
1290                 nop
1291             No_overflow:
1292             */
1293             m_assembler.mult(src, dest);
1294             m_assembler.mfhi(dataTempRegister);
1295             m_assembler.mflo(dest);
1296             m_assembler.sra(addrTempRegister, dest, 31);
1297             m_assembler.beq(dataTempRegister, addrTempRegister, 7);
1298             m_assembler.nop();
1299             return jump();
1300         }
1301         if (cond == Signed) {
1302             mul32(src, dest);
1303             // Check if dest is negative.
1304             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
1305             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1306         }
1307         if (cond == Zero) {
1308             mul32(src, dest);
1309             return branchEqual(dest, MIPSRegisters::zero);
1310         }
1311         if (cond == NonZero) {
1312             mul32(src, dest);
1313             return branchNotEqual(dest, MIPSRegisters::zero);
1314         }
1315         ASSERT(0);
1316         return Jump();
1317     }
1318
1319     Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
1320     {
1321         move(imm, immTempRegister);
1322         move(src, dest);
1323         return branchMul32(cond, immTempRegister, dest);
1324     }
1325
1326     Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
1327     {
1328         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1329         if (cond == Overflow) {
1330             /*
1331                 move    dest, dataTemp
1332                 xor     cmpTemp, dataTemp, src
1333                 bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
1334                 subu    dest, dataTemp, src
1335                 xor     cmpTemp, dest, dataTemp
1336                 bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
1337                 nop
1338                 b       Overflow
1339                 nop
1340                 nop
1341                 nop
1342                 nop
1343                 nop
1344             No_overflow:
1345             */
1346             move(dest, dataTempRegister);
1347             m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src);
1348             m_assembler.bgez(cmpTempRegister, 10);
1349             m_assembler.subu(dest, dataTempRegister, src);
1350             m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
1351             m_assembler.bgez(cmpTempRegister, 7);
1352             m_assembler.nop();
1353             return jump();
1354         }
1355         if (cond == Signed) {
1356             sub32(src, dest);
1357             // Check if dest is negative.
1358             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
1359             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1360         }
1361         if (cond == Zero) {
1362             sub32(src, dest);
1363             return branchEqual(dest, MIPSRegisters::zero);
1364         }
1365         if (cond == NonZero) {
1366             sub32(src, dest);
1367             return branchNotEqual(dest, MIPSRegisters::zero);
1368         }
1369         ASSERT(0);
1370         return Jump();
1371     }
1372
1373     Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
1374     {
1375         move(imm, immTempRegister);
1376         return branchSub32(cond, immTempRegister, dest);
1377     }
1378
1379     Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
1380     {
1381         move(imm, immTempRegister);
1382         move(src, dest);
1383         return branchSub32(cond, immTempRegister, dest);
1384     }
1385
1386     Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
1387     {
1388         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
1389         if (cond == Signed) {
1390             or32(src, dest);
1391             // Check if dest is negative.
1392             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
1393             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
1394         }
1395         if (cond == Zero) {
1396             or32(src, dest);
1397             return branchEqual(dest, MIPSRegisters::zero);
1398         }
1399         if (cond == NonZero) {
1400             or32(src, dest);
1401             return branchNotEqual(dest, MIPSRegisters::zero);
1402         }
1403         ASSERT(0);
1404         return Jump();
1405     }
1406
1407     // Miscellaneous operations:
1408
1409     void breakpoint()
1410     {
1411         m_assembler.bkpt();
1412     }
1413
1414     Call nearCall()
1415     {
1416         /* We need two words for relaxation.  */
1417         m_assembler.nop();
1418         m_assembler.nop();
1419         m_assembler.jal();
1420         m_assembler.nop();
1421         return Call(m_assembler.label(), Call::LinkableNear);
1422     }
1423
1424     Call call()
1425     {
1426         m_assembler.lui(MIPSRegisters::t9, 0);
1427         m_assembler.ori(MIPSRegisters::t9, MIPSRegisters::t9, 0);
1428         m_assembler.jalr(MIPSRegisters::t9);
1429         m_assembler.nop();
1430         return Call(m_assembler.label(), Call::Linkable);
1431     }
1432
1433     Call call(RegisterID target)
1434     {
1435         m_assembler.jalr(target);
1436         m_assembler.nop();
1437         return Call(m_assembler.label(), Call::None);
1438     }
1439
1440     Call call(Address address)
1441     {
1442         m_fixedWidth = true;
1443         load32(address, MIPSRegisters::t9);
1444         m_assembler.jalr(MIPSRegisters::t9);
1445         m_assembler.nop();
1446         m_fixedWidth = false;
1447         return Call(m_assembler.label(), Call::None);
1448     }
1449
1450     void ret()
1451     {
1452         m_assembler.jr(MIPSRegisters::ra);
1453         m_assembler.nop();
1454     }
1455
1456     void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
1457     {
1458         if (cond == Equal) {
1459             m_assembler.xorInsn(dest, left, right);
1460             m_assembler.sltiu(dest, dest, 1);
1461         } else if (cond == NotEqual) {
1462             m_assembler.xorInsn(dest, left, right);
1463             m_assembler.sltu(dest, MIPSRegisters::zero, dest);
1464         } else if (cond == Above)
1465             m_assembler.sltu(dest, right, left);
1466         else if (cond == AboveOrEqual) {
1467             m_assembler.sltu(dest, left, right);
1468             m_assembler.xori(dest, dest, 1);
1469         } else if (cond == Below)
1470             m_assembler.sltu(dest, left, right);
1471         else if (cond == BelowOrEqual) {
1472             m_assembler.sltu(dest, right, left);
1473             m_assembler.xori(dest, dest, 1);
1474         } else if (cond == GreaterThan)
1475             m_assembler.slt(dest, right, left);
1476         else if (cond == GreaterThanOrEqual) {
1477             m_assembler.slt(dest, left, right);
1478             m_assembler.xori(dest, dest, 1);
1479         } else if (cond == LessThan)
1480             m_assembler.slt(dest, left, right);
1481         else if (cond == LessThanOrEqual) {
1482             m_assembler.slt(dest, right, left);
1483             m_assembler.xori(dest, dest, 1);
1484         }
1485     }
1486
1487     void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
1488     {
1489         move(right, immTempRegister);
1490         compare32(cond, left, immTempRegister, dest);
1491     }
1492
1493     void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
1494     {
1495         ASSERT((cond == Zero) || (cond == NonZero));
1496         load8(address, dataTempRegister);
1497         if (mask.m_value == -1 && !m_fixedWidth) {
1498             if (cond == Zero)
1499                 m_assembler.sltiu(dest, dataTempRegister, 1);
1500             else
1501                 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister);
1502         } else {
1503             move(mask, immTempRegister);
1504             m_assembler.andInsn(cmpTempRegister, dataTempRegister,
1505                                 immTempRegister);
1506             if (cond == Zero)
1507                 m_assembler.sltiu(dest, cmpTempRegister, 1);
1508             else
1509                 m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister);
1510         }
1511     }
1512
1513     void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
1514     {
1515         ASSERT((cond == Zero) || (cond == NonZero));
1516         load32(address, dataTempRegister);
1517         if (mask.m_value == -1 && !m_fixedWidth) {
1518             if (cond == Zero)
1519                 m_assembler.sltiu(dest, dataTempRegister, 1);
1520             else
1521                 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister);
1522         } else {
1523             move(mask, immTempRegister);
1524             m_assembler.andInsn(cmpTempRegister, dataTempRegister,
1525                                 immTempRegister);
1526             if (cond == Zero)
1527                 m_assembler.sltiu(dest, cmpTempRegister, 1);
1528             else
1529                 m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister);
1530         }
1531     }
1532
1533     DataLabel32 moveWithPatch(TrustedImm32 imm, RegisterID dest)
1534     {
1535         m_fixedWidth = true;
1536         DataLabel32 label(this);
1537         move(imm, dest);
1538         m_fixedWidth = false;
1539         return label;
1540     }
1541
1542     DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
1543     {
1544         m_fixedWidth = true;
1545         DataLabelPtr label(this);
1546         move(initialValue, dest);
1547         m_fixedWidth = false;
1548         return label;
1549     }
1550
1551     Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
1552     {
1553         m_fixedWidth = true;
1554         dataLabel = moveWithPatch(initialRightValue, immTempRegister);
1555         Jump temp = branch32(cond, left, immTempRegister);
1556         m_fixedWidth = false;
1557         return temp;
1558     }
1559
1560     Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
1561     {
1562         m_fixedWidth = true;
1563         load32(left, dataTempRegister);
1564         dataLabel = moveWithPatch(initialRightValue, immTempRegister);
1565         Jump temp = branch32(cond, dataTempRegister, immTempRegister);
1566         m_fixedWidth = false;
1567         return temp;
1568     }
1569
1570     DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
1571     {
1572         m_fixedWidth = true;
1573         DataLabelPtr dataLabel = moveWithPatch(initialValue, dataTempRegister);
1574         store32(dataTempRegister, address);
1575         m_fixedWidth = false;
1576         return dataLabel;
1577     }
1578
1579     DataLabelPtr storePtrWithPatch(ImplicitAddress address)
1580     {
1581         return storePtrWithPatch(TrustedImmPtr(0), address);
1582     }
1583
1584     Call tailRecursiveCall()
1585     {
1586         // Like a normal call, but don't update the returned address register
1587         m_fixedWidth = true;
1588         move(TrustedImm32(0), MIPSRegisters::t9);
1589         m_assembler.jr(MIPSRegisters::t9);
1590         m_assembler.nop();
1591         m_fixedWidth = false;
1592         return Call(m_assembler.label(), Call::Linkable);
1593     }
1594
1595     Call makeTailRecursiveCall(Jump oldJump)
1596     {
1597         oldJump.link(this);
1598         return tailRecursiveCall();
1599     }
1600
1601     void loadDouble(ImplicitAddress address, FPRegisterID dest)
1602     {
1603 #if WTF_MIPS_ISA(1)
1604         /*
1605             li          addrTemp, address.offset
1606             addu        addrTemp, addrTemp, base
1607             lwc1        dest, 0(addrTemp)
1608             lwc1        dest+1, 4(addrTemp)
1609          */
1610         move(TrustedImm32(address.offset), addrTempRegister);
1611         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1612         m_assembler.lwc1(dest, addrTempRegister, 0);
1613         m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4);
1614 #else
1615         if (address.offset >= -32768 && address.offset <= 32767
1616             && !m_fixedWidth) {
1617             m_assembler.ldc1(dest, address.base, address.offset);
1618         } else {
1619             /*
1620                 lui     addrTemp, (offset + 0x8000) >> 16
1621                 addu    addrTemp, addrTemp, base
1622                 ldc1    dest, (offset & 0xffff)(addrTemp)
1623               */
1624             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
1625             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1626             m_assembler.ldc1(dest, addrTempRegister, address.offset);
1627         }
1628 #endif
1629     }
1630
1631     void loadDouble(const void* address, FPRegisterID dest)
1632     {
1633 #if WTF_MIPS_ISA(1)
1634         /*
1635             li          addrTemp, address
1636             lwc1        dest, 0(addrTemp)
1637             lwc1        dest+1, 4(addrTemp)
1638          */
1639         move(TrustedImmPtr(address), addrTempRegister);
1640         m_assembler.lwc1(dest, addrTempRegister, 0);
1641         m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4);
1642 #else
1643         /*
1644             li          addrTemp, address
1645             ldc1        dest, 0(addrTemp)
1646         */
1647         move(TrustedImmPtr(address), addrTempRegister);
1648         m_assembler.ldc1(dest, addrTempRegister, 0);
1649 #endif
1650     }
1651
1652
1653     void storeDouble(FPRegisterID src, ImplicitAddress address)
1654     {
1655 #if WTF_MIPS_ISA(1)
1656         /*
1657             li          addrTemp, address.offset
1658             addu        addrTemp, addrTemp, base
1659             swc1        dest, 0(addrTemp)
1660             swc1        dest+1, 4(addrTemp)
1661          */
1662         move(TrustedImm32(address.offset), addrTempRegister);
1663         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1664         m_assembler.swc1(src, addrTempRegister, 0);
1665         m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4);
1666 #else
1667         if (address.offset >= -32768 && address.offset <= 32767
1668             && !m_fixedWidth)
1669             m_assembler.sdc1(src, address.base, address.offset);
1670         else {
1671             /*
1672                 lui     addrTemp, (offset + 0x8000) >> 16
1673                 addu    addrTemp, addrTemp, base
1674                 sdc1    src, (offset & 0xffff)(addrTemp)
1675               */
1676             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
1677             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
1678             m_assembler.sdc1(src, addrTempRegister, address.offset);
1679         }
1680 #endif
1681     }
1682
1683     void addDouble(FPRegisterID src, FPRegisterID dest)
1684     {
1685         m_assembler.addd(dest, dest, src);
1686     }
1687
1688     void addDouble(Address src, FPRegisterID dest)
1689     {
1690         loadDouble(src, fpTempRegister);
1691         m_assembler.addd(dest, dest, fpTempRegister);
1692     }
1693
1694     void subDouble(FPRegisterID src, FPRegisterID dest)
1695     {
1696         m_assembler.subd(dest, dest, src);
1697     }
1698
1699     void subDouble(Address src, FPRegisterID dest)
1700     {
1701         loadDouble(src, fpTempRegister);
1702         m_assembler.subd(dest, dest, fpTempRegister);
1703     }
1704
1705     void mulDouble(FPRegisterID src, FPRegisterID dest)
1706     {
1707         m_assembler.muld(dest, dest, src);
1708     }
1709
1710     void mulDouble(Address src, FPRegisterID dest)
1711     {
1712         loadDouble(src, fpTempRegister);
1713         m_assembler.muld(dest, dest, fpTempRegister);
1714     }
1715
1716     void divDouble(FPRegisterID src, FPRegisterID dest)
1717     {
1718         m_assembler.divd(dest, dest, src);
1719     }
1720
1721     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
1722     {
1723         m_assembler.mtc1(src, fpTempRegister);
1724         m_assembler.cvtdw(dest, fpTempRegister);
1725     }
1726
1727     void convertInt32ToDouble(Address src, FPRegisterID dest)
1728     {
1729         load32(src, dataTempRegister);
1730         m_assembler.mtc1(dataTempRegister, fpTempRegister);
1731         m_assembler.cvtdw(dest, fpTempRegister);
1732     }
1733
1734     void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
1735     {
1736         load32(src.m_ptr, dataTempRegister);
1737         m_assembler.mtc1(dataTempRegister, fpTempRegister);
1738         m_assembler.cvtdw(dest, fpTempRegister);
1739     }
1740
1741     void insertRelaxationWords()
1742     {
1743         /* We need four words for relaxation. */
1744         m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 3); // Jump over nops;
1745         m_assembler.nop();
1746         m_assembler.nop();
1747         m_assembler.nop();
1748     }
1749
1750     Jump branchTrue()
1751     {
1752         m_assembler.appendJump();
1753         m_assembler.bc1t();
1754         m_assembler.nop();
1755         insertRelaxationWords();
1756         return Jump(m_assembler.label());
1757     }
1758
1759     Jump branchFalse()
1760     {
1761         m_assembler.appendJump();
1762         m_assembler.bc1f();
1763         m_assembler.nop();
1764         insertRelaxationWords();
1765         return Jump(m_assembler.label());
1766     }
1767
1768     Jump branchEqual(RegisterID rs, RegisterID rt)
1769     {
1770         m_assembler.appendJump();
1771         m_assembler.beq(rs, rt, 0);
1772         m_assembler.nop();
1773         insertRelaxationWords();
1774         return Jump(m_assembler.label());
1775     }
1776
1777     Jump branchNotEqual(RegisterID rs, RegisterID rt)
1778     {
1779         m_assembler.appendJump();
1780         m_assembler.bne(rs, rt, 0);
1781         m_assembler.nop();
1782         insertRelaxationWords();
1783         return Jump(m_assembler.label());
1784     }
1785
1786     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
1787     {
1788         if (cond == DoubleEqual) {
1789             m_assembler.ceqd(left, right);
1790             return branchTrue();
1791         }
1792         if (cond == DoubleNotEqual) {
1793             m_assembler.cueqd(left, right);
1794             return branchFalse(); // false
1795         }
1796         if (cond == DoubleGreaterThan) {
1797             m_assembler.cngtd(left, right);
1798             return branchFalse(); // false
1799         }
1800         if (cond == DoubleGreaterThanOrEqual) {
1801             m_assembler.cnged(left, right);
1802             return branchFalse(); // false
1803         }
1804         if (cond == DoubleLessThan) {
1805             m_assembler.cltd(left, right);
1806             return branchTrue();
1807         }
1808         if (cond == DoubleLessThanOrEqual) {
1809             m_assembler.cled(left, right);
1810             return branchTrue();
1811         }
1812         if (cond == DoubleEqualOrUnordered) {
1813             m_assembler.cueqd(left, right);
1814             return branchTrue();
1815         }
1816         if (cond == DoubleNotEqualOrUnordered) {
1817             m_assembler.ceqd(left, right);
1818             return branchFalse(); // false
1819         }
1820         if (cond == DoubleGreaterThanOrUnordered) {
1821             m_assembler.coled(left, right);
1822             return branchFalse(); // false
1823         }
1824         if (cond == DoubleGreaterThanOrEqualOrUnordered) {
1825             m_assembler.coltd(left, right);
1826             return branchFalse(); // false
1827         }
1828         if (cond == DoubleLessThanOrUnordered) {
1829             m_assembler.cultd(left, right);
1830             return branchTrue();
1831         }
1832         if (cond == DoubleLessThanOrEqualOrUnordered) {
1833             m_assembler.culed(left, right);
1834             return branchTrue();
1835         }
1836         ASSERT(0);
1837
1838         return Jump();
1839     }
1840
1841     // Truncates 'src' to an integer, and places the resulting 'dest'.
1842     // If the result is not representable as a 32 bit value, branch.
1843     // May also branch for some values that are representable in 32 bits
1844     // (specifically, in this case, INT_MAX 0x7fffffff).
1845     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
1846     {
1847         m_assembler.truncwd(fpTempRegister, src);
1848         m_assembler.mfc1(dest, fpTempRegister);
1849         return branch32(Equal, dest, TrustedImm32(0x7fffffff));
1850     }
1851
1852     // Convert 'src' to an integer, and places the resulting 'dest'.
1853     // If the result is not representable as a 32 bit value, branch.
1854     // May also branch for some values that are representable in 32 bits
1855     // (specifically, in this case, 0).
1856     void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
1857     {
1858         m_assembler.cvtwd(fpTempRegister, src);
1859         m_assembler.mfc1(dest, fpTempRegister);
1860
1861         // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
1862         failureCases.append(branch32(Equal, dest, MIPSRegisters::zero));
1863
1864         // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
1865         convertInt32ToDouble(dest, fpTemp);
1866         failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fpTemp, src));
1867     }
1868
1869     Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
1870     {
1871 #if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
1872         m_assembler.mtc1(MIPSRegisters::zero, scratch);
1873         m_assembler.mthc1(MIPSRegisters::zero, scratch);
1874 #else
1875         m_assembler.mtc1(MIPSRegisters::zero, scratch);
1876         m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1));
1877 #endif
1878         return branchDouble(DoubleNotEqual, reg, scratch);
1879     }
1880
1881     Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
1882     {
1883 #if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
1884         m_assembler.mtc1(MIPSRegisters::zero, scratch);
1885         m_assembler.mthc1(MIPSRegisters::zero, scratch);
1886 #else
1887         m_assembler.mtc1(MIPSRegisters::zero, scratch);
1888         m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1));
1889 #endif
1890         return branchDouble(DoubleEqualOrUnordered, reg, scratch);
1891     }
1892
1893     void nop()
1894     {
1895         m_assembler.nop();
1896     }
1897
1898     static FunctionPtr readCallTarget(CodeLocationCall call)
1899     {
1900         return FunctionPtr(reinterpret_cast<void(*)()>(MIPSAssembler::readCallTarget(call.dataLocation())));
1901     }
1902
1903     static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
1904     {
1905         ASSERT_NOT_REACHED();
1906     }
1907     
1908     static ptrdiff_t maxJumpReplacementSize()
1909     {
1910         ASSERT_NOT_REACHED();
1911         return 0;
1912     }
1913
1914 private:
1915     // If m_fixedWidth is true, we will generate a fixed number of instructions.
1916     // Otherwise, we can emit any number of instructions.
1917     bool m_fixedWidth;
1918
1919     friend class LinkBuffer;
1920     friend class RepatchBuffer;
1921
1922     static void linkCall(void* code, Call call, FunctionPtr function)
1923     {
1924         MIPSAssembler::linkCall(code, call.m_label, function.value());
1925     }
1926
1927     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
1928     {
1929         MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
1930     }
1931
1932     static void repatchCall(CodeLocationCall call, FunctionPtr destination)
1933     {
1934         MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
1935     }
1936
1937 };
1938
1939 }
1940
1941 #endif // ENABLE(ASSEMBLER) && CPU(MIPS)
1942
1943 #endif // MacroAssemblerMIPS_h