[sh4] Refactor jumps in baseline JIT to return label after the jump.
[qtwebkit:qt5x2.git] / Source / JavaScriptCore / assembler / MacroAssemblerSH4.h
1 /*
2  * Copyright (C) 2013 Cisco Systems, Inc. All rights reserved.
3  * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved.
4  * Copyright (C) 2008 Apple Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #ifndef MacroAssemblerSH4_h
29 #define MacroAssemblerSH4_h
30
31 #if ENABLE(ASSEMBLER) && CPU(SH4)
32
33 #include "SH4Assembler.h"
34 #include "AbstractMacroAssembler.h"
35 #include <wtf/Assertions.h>
36
37 namespace JSC {
38
39 class MacroAssemblerSH4 : public AbstractMacroAssembler<SH4Assembler> {
40 public:
41     typedef SH4Assembler::FPRegisterID FPRegisterID;
42
43     static const Scale ScalePtr = TimesFour;
44     static const FPRegisterID fscratch = SH4Registers::dr10;
45     static const RegisterID stackPointerRegister = SH4Registers::sp;
46     static const RegisterID linkRegister = SH4Registers::pr;
47     static const RegisterID scratchReg3 = SH4Registers::r13;
48
49     static const int MaximumCompactPtrAlignedAddressOffset = 60;
50
51     static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value)
52     {
53         return (value >= 0) && (value <= MaximumCompactPtrAlignedAddressOffset) && (!(value & 3));
54     }
55
56     enum RelationalCondition {
57         Equal = SH4Assembler::EQ,
58         NotEqual = SH4Assembler::NE,
59         Above = SH4Assembler::HI,
60         AboveOrEqual = SH4Assembler::HS,
61         Below = SH4Assembler::LI,
62         BelowOrEqual = SH4Assembler::LS,
63         GreaterThan = SH4Assembler::GT,
64         GreaterThanOrEqual = SH4Assembler::GE,
65         LessThan = SH4Assembler::LT,
66         LessThanOrEqual = SH4Assembler::LE
67     };
68
69     enum ResultCondition {
70         Overflow = SH4Assembler::OF,
71         Signed = SH4Assembler::SI,
72         PositiveOrZero = SH4Assembler::NS,
73         Zero = SH4Assembler::EQ,
74         NonZero = SH4Assembler::NE
75     };
76
77     enum DoubleCondition {
78         // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
79         DoubleEqual = SH4Assembler::EQ,
80         DoubleNotEqual = SH4Assembler::NE,
81         DoubleGreaterThan = SH4Assembler::GT,
82         DoubleGreaterThanOrEqual = SH4Assembler::GE,
83         DoubleLessThan = SH4Assembler::LT,
84         DoubleLessThanOrEqual = SH4Assembler::LE,
85         // If either operand is NaN, these conditions always evaluate to true.
86         DoubleEqualOrUnordered = SH4Assembler::EQU,
87         DoubleNotEqualOrUnordered = SH4Assembler::NEU,
88         DoubleGreaterThanOrUnordered = SH4Assembler::GTU,
89         DoubleGreaterThanOrEqualOrUnordered = SH4Assembler::GEU,
90         DoubleLessThanOrUnordered = SH4Assembler::LTU,
91         DoubleLessThanOrEqualOrUnordered = SH4Assembler::LEU,
92     };
93
94     RegisterID claimScratch()
95     {
96         return m_assembler.claimScratch();
97     }
98
99     void releaseScratch(RegisterID reg)
100     {
101         m_assembler.releaseScratch(reg);
102     }
103
104     static RelationalCondition invert(RelationalCondition cond)
105     {
106         switch (cond) {
107         case Equal:
108             return NotEqual;
109         case NotEqual:
110             return Equal;
111         case Above:
112             return BelowOrEqual;
113         case AboveOrEqual:
114             return Below;
115         case Below:
116             return AboveOrEqual;
117         case BelowOrEqual:
118             return Above;
119         case GreaterThan:
120             return LessThanOrEqual;
121         case GreaterThanOrEqual:
122             return LessThan;
123         case LessThan:
124             return GreaterThanOrEqual;
125         case LessThanOrEqual:
126             return GreaterThan;
127         default:
128             RELEASE_ASSERT_NOT_REACHED();
129         }
130     }
131
132     // Integer arithmetic operations
133
134     void add32(RegisterID src, RegisterID dest)
135     {
136         m_assembler.addlRegReg(src, dest);
137     }
138
139     void add32(RegisterID src1, RegisterID src2, RegisterID dest)
140     {
141         if (src1 == dest)
142             add32(src2, dest);
143         else {
144             move(src2, dest);
145             add32(src1, dest);
146         }
147     }
148
149     void add32(TrustedImm32 imm, RegisterID dest)
150     {
151         if (!imm.m_value)
152             return;
153
154         if (m_assembler.isImmediate(imm.m_value)) {
155             m_assembler.addlImm8r(imm.m_value, dest);
156             return;
157         }
158
159         RegisterID scr = claimScratch();
160         m_assembler.loadConstant(imm.m_value, scr);
161         m_assembler.addlRegReg(scr, dest);
162         releaseScratch(scr);
163     }
164
165     void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
166     {
167         move(src, dest);
168         add32(imm, dest);
169     }
170
171     void add32(TrustedImm32 imm, Address address)
172     {
173         if (!imm.m_value)
174             return;
175
176         RegisterID scr = claimScratch();
177         load32(address, scr);
178         add32(imm, scr);
179         store32(scr, address);
180         releaseScratch(scr);
181     }
182
183     void add32(Address src, RegisterID dest)
184     {
185         RegisterID scr = claimScratch();
186         load32(src, scr);
187         m_assembler.addlRegReg(scr, dest);
188         releaseScratch(scr);
189     }
190
191     void add32(AbsoluteAddress src, RegisterID dest)
192     {
193         RegisterID scr = claimScratch();
194         load32(src.m_ptr, scr);
195         m_assembler.addlRegReg(scr, dest);
196         releaseScratch(scr);
197     }
198
199     void and32(RegisterID src, RegisterID dest)
200     {
201         m_assembler.andlRegReg(src, dest);
202     }
203
204     void and32(RegisterID src1, RegisterID src2, RegisterID dest)
205     {
206         if (src1 == dest)
207             and32(src2, dest);
208         else {
209             move(src2, dest);
210             and32(src1, dest);
211         }
212     }
213
214     void and32(Address src, RegisterID dest)
215     {
216         RegisterID scr = claimScratch();
217         load32(src, scr);
218         and32(scr, dest);
219         releaseScratch(scr);
220     }
221
222     void and32(TrustedImm32 imm, RegisterID dest)
223     {
224         if (!imm.m_value) {
225             m_assembler.movImm8(0, dest);
226             return;
227         }
228
229         if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) {
230             m_assembler.andlImm8r(imm.m_value, dest);
231             return;
232         }
233
234         RegisterID scr = claimScratch();
235         m_assembler.loadConstant(imm.m_value, scr);
236         m_assembler.andlRegReg(scr, dest);
237         releaseScratch(scr);
238     }
239
240     void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
241     {
242         if (src != dest) {
243             move(imm, dest);
244             and32(src, dest);
245             return;
246         }
247
248         and32(imm, dest);
249     }
250
251     void lshift32(RegisterID shiftamount, RegisterID dest)
252     {
253         RegisterID shiftTmp = claimScratch();
254         m_assembler.loadConstant(0x1f, shiftTmp);
255         m_assembler.andlRegReg(shiftamount, shiftTmp);
256         m_assembler.shldRegReg(dest, shiftTmp);
257         releaseScratch(shiftTmp);
258     }
259
260     void lshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
261     {
262         move(src, dest);
263         lshift32(shiftAmount, dest);
264     }
265
266     void lshift32(TrustedImm32 imm, RegisterID dest)
267     {
268         int immMasked = imm.m_value & 0x1f;
269         if (!immMasked)
270             return;
271
272         if ((immMasked == 1) || (immMasked == 2) || (immMasked == 8) || (immMasked == 16)) {
273             m_assembler.shllImm8r(immMasked, dest);
274             return;
275         }
276
277         RegisterID shiftTmp = claimScratch();
278         m_assembler.loadConstant(immMasked, shiftTmp);
279         m_assembler.shldRegReg(dest, shiftTmp);
280         releaseScratch(shiftTmp);
281     }
282
283     void lshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest)
284     {
285         move(src, dest);
286         lshift32(shiftamount, dest);
287     }
288
289     void mul32(RegisterID src, RegisterID dest)
290     {
291         mul32(src, dest, dest);    
292     }
293
294     void mul32(RegisterID src1, RegisterID src2, RegisterID dest)
295     {
296         m_assembler.imullRegReg(src1, src2);
297         m_assembler.stsmacl(dest);
298     }
299
300     void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
301     {
302         if (src == dest) {
303             RegisterID immval = claimScratch();
304             move(imm, immval);
305             mul32(immval, dest);
306             releaseScratch(immval);
307         } else {
308             move(imm, dest);
309             mul32(src, dest);
310         }
311     }
312
313     void or32(RegisterID src, RegisterID dest)
314     {
315         m_assembler.orlRegReg(src, dest);
316     }
317
318     void or32(TrustedImm32 imm, RegisterID dest)
319     {
320         if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) {
321             m_assembler.orlImm8r(imm.m_value, dest);
322             return;
323         }
324
325         RegisterID scr = claimScratch();
326         m_assembler.loadConstant(imm.m_value, scr);
327         m_assembler.orlRegReg(scr, dest);
328         releaseScratch(scr);
329     }
330
331     void or32(RegisterID op1, RegisterID op2, RegisterID dest)
332     {
333         if (op1 == op2)
334             move(op1, dest);
335         else if (op1 == dest)
336             or32(op2, dest);
337         else {
338             move(op2, dest);
339             or32(op1, dest);
340         }
341     }
342
343     void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
344     {
345         if (src != dest) {
346             move(imm, dest);
347             or32(src, dest);
348             return;
349         }
350
351         or32(imm, dest);
352     }
353
354     void or32(RegisterID src, AbsoluteAddress address)
355     {
356         RegisterID destptr = claimScratch();
357         move(TrustedImmPtr(address.m_ptr), destptr);
358         RegisterID destval = claimScratch();
359         m_assembler.movlMemReg(destptr, destval);
360         m_assembler.orlRegReg(src, destval);
361         m_assembler.movlRegMem(destval, destptr);
362         releaseScratch(destval);
363         releaseScratch(destptr);
364     }
365
366     void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
367     {
368         if (src != dest) {
369             move(imm, dest);
370             xor32(src, dest);
371             return;
372         }
373
374         xor32(imm, dest);
375     }
376
377     void rshift32(RegisterID shiftamount, RegisterID dest)
378     {
379         RegisterID shiftTmp = claimScratch();
380         m_assembler.loadConstant(0x1f, shiftTmp);
381         m_assembler.andlRegReg(shiftamount, shiftTmp);
382         m_assembler.neg(shiftTmp, shiftTmp);
383         m_assembler.shadRegReg(dest, shiftTmp);
384         releaseScratch(shiftTmp);
385     }
386
387     void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
388     {
389         move(src, dest);
390         rshift32(shiftAmount, dest);
391     }
392
393     void rshift32(TrustedImm32 imm, RegisterID dest)
394     {
395         int immMasked = imm.m_value & 0x1f;
396         if (!immMasked)
397             return;
398
399         if (immMasked == 1) {
400             m_assembler.sharImm8r(immMasked, dest);
401             return;
402         }
403
404         RegisterID shiftTmp = claimScratch();
405         m_assembler.loadConstant(-immMasked, shiftTmp);
406         m_assembler.shadRegReg(dest, shiftTmp);
407         releaseScratch(shiftTmp);
408     }
409
410     void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
411     {
412         move(src, dest);
413         rshift32(imm, dest);
414     }
415
416     void sub32(RegisterID src, RegisterID dest)
417     {
418         m_assembler.sublRegReg(src, dest);
419     }
420
421     void sub32(TrustedImm32 imm, AbsoluteAddress address)
422     {
423         if (!imm.m_value)
424             return;
425
426         RegisterID result = claimScratch();
427         RegisterID scratchReg = claimScratch();
428
429         move(TrustedImmPtr(address.m_ptr), scratchReg);
430         m_assembler.movlMemReg(scratchReg, result);
431
432         if (m_assembler.isImmediate(-imm.m_value))
433             m_assembler.addlImm8r(-imm.m_value, result);
434         else {
435             m_assembler.loadConstant(imm.m_value, scratchReg3);
436             m_assembler.sublRegReg(scratchReg3, result);
437         }
438
439         store32(result, scratchReg);
440         releaseScratch(result);
441         releaseScratch(scratchReg);
442     }
443
444     void sub32(TrustedImm32 imm, Address address)
445     {
446         add32(TrustedImm32(-imm.m_value), address);
447     }
448
449     void add32(TrustedImm32 imm, AbsoluteAddress address)
450     {
451         if (!imm.m_value)
452             return;
453
454         RegisterID result = claimScratch();
455         RegisterID scratchReg = claimScratch();
456
457         move(TrustedImmPtr(address.m_ptr), scratchReg);
458         m_assembler.movlMemReg(scratchReg, result);
459
460         if (m_assembler.isImmediate(imm.m_value))
461             m_assembler.addlImm8r(imm.m_value, result);
462         else {
463             m_assembler.loadConstant(imm.m_value, scratchReg3);
464             m_assembler.addlRegReg(scratchReg3, result);
465         }
466
467         store32(result, scratchReg);
468         releaseScratch(result);
469         releaseScratch(scratchReg);
470     }
471
472     void add64(TrustedImm32 imm, AbsoluteAddress address)
473     {
474         RegisterID scr1 = claimScratch();
475         RegisterID scr2 = claimScratch();
476
477         // Add 32-bit LSB first.
478         move(TrustedImmPtr(address.m_ptr), scratchReg3);
479         m_assembler.movlMemReg(scratchReg3, scr1); // scr1 = 32-bit LSB of int64 @ address
480         m_assembler.loadConstant(imm.m_value, scr2);
481         m_assembler.clrt();
482         m_assembler.addclRegReg(scr1, scr2);
483         m_assembler.movlRegMem(scr2, scratchReg3); // Update address with 32-bit LSB result.
484
485         // Then add 32-bit MSB.
486         m_assembler.addlImm8r(4, scratchReg3);
487         m_assembler.movlMemReg(scratchReg3, scr1); // scr1 = 32-bit MSB of int64 @ address
488         m_assembler.movt(scr2);
489         if (imm.m_value < 0)
490             m_assembler.addlImm8r(-1, scr2); // Sign extend imm value if needed.
491         m_assembler.addvlRegReg(scr2, scr1);
492         m_assembler.movlRegMem(scr1, scratchReg3); // Update (address + 4) with 32-bit MSB result.
493
494         releaseScratch(scr2);
495         releaseScratch(scr1);
496     }
497
498     void sub32(TrustedImm32 imm, RegisterID dest)
499     {
500         if (!imm.m_value)
501             return;
502
503         if (m_assembler.isImmediate(-imm.m_value)) {
504             m_assembler.addlImm8r(-imm.m_value, dest);
505             return;
506         }
507
508         RegisterID scr = claimScratch();
509         m_assembler.loadConstant(imm.m_value, scr);
510         m_assembler.sublRegReg(scr, dest);
511         releaseScratch(scr);
512     }
513
514     void sub32(Address src, RegisterID dest)
515     {
516         RegisterID scr = claimScratch();
517         load32(src, scr);
518         m_assembler.sublRegReg(scr, dest);
519         releaseScratch(scr);
520     }
521
522     void xor32(RegisterID src, RegisterID dest)
523     {
524         m_assembler.xorlRegReg(src, dest);
525     }
526
527     void xor32(RegisterID src1, RegisterID src2, RegisterID dest)
528     {
529         if (src1 == dest)
530             xor32(src2, dest);
531         else {
532             move(src2, dest);
533             xor32(src1, dest);
534         }
535     }
536
537     void xor32(TrustedImm32 imm, RegisterID srcDest)
538     {
539         if (imm.m_value == -1) {
540             m_assembler.notlReg(srcDest, srcDest);
541             return;
542         }
543
544         if ((srcDest != SH4Registers::r0) || (imm.m_value > 255) || (imm.m_value < 0)) {
545             RegisterID scr = claimScratch();
546             m_assembler.loadConstant(imm.m_value, scr);
547             m_assembler.xorlRegReg(scr, srcDest);
548             releaseScratch(scr);
549             return;
550         }
551
552         m_assembler.xorlImm8r(imm.m_value, srcDest);
553     }
554
555     void compare32(int imm, RegisterID dst, RelationalCondition cond)
556     {
557         if (((cond == Equal) || (cond == NotEqual)) && (dst == SH4Registers::r0) && m_assembler.isImmediate(imm)) {
558             m_assembler.cmpEqImmR0(imm, dst);
559             return;
560         }
561
562         if (((cond == Equal) || (cond == NotEqual)) && !imm) {
563             m_assembler.testlRegReg(dst, dst);
564             return;
565         }
566
567         RegisterID scr = claimScratch();
568         m_assembler.loadConstant(imm, scr);
569         m_assembler.cmplRegReg(scr, dst, SH4Condition(cond));
570         releaseScratch(scr);
571     }
572
573     void compare32(int offset, RegisterID base, RegisterID left, RelationalCondition cond)
574     {
575         RegisterID scr = claimScratch();
576         if (!offset) {
577             m_assembler.movlMemReg(base, scr);
578             m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
579             releaseScratch(scr);
580             return;
581         }
582
583         if ((offset < 0) || (offset >= 64)) {
584             m_assembler.loadConstant(offset, scr);
585             m_assembler.addlRegReg(base, scr);
586             m_assembler.movlMemReg(scr, scr);
587             m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
588             releaseScratch(scr);
589             return;
590         }
591
592         m_assembler.movlMemReg(offset >> 2, base, scr);
593         m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
594         releaseScratch(scr);
595     }
596
597     void testImm(int imm, int offset, RegisterID base)
598     {
599         RegisterID scr = claimScratch();
600         load32(base, offset, scr);
601
602         RegisterID scr1 = claimScratch();
603         move(TrustedImm32(imm), scr1);
604
605         m_assembler.testlRegReg(scr, scr1);
606         releaseScratch(scr);
607         releaseScratch(scr1);
608     }
609
610     void testlImm(int imm, RegisterID dst)
611     {
612         if ((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0)) {
613             m_assembler.testlImm8r(imm, dst);
614             return;
615         }
616
617         RegisterID scr = claimScratch();
618         m_assembler.loadConstant(imm, scr);
619         m_assembler.testlRegReg(scr, dst);
620         releaseScratch(scr);
621     }
622
623     void compare32(RegisterID right, int offset, RegisterID base, RelationalCondition cond)
624     {
625         if (!offset) {
626             RegisterID scr = claimScratch();
627             m_assembler.movlMemReg(base, scr);
628             m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
629             releaseScratch(scr);
630             return;
631         }
632
633         if ((offset < 0) || (offset >= 64)) {
634             RegisterID scr = claimScratch();
635             m_assembler.loadConstant(offset, scr);
636             m_assembler.addlRegReg(base, scr);
637             m_assembler.movlMemReg(scr, scr);
638             m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
639             releaseScratch(scr);
640             return;
641         }
642
643         RegisterID scr = claimScratch();
644         m_assembler.movlMemReg(offset >> 2, base, scr);
645         m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
646         releaseScratch(scr);
647     }
648
649     void compare32(int imm, int offset, RegisterID base, RelationalCondition cond)
650     {
651         RegisterID scr = claimScratch();
652         load32(base, offset, scr);
653
654         RegisterID scr1 = claimScratch();
655         move(TrustedImm32(imm), scr1);
656
657         m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
658
659         releaseScratch(scr1);
660         releaseScratch(scr);
661     }
662
663     // Memory access operation
664
665     ALWAYS_INLINE void loadEffectiveAddress(BaseIndex address, RegisterID dest, int extraoffset = 0)
666     {
667         if (dest == address.base) {
668             RegisterID scaledIndex = claimScratch();
669             move(address.index, scaledIndex);
670             lshift32(TrustedImm32(address.scale), scaledIndex);
671             add32(scaledIndex, dest);
672             releaseScratch(scaledIndex);
673         } else {
674             move(address.index, dest);
675             lshift32(TrustedImm32(address.scale), dest);
676             add32(address.base, dest);
677         }
678
679         add32(TrustedImm32(address.offset + extraoffset), dest);
680     }
681
682     void load32(ImplicitAddress address, RegisterID dest)
683     {
684         load32(address.base, address.offset, dest);
685     }
686
687     void load8(ImplicitAddress address, RegisterID dest)
688     {
689         load8(address.base, address.offset, dest);
690     }
691
692     void load8(BaseIndex address, RegisterID dest)
693     {
694         RegisterID scr = claimScratch();
695         move(address.index, scr);
696         lshift32(TrustedImm32(address.scale), scr);
697         add32(address.base, scr);
698         load8(scr, address.offset, dest);
699         releaseScratch(scr);
700     }
701
702     void load8PostInc(RegisterID base, RegisterID dest)
703     {
704         m_assembler.movbMemRegIn(base, dest);
705         m_assembler.extub(dest, dest);
706     }
707
708     void load8Signed(BaseIndex address, RegisterID dest)
709     {
710         RegisterID scr = claimScratch();
711         move(address.index, scr);
712         lshift32(TrustedImm32(address.scale), scr);
713         add32(address.base, scr);
714         load8Signed(scr, address.offset, dest);
715         releaseScratch(scr);
716     }
717
718     void load32(BaseIndex address, RegisterID dest)
719     {
720         RegisterID scr = claimScratch();
721         move(address.index, scr);
722         lshift32(TrustedImm32(address.scale), scr);
723         add32(address.base, scr);
724         load32(scr, address.offset, dest);
725         releaseScratch(scr);
726     }
727
728     void load32(const void* address, RegisterID dest)
729     {
730         move(TrustedImmPtr(address), dest);
731         m_assembler.movlMemReg(dest, dest);
732     }
733
734     void load32(RegisterID base, int offset, RegisterID dest)
735     {
736         if (!offset) {
737             m_assembler.movlMemReg(base, dest);
738             return;
739         }
740
741         if ((offset >= 0) && (offset < 64)) {
742             m_assembler.movlMemReg(offset >> 2, base, dest);
743             return;
744         }
745
746         RegisterID scr = (dest == base) ? claimScratch() : dest;
747
748         m_assembler.loadConstant(offset, scr);
749         if (base == SH4Registers::r0)
750             m_assembler.movlR0mr(scr, dest);
751         else {
752             m_assembler.addlRegReg(base, scr);
753             m_assembler.movlMemReg(scr, dest);
754         }
755
756         if (dest == base)
757             releaseScratch(scr);
758     }
759
760     void load8Signed(RegisterID base, int offset, RegisterID dest)
761     {
762         if (!offset) {
763             m_assembler.movbMemReg(base, dest);
764             return;
765         }
766
767         if ((offset > 0) && (offset <= 15) && (dest == SH4Registers::r0)) {
768             m_assembler.movbMemReg(offset, base, dest);
769             return;
770         }
771
772         RegisterID scr = (dest == base) ? claimScratch() : dest;
773
774         m_assembler.loadConstant(offset, scr);
775         if (base == SH4Registers::r0)
776             m_assembler.movbR0mr(scr, dest);
777         else {
778             m_assembler.addlRegReg(base, scr);
779             m_assembler.movbMemReg(scr, dest);
780         }
781
782         if (dest == base)
783             releaseScratch(scr);
784     }
785
786     void load8(RegisterID base, int offset, RegisterID dest)
787     {
788         load8Signed(base, offset, dest);
789         m_assembler.extub(dest, dest);
790     }
791
792     void load32(RegisterID src, RegisterID dst)
793     {
794         m_assembler.movlMemReg(src, dst);
795     }
796
797     void load16(ImplicitAddress address, RegisterID dest)
798     {
799         if (!address.offset) {
800             m_assembler.movwMemReg(address.base, dest);
801             m_assembler.extuw(dest, dest);
802             return;
803         }
804
805         if ((address.offset > 0) && (address.offset <= 30) && (dest == SH4Registers::r0)) {
806             m_assembler.movwMemReg(address.offset >> 1, address.base, dest);
807             m_assembler.extuw(dest, dest);
808             return;
809         }
810
811         RegisterID scr = (dest == address.base) ? claimScratch() : dest;
812
813         m_assembler.loadConstant(address.offset, scr);
814         if (address.base == SH4Registers::r0)
815             m_assembler.movwR0mr(scr, dest);
816         else {
817             m_assembler.addlRegReg(address.base, scr);
818             m_assembler.movwMemReg(scr, dest);
819         }
820         m_assembler.extuw(dest, dest);
821
822         if (dest == address.base)
823             releaseScratch(scr);
824     }
825
826     void load16Unaligned(BaseIndex address, RegisterID dest)
827     {
828         RegisterID scr = claimScratch();
829
830         loadEffectiveAddress(address, scr);
831
832         RegisterID scr1 = claimScratch();
833         load8PostInc(scr, scr1);
834         load8(scr, dest);
835         m_assembler.shllImm8r(8, dest);
836         or32(scr1, dest);
837
838         releaseScratch(scr);
839         releaseScratch(scr1);
840     }
841
842     void load16(RegisterID src, RegisterID dest)
843     {
844         m_assembler.movwMemReg(src, dest);
845         m_assembler.extuw(dest, dest);
846     }
847
848     void load16Signed(RegisterID src, RegisterID dest)
849     {
850         m_assembler.movwMemReg(src, dest);
851     }
852
853     void load16(BaseIndex address, RegisterID dest)
854     {
855         load16Signed(address, dest);
856         m_assembler.extuw(dest, dest);
857     }
858
859     void load16PostInc(RegisterID base, RegisterID dest)
860     {
861         m_assembler.movwMemRegIn(base, dest);
862         m_assembler.extuw(dest, dest);
863     }
864
865     void load16Signed(BaseIndex address, RegisterID dest)
866     {
867         RegisterID scr = claimScratch();
868
869         move(address.index, scr);
870         lshift32(TrustedImm32(address.scale), scr);
871         add32(TrustedImm32(address.offset), scr);
872
873         if (address.base == SH4Registers::r0)
874             m_assembler.movwR0mr(scr, dest);
875         else {
876             add32(address.base, scr);
877             load16Signed(scr, dest);
878         }
879
880         releaseScratch(scr);
881     }
882
883     void store8(RegisterID src, BaseIndex address)
884     {
885         RegisterID scr = claimScratch();
886
887         move(address.index, scr);
888         lshift32(TrustedImm32(address.scale), scr);
889         add32(TrustedImm32(address.offset), scr);
890
891         if (address.base == SH4Registers::r0)
892             m_assembler.movbRegMemr0(src, scr);
893         else {
894             add32(address.base, scr);
895             m_assembler.movbRegMem(src, scr);
896         }
897
898         releaseScratch(scr);
899     }
900
901     void store8(TrustedImm32 imm, void* address)
902     {
903         RegisterID srcval = claimScratch();
904         RegisterID dstptr = claimScratch();
905         move(imm, srcval);
906         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), dstptr);
907         m_assembler.movbRegMem(srcval, dstptr);
908         releaseScratch(dstptr);
909         releaseScratch(srcval);
910     }
911
912     void store16(RegisterID src, BaseIndex address)
913     {
914         RegisterID scr = claimScratch();
915
916         move(address.index, scr);
917         lshift32(TrustedImm32(address.scale), scr);
918         add32(TrustedImm32(address.offset), scr);
919
920         if (address.base == SH4Registers::r0)
921             m_assembler.movwRegMemr0(src, scr);
922         else {
923             add32(address.base, scr);
924             m_assembler.movwRegMem(src, scr);
925         }
926
927         releaseScratch(scr);
928     }
929
930     void store32(RegisterID src, ImplicitAddress address)
931     {
932         if (!address.offset) {
933             m_assembler.movlRegMem(src, address.base);
934             return;
935         }
936
937         if ((address.offset >= 0) && (address.offset < 64)) {
938             m_assembler.movlRegMem(src, address.offset >> 2, address.base);
939             return;
940         }
941
942         RegisterID scr = claimScratch();
943         m_assembler.loadConstant(address.offset, scr);
944         if (address.base == SH4Registers::r0)
945             m_assembler.movlRegMemr0(src, scr);
946         else {
947             m_assembler.addlRegReg(address.base, scr);
948             m_assembler.movlRegMem(src, scr);
949         }
950         releaseScratch(scr);
951     }
952
953     void store32(RegisterID src, RegisterID dst)
954     {
955         m_assembler.movlRegMem(src, dst);
956     }
957
958     void store32(TrustedImm32 imm, ImplicitAddress address)
959     {
960         RegisterID scr = claimScratch();
961         m_assembler.loadConstant(imm.m_value, scr);
962         store32(scr, address);
963         releaseScratch(scr);
964     }
965
966     void store32(RegisterID src, BaseIndex address)
967     {
968         RegisterID scr = claimScratch();
969
970         move(address.index, scr);
971         lshift32(TrustedImm32(address.scale), scr);
972         add32(address.base, scr);
973         store32(src, Address(scr, address.offset));
974
975         releaseScratch(scr);
976     }
977
978     void store32(TrustedImm32 imm, void* address)
979     {
980         RegisterID scr = claimScratch();
981         RegisterID scr1 = claimScratch();
982         m_assembler.loadConstant(imm.m_value, scr);
983         move(TrustedImmPtr(address), scr1);
984         m_assembler.movlRegMem(scr, scr1);
985         releaseScratch(scr);
986         releaseScratch(scr1);
987     }
988
989     void store32(RegisterID src, void* address)
990     {
991         RegisterID scr = claimScratch();
992         move(TrustedImmPtr(address), scr);
993         m_assembler.movlRegMem(src, scr);
994         releaseScratch(scr);
995     }
996
997     void store32(TrustedImm32 imm, BaseIndex address)
998     {
999         RegisterID destptr = claimScratch();
1000
1001         loadEffectiveAddress(address, destptr);
1002
1003         RegisterID srcval = claimScratch();
1004         move(imm, srcval);
1005         m_assembler.movlRegMem(srcval, destptr);
1006         releaseScratch(srcval);
1007         releaseScratch(destptr);
1008     }
1009
1010     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
1011     {
1012         RegisterID scr = claimScratch();
1013         DataLabel32 label(this);
1014         m_assembler.loadConstantUnReusable(address.offset, scr);
1015         m_assembler.addlRegReg(address.base, scr);
1016         m_assembler.movlMemReg(scr, dest);
1017         releaseScratch(scr);
1018         return label;
1019     }
1020     
1021     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
1022     {
1023         RegisterID scr = claimScratch();
1024         DataLabel32 label(this);
1025         m_assembler.loadConstantUnReusable(address.offset, scr);
1026         m_assembler.addlRegReg(address.base, scr);
1027         m_assembler.movlRegMem(src, scr);
1028         releaseScratch(scr);
1029         return label;
1030     }
1031
1032     DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
1033     {
1034         DataLabelCompact dataLabel(this);
1035         ASSERT(isCompactPtrAlignedAddressOffset(address.offset));
1036         m_assembler.movlMemRegCompact(address.offset >> 2, address.base, dest);
1037         return dataLabel;
1038     }
1039
1040     ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest)
1041     {
1042         ConvertibleLoadLabel result(this);
1043
1044         RegisterID scr = claimScratch();
1045         m_assembler.movImm8(address.offset, scr);
1046         m_assembler.addlRegReg(address.base, scr);
1047         m_assembler.movlMemReg(scr, dest);
1048         releaseScratch(scr);
1049
1050         return result;
1051     }
1052
1053     // Floating-point operations
1054
1055     static bool supportsFloatingPoint() { return true; }
1056     static bool supportsFloatingPointTruncate() { return true; }
1057     static bool supportsFloatingPointSqrt() { return true; }
1058     static bool supportsFloatingPointAbs() { return true; }
1059
1060     void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2)
1061     {
1062         m_assembler.fldsfpul((FPRegisterID)(src + 1));
1063         m_assembler.stsfpulReg(dest1);
1064         m_assembler.fldsfpul(src);
1065         m_assembler.stsfpulReg(dest2);
1066     }
1067
1068     void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID)
1069     {
1070         m_assembler.ldsrmfpul(src1);
1071         m_assembler.fstsfpul((FPRegisterID)(dest + 1));
1072         m_assembler.ldsrmfpul(src2);
1073         m_assembler.fstsfpul(dest);
1074     }
1075
1076     void moveDouble(FPRegisterID src, FPRegisterID dest)
1077     {
1078         if (src != dest) {
1079             m_assembler.fmovsRegReg((FPRegisterID)(src + 1), (FPRegisterID)(dest + 1));
1080             m_assembler.fmovsRegReg(src, dest);
1081         }
1082     }
1083
1084     void swapDouble(FPRegisterID fr1, FPRegisterID fr2)
1085     {
1086         if (fr1 != fr2) {
1087             m_assembler.fldsfpul((FPRegisterID)(fr1 + 1));
1088             m_assembler.fmovsRegReg((FPRegisterID)(fr2 + 1), (FPRegisterID)(fr1 + 1));
1089             m_assembler.fstsfpul((FPRegisterID)(fr2 + 1));
1090             m_assembler.fldsfpul(fr1);
1091             m_assembler.fmovsRegReg(fr2, fr1);
1092             m_assembler.fstsfpul(fr2);
1093         }
1094     }
1095
1096     void loadFloat(BaseIndex address, FPRegisterID dest)
1097     {
1098         RegisterID scr = claimScratch();
1099
1100         loadEffectiveAddress(address, scr);
1101
1102         m_assembler.fmovsReadrm(scr, dest);
1103         releaseScratch(scr);
1104     }
1105
1106     void loadDouble(BaseIndex address, FPRegisterID dest)
1107     {
1108         RegisterID scr = claimScratch();
1109
1110         loadEffectiveAddress(address, scr);
1111
1112         m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
1113         m_assembler.fmovsReadrm(scr, dest);
1114         releaseScratch(scr);
1115     }
1116
1117     void loadDouble(ImplicitAddress address, FPRegisterID dest)
1118     {
1119         RegisterID scr = claimScratch();
1120
1121         m_assembler.loadConstant(address.offset, scr);
1122         if (address.base == SH4Registers::r0) {
1123             m_assembler.fmovsReadr0r(scr, (FPRegisterID)(dest + 1));
1124             m_assembler.addlImm8r(4, scr);
1125             m_assembler.fmovsReadr0r(scr, dest);
1126             releaseScratch(scr);
1127             return;
1128         }
1129
1130         m_assembler.addlRegReg(address.base, scr);
1131         m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
1132         m_assembler.fmovsReadrm(scr, dest);
1133         releaseScratch(scr);
1134     }
1135
1136     void loadDouble(const void* address, FPRegisterID dest)
1137     {
1138         RegisterID scr = claimScratch();
1139         move(TrustedImmPtr(address), scr);
1140         m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
1141         m_assembler.fmovsReadrm(scr, dest);
1142         releaseScratch(scr);
1143     }
1144
1145     void storeFloat(FPRegisterID src, BaseIndex address)
1146     {
1147         RegisterID scr = claimScratch();
1148         loadEffectiveAddress(address, scr);
1149         m_assembler.fmovsWriterm(src, scr);
1150         releaseScratch(scr);
1151     }
1152
1153     void storeDouble(FPRegisterID src, ImplicitAddress address)
1154     {
1155         RegisterID scr = claimScratch();
1156         m_assembler.loadConstant(address.offset + 8, scr);
1157         m_assembler.addlRegReg(address.base, scr);
1158         m_assembler.fmovsWriterndec(src, scr);
1159         m_assembler.fmovsWriterndec((FPRegisterID)(src + 1), scr);
1160         releaseScratch(scr);
1161     }
1162
1163     void storeDouble(FPRegisterID src, BaseIndex address)
1164     {
1165         RegisterID scr = claimScratch();
1166
1167         loadEffectiveAddress(address, scr, 8);
1168
1169         m_assembler.fmovsWriterndec(src, scr);
1170         m_assembler.fmovsWriterndec((FPRegisterID)(src + 1), scr);
1171
1172         releaseScratch(scr);
1173     }
1174
1175     void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1176     {
1177         if (op1 == dest)
1178             addDouble(op2, dest);
1179         else {
1180             moveDouble(op2, dest);
1181             addDouble(op1, dest);
1182         }
1183     }
1184
1185     void storeDouble(FPRegisterID src, const void* address)
1186     {
1187         RegisterID scr = claimScratch();
1188         m_assembler.loadConstant(reinterpret_cast<uint32_t>(const_cast<void*>(address)) + 8, scr);
1189         m_assembler.fmovsWriterndec(src, scr);
1190         m_assembler.fmovsWriterndec((FPRegisterID)(src + 1), scr);
1191         releaseScratch(scr);
1192     }
1193
1194     void addDouble(FPRegisterID src, FPRegisterID dest)
1195     {
1196         m_assembler.daddRegReg(src, dest);
1197     }
1198
1199     void addDouble(AbsoluteAddress address, FPRegisterID dest)
1200     {
1201         loadDouble(address.m_ptr, fscratch);
1202         addDouble(fscratch, dest);
1203     }
1204
1205     void addDouble(Address address, FPRegisterID dest)
1206     {
1207         loadDouble(address, fscratch);
1208         addDouble(fscratch, dest);
1209     }
1210
1211     void subDouble(FPRegisterID src, FPRegisterID dest)
1212     {
1213         m_assembler.dsubRegReg(src, dest);
1214     }
1215
1216     void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1217     {
1218         if (op2 == dest) {
1219             moveDouble(op1, fscratch);
1220             subDouble(op2, fscratch);
1221             moveDouble(fscratch, dest);
1222         } else {
1223             moveDouble(op1, dest);
1224             subDouble(op2, dest);
1225         }
1226     }
1227
1228     void subDouble(Address address, FPRegisterID dest)
1229     {
1230         loadDouble(address, fscratch);
1231         subDouble(fscratch, dest);
1232     }
1233
1234     void mulDouble(FPRegisterID src, FPRegisterID dest)
1235     {
1236         m_assembler.dmulRegReg(src, dest);
1237     }
1238
1239     void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1240     {
1241         if (op1 == dest)
1242             mulDouble(op2, dest);
1243         else {
1244             moveDouble(op2, dest);
1245             mulDouble(op1, dest);
1246         }
1247     }
1248
1249     void mulDouble(Address address, FPRegisterID dest)
1250     {
1251         loadDouble(address, fscratch);
1252         mulDouble(fscratch, dest);
1253     }
1254
1255     void divDouble(FPRegisterID src, FPRegisterID dest)
1256     {
1257         m_assembler.ddivRegReg(src, dest);
1258     }
1259
1260     void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1261     {
1262         if (op2 == dest) {
1263             moveDouble(op1, fscratch);
1264             divDouble(op2, fscratch);
1265             moveDouble(fscratch, dest);
1266         } else {
1267             moveDouble(op1, dest);
1268             divDouble(op2, dest);
1269         }
1270     }
1271
1272     void negateDouble(FPRegisterID src, FPRegisterID dest)
1273     {
1274         moveDouble(src, dest);
1275         m_assembler.dneg(dest);
1276     }
1277
1278     void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
1279     {
1280         m_assembler.fldsfpul(src);
1281         m_assembler.dcnvsd(dst);
1282     }
1283
1284     void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst)
1285     {
1286         m_assembler.dcnvds(src);
1287         m_assembler.fstsfpul(dst);
1288     }
1289
1290     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
1291     {
1292         m_assembler.ldsrmfpul(src);
1293         m_assembler.floatfpulDreg(dest);
1294     }
1295
1296     void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
1297     {
1298         RegisterID scr = claimScratch();
1299         load32(src.m_ptr, scr);
1300         convertInt32ToDouble(scr, dest);
1301         releaseScratch(scr);
1302     }
1303
1304     void convertInt32ToDouble(Address src, FPRegisterID dest)
1305     {
1306         RegisterID scr = claimScratch();
1307         load32(src, scr);
1308         convertInt32ToDouble(scr, dest);
1309         releaseScratch(scr);
1310     }
1311
1312     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
1313     {
1314         RegisterID scr = claimScratch();
1315         RegisterID scr1 = claimScratch();
1316         Jump m_jump;
1317         JumpList end;
1318
1319         if (dest != SH4Registers::r0)
1320             move(SH4Registers::r0, scr1);
1321
1322         loadEffectiveAddress(address, scr);
1323
1324         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 58, sizeof(uint32_t));
1325         move(scr, SH4Registers::r0);
1326         m_assembler.testlImm8r(0x3, SH4Registers::r0);
1327         m_jump = Jump(m_assembler.jne(), SH4Assembler::JumpNear);
1328
1329         if (dest != SH4Registers::r0)
1330             move(scr1, SH4Registers::r0);
1331
1332         load32(scr, dest);
1333         end.append(Jump(m_assembler.bra(), SH4Assembler::JumpNear));
1334         m_assembler.nop();
1335         m_jump.link(this);
1336         m_assembler.testlImm8r(0x1, SH4Registers::r0);
1337
1338         if (dest != SH4Registers::r0)
1339             move(scr1, SH4Registers::r0);
1340
1341         m_jump = Jump(m_assembler.jne(), SH4Assembler::JumpNear);
1342         load16PostInc(scr, scr1);
1343         load16(scr, dest);
1344         m_assembler.shllImm8r(16, dest);
1345         or32(scr1, dest);
1346         end.append(Jump(m_assembler.bra(), SH4Assembler::JumpNear));
1347         m_assembler.nop();
1348         m_jump.link(this);
1349         load8PostInc(scr, scr1);
1350         load16PostInc(scr, dest);
1351         m_assembler.shllImm8r(8, dest);
1352         or32(dest, scr1);
1353         load8(scr, dest);
1354         m_assembler.shllImm8r(8, dest);
1355         m_assembler.shllImm8r(16, dest);
1356         or32(scr1, dest);
1357         end.link(this);
1358
1359         releaseScratch(scr);
1360         releaseScratch(scr1);
1361     }
1362
1363     Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1364     {
1365         RegisterID scr = scratchReg3;
1366         load32WithUnalignedHalfWords(left, scr);
1367         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1368             m_assembler.testlRegReg(scr, scr);
1369         else
1370             compare32(right.m_value, scr, cond);
1371
1372         if (cond == NotEqual)
1373             return branchFalse();
1374         return branchTrue();
1375     }
1376
1377     Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
1378     {
1379         m_assembler.movImm8(0, scratchReg3);
1380         convertInt32ToDouble(scratchReg3, scratch);
1381         return branchDouble(DoubleNotEqual, reg, scratch);
1382     }
1383
1384     Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
1385     {
1386         m_assembler.movImm8(0, scratchReg3);
1387         convertInt32ToDouble(scratchReg3, scratch);
1388         return branchDouble(DoubleEqualOrUnordered, reg, scratch);
1389     }
1390
1391     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
1392     {
1393         if (cond == DoubleEqual) {
1394             m_assembler.dcmppeq(right, left);
1395             return branchTrue();
1396         }
1397
1398         if (cond == DoubleNotEqual) {
1399             JumpList end;
1400             m_assembler.dcmppeq(left, left);
1401             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1402             end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1403             m_assembler.dcmppeq(right, right);
1404             end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1405             m_assembler.dcmppeq(right, left);
1406             Jump m_jump = branchFalse();
1407             end.link(this);
1408             return m_jump;
1409         }
1410
1411         if (cond == DoubleGreaterThan) {
1412             m_assembler.dcmppgt(right, left);
1413             return branchTrue();
1414         }
1415
1416         if (cond == DoubleGreaterThanOrEqual) {
1417             JumpList end;
1418             m_assembler.dcmppeq(left, left);
1419             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1420             end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1421             m_assembler.dcmppeq(right, right);
1422             end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1423             m_assembler.dcmppgt(left, right);
1424             Jump m_jump = branchFalse();
1425             end.link(this);
1426             return m_jump;
1427         }
1428
1429         if (cond == DoubleLessThan) {
1430             m_assembler.dcmppgt(left, right);
1431             return branchTrue();
1432         }
1433
1434         if (cond == DoubleLessThanOrEqual) {
1435             JumpList end;
1436             m_assembler.dcmppeq(left, left);
1437             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1438             end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1439             m_assembler.dcmppeq(right, right);
1440             end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1441             m_assembler.dcmppgt(right, left);
1442             Jump m_jump = branchFalse();
1443             end.link(this);
1444             return m_jump;
1445         }
1446
1447         if (cond == DoubleEqualOrUnordered) {
1448             JumpList takeBranch;
1449             m_assembler.dcmppeq(left, left);
1450             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1451             takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1452             m_assembler.dcmppeq(right, right);
1453             takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1454             m_assembler.dcmppeq(left, right);
1455             m_assembler.branch(BF_OPCODE, 2);
1456             takeBranch.link(this);
1457             return Jump(m_assembler.extraInstrForBranch(scratchReg3));
1458         }
1459
1460         if (cond == DoubleGreaterThanOrUnordered) {
1461             JumpList takeBranch;
1462             m_assembler.dcmppeq(left, left);
1463             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1464             takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1465             m_assembler.dcmppeq(right, right);
1466             takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1467             m_assembler.dcmppgt(right, left);
1468             m_assembler.branch(BF_OPCODE, 2);
1469             takeBranch.link(this);
1470             return Jump(m_assembler.extraInstrForBranch(scratchReg3));
1471         }
1472
1473         if (cond == DoubleGreaterThanOrEqualOrUnordered) {
1474             m_assembler.dcmppgt(left, right);
1475             return branchFalse();
1476         }
1477
1478         if (cond == DoubleLessThanOrUnordered) {
1479             JumpList takeBranch;
1480             m_assembler.dcmppeq(left, left);
1481             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1482             takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1483             m_assembler.dcmppeq(right, right);
1484             takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1485             m_assembler.dcmppgt(left, right);
1486             m_assembler.branch(BF_OPCODE, 2);
1487             takeBranch.link(this);
1488             return Jump(m_assembler.extraInstrForBranch(scratchReg3));
1489         }
1490
1491         if (cond == DoubleLessThanOrEqualOrUnordered) {
1492             m_assembler.dcmppgt(right, left);
1493             return branchFalse();
1494         }
1495
1496         ASSERT(cond == DoubleNotEqualOrUnordered);
1497         m_assembler.dcmppeq(right, left);
1498         return branchFalse();
1499     }
1500
1501     Jump branchTrue()
1502     {
1503         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
1504         m_assembler.branch(BF_OPCODE, 2);
1505         return Jump(m_assembler.extraInstrForBranch(scratchReg3));
1506     }
1507
1508     Jump branchFalse()
1509     {
1510         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
1511         m_assembler.branch(BT_OPCODE, 2);
1512         return Jump(m_assembler.extraInstrForBranch(scratchReg3));
1513     }
1514
1515     Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1516     {
1517         RegisterID scr = claimScratch();
1518         move(left.index, scr);
1519         lshift32(TrustedImm32(left.scale), scr);
1520         add32(left.base, scr);
1521         load32(scr, left.offset, scr);
1522         compare32(right.m_value, scr, cond);
1523         releaseScratch(scr);
1524
1525         if (cond == NotEqual)
1526             return branchFalse();
1527         return branchTrue();
1528     }
1529
1530     void sqrtDouble(FPRegisterID src, FPRegisterID dest)
1531     {
1532         moveDouble(src, dest);
1533         m_assembler.dsqrt(dest);
1534     }
1535     
1536     void absDouble(FPRegisterID src, FPRegisterID dest)
1537     {
1538         moveDouble(src, dest);
1539         m_assembler.dabs(dest);
1540     }
1541
1542     Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1543     {
1544         RegisterID addressTempRegister = claimScratch();
1545         load8(address, addressTempRegister);
1546         Jump jmp = branchTest32(cond, addressTempRegister, mask);
1547         releaseScratch(addressTempRegister);
1548         return jmp;
1549     }
1550
1551     Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
1552     {
1553         RegisterID addressTempRegister = claimScratch();
1554         move(TrustedImmPtr(address.m_ptr), addressTempRegister);
1555         load8(Address(addressTempRegister), addressTempRegister);
1556         Jump jmp = branchTest32(cond, addressTempRegister, mask);
1557         releaseScratch(addressTempRegister);
1558         return jmp;
1559     }
1560
1561     void signExtend32ToPtr(RegisterID src, RegisterID dest)
1562     {
1563         move(src, dest);
1564     }
1565
1566     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
1567     {
1568         move(src, dest);
1569     }
1570
1571     Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
1572     {
1573         RegisterID addressTempRegister = claimScratch();
1574         load8(left, addressTempRegister);
1575         Jump jmp = branch32(cond, addressTempRegister, right);
1576         releaseScratch(addressTempRegister);
1577         return jmp;
1578     }
1579
1580     void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
1581     {
1582         RegisterID addressTempRegister = claimScratch();
1583         load8(left, addressTempRegister);
1584         compare32(cond, addressTempRegister, right, dest);
1585         releaseScratch(addressTempRegister);
1586     }
1587
1588     enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
1589     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
1590     {
1591         Jump result;
1592         truncateDoubleToInt32(src, dest);
1593         RegisterID intscr = claimScratch();
1594         m_assembler.loadConstant(0x7fffffff, intscr);
1595         m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal));
1596         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 12, sizeof(uint32_t));
1597         if (branchType == BranchIfTruncateFailed) {
1598             m_assembler.branch(BT_OPCODE, 2);
1599             m_assembler.addlImm8r(1, intscr);
1600             m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal));
1601             result = branchTrue();
1602         } else {
1603             Jump out = Jump(m_assembler.je(), SH4Assembler::JumpNear);
1604             m_assembler.addlImm8r(1, intscr);
1605             m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal));
1606             result = branchFalse();
1607             out.link(this);
1608         }
1609         releaseScratch(intscr);
1610         return result;
1611     }
1612
1613     Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
1614     {
1615         Jump result;
1616         RegisterID intscr = claimScratch();
1617         m_assembler.loadConstant(0x80000000, intscr);
1618         convertInt32ToDouble(intscr, fscratch);
1619         addDouble(src, fscratch);
1620         truncateDoubleToInt32(fscratch, dest);
1621         m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal));
1622         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 16, sizeof(uint32_t));
1623         if (branchType == BranchIfTruncateFailed) {
1624             m_assembler.branch(BT_OPCODE, 4);
1625             m_assembler.addlImm8r(-1, intscr);
1626             m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal));
1627             m_assembler.addlImm8r(1, intscr);
1628             m_assembler.sublRegReg(intscr, dest);
1629             result = branchTrue();
1630         } else {
1631             Jump out = Jump(m_assembler.je(), SH4Assembler::JumpNear);
1632             m_assembler.addlImm8r(-1, intscr);
1633             m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal));
1634             m_assembler.addlImm8r(1, intscr);
1635             m_assembler.sublRegReg(intscr, dest);
1636             result = branchFalse();
1637             out.link(this);
1638         }
1639         releaseScratch(intscr);
1640         return result;
1641     }
1642
1643     void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
1644     {
1645         m_assembler.ftrcdrmfpul(src);
1646         m_assembler.stsfpulReg(dest);
1647     }
1648
1649     void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
1650     {
1651         RegisterID intscr = claimScratch();
1652         m_assembler.loadConstant(0x80000000, intscr);
1653         convertInt32ToDouble(intscr, fscratch);
1654         addDouble(src, fscratch);
1655         m_assembler.ftrcdrmfpul(fscratch);
1656         m_assembler.stsfpulReg(dest);
1657         m_assembler.sublRegReg(intscr, dest);
1658         releaseScratch(intscr);
1659     }
1660
1661     // Stack manipulation operations
1662
1663     void pop(RegisterID dest)
1664     {
1665         m_assembler.popReg(dest);
1666     }
1667
1668     void push(RegisterID src)
1669     {
1670         m_assembler.pushReg(src);
1671     }
1672
1673     void push(TrustedImm32 imm)
1674     {
1675         RegisterID scr = claimScratch();
1676         m_assembler.loadConstant(imm.m_value, scr);
1677         push(scr);
1678         releaseScratch(scr);
1679     }
1680
1681     // Register move operations
1682
1683     void move(TrustedImm32 imm, RegisterID dest)
1684     {
1685         m_assembler.loadConstant(imm.m_value, dest);
1686     }
1687
1688     DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
1689     {
1690         m_assembler.ensureSpace(m_assembler.maxInstructionSize, sizeof(uint32_t));
1691         DataLabelPtr dataLabel(this);
1692         m_assembler.loadConstantUnReusable(reinterpret_cast<uint32_t>(initialValue.m_value), dest);
1693         return dataLabel;
1694     }
1695
1696     void move(RegisterID src, RegisterID dest)
1697     {
1698         if (src != dest)
1699             m_assembler.movlRegReg(src, dest);
1700     }
1701
1702     void move(TrustedImmPtr imm, RegisterID dest)
1703     {
1704         m_assembler.loadConstant(imm.asIntptr(), dest);
1705     }
1706
1707     void swap(RegisterID reg1, RegisterID reg2)
1708     {
1709         if (reg1 != reg2) {
1710             xor32(reg1, reg2);
1711             xor32(reg2, reg1);
1712             xor32(reg1, reg2);
1713         }
1714     }
1715
1716     void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
1717     {
1718         m_assembler.cmplRegReg(right, left, SH4Condition(cond));
1719         if (cond != NotEqual) {
1720             m_assembler.movt(dest);
1721             return;
1722         }
1723
1724         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
1725         m_assembler.movImm8(0, dest);
1726         m_assembler.branch(BT_OPCODE, 0);
1727         m_assembler.movImm8(1, dest);
1728     }
1729
1730     void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
1731     {
1732         if (left != dest) {
1733             move(right, dest);
1734             compare32(cond, left, dest, dest);
1735             return;
1736         }
1737
1738         RegisterID scr = claimScratch();
1739         move(right, scr);
1740         compare32(cond, left, scr, dest);
1741         releaseScratch(scr);
1742     }
1743
1744     void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
1745     {
1746         ASSERT((cond == Zero) || (cond == NonZero));
1747
1748         load8(address, dest);
1749         if (mask.m_value == -1)
1750             compare32(0, dest, static_cast<RelationalCondition>(cond));
1751         else
1752             testlImm(mask.m_value, dest);
1753         if (cond != NonZero) {
1754             m_assembler.movt(dest);
1755             return;
1756         }
1757
1758         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
1759         m_assembler.movImm8(0, dest);
1760         m_assembler.branch(BT_OPCODE, 0);
1761         m_assembler.movImm8(1, dest);
1762     }
1763
1764     void loadPtrLinkReg(ImplicitAddress address)
1765     {
1766         RegisterID scr = claimScratch();
1767         load32(address, scr);
1768         m_assembler.ldspr(scr);
1769         releaseScratch(scr);
1770     }
1771
1772     Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
1773     {
1774         m_assembler.cmplRegReg(right, left, SH4Condition(cond));
1775         /* BT label => BF off
1776            nop         LDR reg
1777            nop         braf @reg
1778            nop         nop
1779          */
1780         if (cond == NotEqual)
1781             return branchFalse();
1782         return branchTrue();
1783     }
1784
1785     Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
1786     {
1787         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1788             m_assembler.testlRegReg(left, left);
1789         else
1790             compare32(right.m_value, left, cond);
1791
1792         if (cond == NotEqual)
1793             return branchFalse();
1794         return branchTrue();
1795     }
1796
1797     Jump branch32(RelationalCondition cond, RegisterID left, Address right)
1798     {
1799         compare32(right.offset, right.base, left, cond);
1800         if (cond == NotEqual)
1801             return branchFalse();
1802         return branchTrue();
1803     }
1804
1805     Jump branch32(RelationalCondition cond, Address left, RegisterID right)
1806     {
1807         compare32(right, left.offset, left.base, cond);
1808         if (cond == NotEqual)
1809             return branchFalse();
1810         return branchTrue();
1811     }
1812
1813     Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
1814     {
1815         compare32(right.m_value, left.offset, left.base, cond);
1816         if (cond == NotEqual)
1817             return branchFalse();
1818         return branchTrue();
1819     }
1820
1821     Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
1822     {
1823         RegisterID scr = claimScratch();
1824
1825         load32(left.m_ptr, scr);
1826         m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
1827         releaseScratch(scr);
1828
1829         if (cond == NotEqual)
1830             return branchFalse();
1831         return branchTrue();
1832     }
1833
1834     Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
1835     {
1836         RegisterID addressTempRegister = claimScratch();
1837
1838         move(TrustedImmPtr(left.m_ptr), addressTempRegister);
1839         m_assembler.movlMemReg(addressTempRegister, addressTempRegister);
1840         compare32(right.m_value, addressTempRegister, cond);
1841         releaseScratch(addressTempRegister);
1842
1843         if (cond == NotEqual)
1844             return branchFalse();
1845         return branchTrue();
1846     }
1847
1848     Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1849     {
1850         ASSERT(!(right.m_value & 0xFFFFFF00));
1851         RegisterID lefttmp = claimScratch();
1852
1853         loadEffectiveAddress(left, lefttmp);
1854
1855         load8(lefttmp, lefttmp);
1856         RegisterID righttmp = claimScratch();
1857         m_assembler.loadConstant(right.m_value, righttmp);
1858
1859         Jump result = branch32(cond, lefttmp, righttmp);
1860         releaseScratch(lefttmp);
1861         releaseScratch(righttmp);
1862         return result;
1863     }
1864
1865     Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
1866     {
1867         ASSERT((cond == Zero) || (cond == NonZero));
1868
1869         m_assembler.testlRegReg(reg, mask);
1870
1871         if (cond == NonZero) // NotEqual
1872             return branchFalse();
1873         return branchTrue();
1874     }
1875
1876     Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
1877     {
1878         ASSERT((cond == Zero) || (cond == NonZero));
1879
1880         if (mask.m_value == -1)
1881             m_assembler.testlRegReg(reg, reg);
1882         else
1883             testlImm(mask.m_value, reg);
1884
1885         if (cond == NonZero) // NotEqual
1886             return branchFalse();
1887         return branchTrue();
1888     }
1889
1890     Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1891     {
1892         ASSERT((cond == Zero) || (cond == NonZero));
1893
1894         if (mask.m_value == -1)
1895             compare32(0, address.offset, address.base, static_cast<RelationalCondition>(cond));
1896         else
1897             testImm(mask.m_value, address.offset, address.base);
1898
1899         if (cond == NonZero) // NotEqual
1900             return branchFalse();
1901         return branchTrue();
1902     }
1903
1904     Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
1905     {
1906         ASSERT((cond == Zero) || (cond == NonZero));
1907
1908         RegisterID scr = claimScratch();
1909
1910         move(address.index, scr);
1911         lshift32(TrustedImm32(address.scale), scr);
1912         add32(address.base, scr);
1913         load32(scr, address.offset, scr);
1914
1915         if (mask.m_value == -1)
1916             m_assembler.testlRegReg(scr, scr);
1917         else
1918             testlImm(mask.m_value, scr);
1919
1920         releaseScratch(scr);
1921
1922         if (cond == NonZero) // NotEqual
1923             return branchFalse();
1924         return branchTrue();
1925     }
1926
1927     Jump jump()
1928     {
1929         return Jump(m_assembler.jmp());
1930     }
1931
1932     void jump(RegisterID target)
1933     {
1934         m_assembler.jmpReg(target);
1935     }
1936
1937     void jump(Address address)
1938     {
1939         RegisterID scr = claimScratch();
1940         load32(address, scr);
1941         m_assembler.jmpReg(scr);
1942         releaseScratch(scr);
1943     }
1944
1945     void jump(AbsoluteAddress address)
1946     {
1947         RegisterID scr = claimScratch();
1948
1949         move(TrustedImmPtr(address.m_ptr), scr);
1950         m_assembler.movlMemReg(scr, scr);
1951         m_assembler.jmpReg(scr);
1952         releaseScratch(scr);
1953     }
1954
1955     // Arithmetic control flow operations
1956
1957     Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
1958     {
1959         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1960
1961         if (cond == Overflow)
1962             return branchMul32(cond, TrustedImm32(-1), srcDest, srcDest);
1963
1964         neg32(srcDest);
1965
1966         if (cond == Signed) {
1967             m_assembler.cmppz(srcDest);
1968             return branchFalse();
1969         }
1970
1971         compare32(0, srcDest, Equal);
1972         return (cond == NonZero) ? branchFalse() : branchTrue();
1973     }
1974
1975     Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
1976     {
1977         ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
1978
1979         if (cond == Overflow) {
1980             m_assembler.addvlRegReg(src, dest);
1981             return branchTrue();
1982         }
1983
1984         m_assembler.addlRegReg(src, dest);
1985
1986         if ((cond == Signed) || (cond == PositiveOrZero)) {
1987             m_assembler.cmppz(dest);
1988             return (cond == Signed) ? branchFalse() : branchTrue();
1989         }
1990
1991         compare32(0, dest, Equal);
1992         return (cond == NonZero) ? branchFalse() : branchTrue();
1993     }
1994
1995     Jump branchAdd32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
1996     {
1997         ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
1998
1999         if (cond == Overflow) {
2000             if (src1 == dest)
2001                 m_assembler.addvlRegReg(src2, dest);
2002             else {
2003                 move(src2, dest);
2004                 m_assembler.addvlRegReg(src1, dest);
2005             }
2006             return branchTrue();
2007         }
2008
2009         add32(src1, src2, dest);
2010
2011         if ((cond == Signed) || (cond == PositiveOrZero)) {
2012             m_assembler.cmppz(dest);
2013             return (cond == Signed) ? branchFalse() : branchTrue();
2014         }
2015
2016         compare32(0, dest, Equal);
2017         return (cond == NonZero) ? branchFalse() : branchTrue();
2018     }
2019
2020     Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
2021     {
2022         ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
2023
2024         RegisterID immval = claimScratch();
2025         move(imm, immval);
2026         Jump result = branchAdd32(cond, immval, dest);
2027         releaseScratch(immval);
2028         return result;
2029     }
2030
2031     Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
2032     {
2033         ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
2034
2035         move(src, dest);
2036
2037         if (cond == Overflow) {
2038             move(imm, scratchReg3);
2039             m_assembler.addvlRegReg(scratchReg3, dest);
2040             return branchTrue();
2041         }
2042
2043         add32(imm, dest);
2044
2045         if ((cond == Signed) || (cond == PositiveOrZero)) {
2046             m_assembler.cmppz(dest);
2047             return (cond == Signed) ? branchFalse() : branchTrue();
2048         }
2049
2050         compare32(0, dest, Equal);
2051         return (cond == NonZero) ? branchFalse() : branchTrue();
2052     }
2053
2054     Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
2055     {
2056         ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
2057         bool result;
2058
2059         move(imm, scratchReg3);
2060         RegisterID destptr = claimScratch();
2061         RegisterID destval = claimScratch();
2062         move(TrustedImmPtr(dest.m_ptr), destptr);
2063         m_assembler.movlMemReg(destptr, destval);
2064         if (cond == Overflow) {
2065             m_assembler.addvlRegReg(scratchReg3, destval);
2066             result = true;
2067         } else {
2068             m_assembler.addlRegReg(scratchReg3, destval);
2069             if ((cond == Signed) || (cond == PositiveOrZero)) {
2070                 m_assembler.cmppz(destval);
2071                 result = (cond == PositiveOrZero);
2072             } else {
2073                 m_assembler.testlRegReg(destval, destval);
2074                 result = (cond != NonZero);
2075             }
2076         }
2077         m_assembler.movlRegMem(destval, destptr);
2078         releaseScratch(destval);
2079         releaseScratch(destptr);
2080         return result ? branchTrue() : branchFalse();
2081     }
2082
2083     Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
2084     {
2085         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2086
2087         if (cond == Overflow) {
2088             RegisterID scrsign = claimScratch();
2089             RegisterID msbres = claimScratch();
2090             m_assembler.dmulslRegReg(src, dest);
2091             m_assembler.stsmacl(dest);
2092             m_assembler.cmppz(dest);
2093             m_assembler.movt(scrsign);
2094             m_assembler.addlImm8r(-1, scrsign);
2095             m_assembler.stsmach(msbres);
2096             m_assembler.cmplRegReg(msbres, scrsign, SH4Condition(Equal));
2097             releaseScratch(msbres);
2098             releaseScratch(scrsign);
2099             return branchFalse();
2100         }
2101
2102         mul32(src, dest);
2103
2104         if (cond == Signed) {
2105             m_assembler.cmppz(dest);
2106             return branchFalse();
2107         }
2108
2109         compare32(0, dest, static_cast<RelationalCondition>(cond));
2110         return (cond == NonZero) ? branchFalse() : branchTrue();
2111     }
2112
2113     Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
2114     {
2115         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2116
2117         if (cond == Overflow) {
2118             RegisterID scrsign = claimScratch();
2119             RegisterID msbres = claimScratch();
2120             m_assembler.dmulslRegReg(src1, src2);
2121             m_assembler.stsmacl(dest);
2122             m_assembler.cmppz(dest);
2123             m_assembler.movt(scrsign);
2124             m_assembler.addlImm8r(-1, scrsign);
2125             m_assembler.stsmach(msbres);
2126             m_assembler.cmplRegReg(msbres, scrsign, SH4Condition(Equal));
2127             releaseScratch(msbres);
2128             releaseScratch(scrsign);
2129             return branchFalse();
2130         }
2131
2132         mul32(src1, src2, dest);
2133
2134         if (cond == Signed) {
2135             m_assembler.cmppz(dest);
2136             return branchFalse();
2137         }
2138
2139         compare32(0, dest, Equal);
2140         return (cond == NonZero) ? branchFalse() : branchTrue();
2141     }
2142
2143     Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
2144     {
2145         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2146
2147         if (src == dest) {
2148             move(imm, scratchReg3);
2149             return branchMul32(cond, scratchReg3, dest);
2150         }
2151
2152         move(imm, dest);
2153         return branchMul32(cond, src, dest);
2154     }
2155
2156     Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
2157     {
2158         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2159
2160         if (cond == Overflow) {
2161             m_assembler.subvlRegReg(src, dest);
2162             return branchTrue();
2163         }
2164
2165         sub32(src, dest);
2166
2167         if (cond == Signed) {
2168             m_assembler.cmppz(dest);
2169             return branchFalse();
2170         }
2171
2172         compare32(0, dest, static_cast<RelationalCondition>(cond));
2173         return (cond == NonZero) ? branchFalse() : branchTrue();
2174     }
2175
2176     Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
2177     {
2178         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2179
2180         RegisterID immval = claimScratch();
2181         move(imm, immval);
2182         Jump result = branchSub32(cond, immval, dest);
2183         releaseScratch(immval);
2184         return result;
2185     }
2186
2187     Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
2188     {
2189         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2190
2191         move(src, dest);
2192         return branchSub32(cond, imm, dest);
2193     }
2194
2195     Jump branchSub32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
2196     {
2197         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2198
2199         if (src2 != dest) {
2200             move(src1, dest);
2201             return branchSub32(cond, src2, dest);
2202         }
2203
2204         if (cond == Overflow) {
2205             RegisterID tmpval = claimScratch();
2206             move(src1, tmpval);
2207             m_assembler.subvlRegReg(src2, tmpval);
2208             move(tmpval, dest);
2209             releaseScratch(tmpval);
2210             return branchTrue();
2211         }
2212
2213         RegisterID tmpval = claimScratch();
2214         move(src1, tmpval);
2215         sub32(src2, tmpval);
2216         move(tmpval, dest);
2217         releaseScratch(tmpval);
2218
2219         if (cond == Signed) {
2220             m_assembler.cmppz(dest);
2221             return branchFalse();
2222         }
2223
2224         compare32(0, dest, static_cast<RelationalCondition>(cond));
2225         return (cond == NonZero) ? branchFalse() : branchTrue();
2226     }
2227
2228     Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
2229     {
2230         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
2231
2232         or32(src, dest);
2233
2234         if (cond == Signed) {
2235             m_assembler.cmppz(dest);
2236             return branchFalse();
2237         }
2238
2239         compare32(0, dest, static_cast<RelationalCondition>(cond));
2240         return (cond == NonZero) ? branchFalse() : branchTrue();
2241     }
2242
2243     void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID, bool negZeroCheck = true)
2244     {
2245         truncateDoubleToInt32(src, dest);
2246         convertInt32ToDouble(dest, fscratch);
2247         failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fscratch, src));
2248
2249         if (negZeroCheck)
2250             failureCases.append(branch32(Equal, dest, TrustedImm32(0)));
2251     }
2252
2253     void neg32(RegisterID dst)
2254     {
2255         m_assembler.neg(dst, dst);
2256     }
2257
2258     void urshift32(RegisterID shiftamount, RegisterID dest)
2259     {
2260         RegisterID shiftTmp = claimScratch();
2261         m_assembler.loadConstant(0x1f, shiftTmp);
2262         m_assembler.andlRegReg(shiftamount, shiftTmp);
2263         m_assembler.neg(shiftTmp, shiftTmp);
2264         m_assembler.shldRegReg(dest, shiftTmp);
2265         releaseScratch(shiftTmp);
2266     }
2267
2268     void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
2269     {
2270         move(src, dest);
2271         urshift32(shiftAmount, dest);
2272     }
2273
2274     void urshift32(TrustedImm32 imm, RegisterID dest)
2275     {
2276         int immMasked = imm.m_value & 0x1f;
2277         if (!immMasked)
2278             return;
2279
2280         if ((immMasked == 1) || (immMasked == 2) || (immMasked == 8) || (immMasked == 16)) {
2281             m_assembler.shlrImm8r(immMasked, dest);
2282             return;
2283         }
2284
2285         RegisterID shiftTmp = claimScratch();
2286         m_assembler.loadConstant(-immMasked, shiftTmp);
2287         m_assembler.shldRegReg(dest, shiftTmp);
2288         releaseScratch(shiftTmp);
2289     }
2290
2291     void urshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest)
2292     {
2293         move(src, dest);
2294         urshift32(shiftamount, dest);
2295     }
2296
2297     Call call()
2298     {
2299         return Call(m_assembler.call(), Call::Linkable);
2300     }
2301
2302     Call nearCall()
2303     {
2304         return Call(m_assembler.call(), Call::LinkableNear);
2305     }
2306
2307     Call call(RegisterID target)
2308     {
2309         return Call(m_assembler.call(target), Call::None);
2310     }
2311
2312     void call(Address address, RegisterID target)
2313     {
2314         load32(address.base, address.offset, target);
2315         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 2);
2316         m_assembler.branch(JSR_OPCODE, target);
2317         m_assembler.nop();
2318     }
2319
2320     void breakpoint()
2321     {
2322         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 2);
2323         m_assembler.bkpt();
2324         m_assembler.nop();
2325     }
2326
2327     Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
2328     {
2329         RegisterID dataTempRegister = claimScratch();
2330
2331         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 10, 2 * sizeof(uint32_t));
2332         dataLabel = moveWithPatch(initialRightValue, dataTempRegister);
2333         m_assembler.cmplRegReg(dataTempRegister, left, SH4Condition(cond));
2334         releaseScratch(dataTempRegister);
2335
2336         if (cond == NotEqual)
2337             return branchFalse();
2338         return branchTrue();
2339     }
2340
2341     Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
2342     {
2343         RegisterID scr = claimScratch();
2344
2345         m_assembler.loadConstant(left.offset, scr);
2346         m_assembler.addlRegReg(left.base, scr);
2347         m_assembler.movlMemReg(scr, scr);
2348         RegisterID scr1 = claimScratch();
2349         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 10, 2 * sizeof(uint32_t));
2350         dataLabel = moveWithPatch(initialRightValue, scr1);
2351         m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
2352         releaseScratch(scr);
2353         releaseScratch(scr1);
2354
2355         if (cond == NotEqual)
2356             return branchFalse();
2357         return branchTrue();
2358     }
2359
2360     void ret()
2361     {
2362         m_assembler.ret();
2363         m_assembler.nop();
2364     }
2365
2366     DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
2367     {
2368         RegisterID scr = claimScratch();
2369         DataLabelPtr label = moveWithPatch(initialValue, scr);
2370         store32(scr, address);
2371         releaseScratch(scr);
2372         return label;
2373     }
2374
2375     DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(TrustedImmPtr(0), address); }
2376
2377     int sizeOfConstantPool()
2378     {
2379         return m_assembler.sizeOfConstantPool();
2380     }
2381
2382     Call tailRecursiveCall()
2383     {
2384         RegisterID scr = claimScratch();
2385
2386         m_assembler.loadConstantUnReusable(0x0, scr, true);
2387         Jump m_jump = Jump(m_assembler.jmp(scr));
2388         releaseScratch(scr);
2389
2390         return Call::fromTailJump(m_jump);
2391     }
2392
2393     Call makeTailRecursiveCall(Jump oldJump)
2394     {
2395         oldJump.link(this);
2396         return tailRecursiveCall();
2397     }
2398
2399     void nop()
2400     {
2401         m_assembler.nop();
2402     }
2403
2404     static FunctionPtr readCallTarget(CodeLocationCall call)
2405     {
2406         return FunctionPtr(reinterpret_cast<void(*)()>(SH4Assembler::readCallTarget(call.dataLocation())));
2407     }
2408
2409     static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
2410     {
2411         SH4Assembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation());
2412     }
2413     
2414     static ptrdiff_t maxJumpReplacementSize()
2415     {
2416         return SH4Assembler::maxJumpReplacementSize();
2417     }
2418
2419     static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; }
2420
2421     static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label)
2422     {
2423         return label.labelAtOffset(0);
2424     }
2425
2426     static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID rd, void* initialValue)
2427     {
2428         SH4Assembler::revertJumpToMove(instructionStart.dataLocation(), rd, reinterpret_cast<int>(initialValue));
2429     }
2430
2431     static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr)
2432     {
2433         UNREACHABLE_FOR_PLATFORM();
2434         return CodeLocationLabel();
2435     }
2436
2437     static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, Address, void* initialValue)
2438     {
2439         UNREACHABLE_FOR_PLATFORM();
2440     }
2441
2442 protected:
2443     SH4Assembler::Condition SH4Condition(RelationalCondition cond)
2444     {
2445         return static_cast<SH4Assembler::Condition>(cond);
2446     }
2447
2448     SH4Assembler::Condition SH4Condition(ResultCondition cond)
2449     {
2450         return static_cast<SH4Assembler::Condition>(cond);
2451     }
2452 private:
2453     friend class LinkBuffer;
2454     friend class RepatchBuffer;
2455
2456     static void linkCall(void* code, Call call, FunctionPtr function)
2457     {
2458         SH4Assembler::linkCall(code, call.m_label, function.value());
2459     }
2460
2461     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
2462     {
2463         SH4Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
2464     }
2465
2466     static void repatchCall(CodeLocationCall call, FunctionPtr destination)
2467     {
2468         SH4Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
2469     }
2470 };
2471
2472 } // namespace JSC
2473
2474 #endif // ENABLE(ASSEMBLER)
2475
2476 #endif // MacroAssemblerSH4_h