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