tizen beta release
[profile/ivi/webkit-efl.git] / Source / JavaScriptCore / assembler / MacroAssemblerSH4.h
1 /*
2  * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved.
3  * Copyright (C) 2008 Apple 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 APPLE 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 APPLE 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 MacroAssemblerSH4_h
28 #define MacroAssemblerSH4_h
29
30 #if ENABLE(ASSEMBLER) && CPU(SH4)
31
32 #include "SH4Assembler.h"
33 #include "AbstractMacroAssembler.h"
34 #include <wtf/Assertions.h>
35
36 namespace JSC {
37
38 class MacroAssemblerSH4 : public AbstractMacroAssembler<SH4Assembler> {
39 public:
40     typedef SH4Assembler::FPRegisterID FPRegisterID;
41
42     static const Scale ScalePtr = TimesFour;
43     static const FPRegisterID fscratch = SH4Registers::fr10;
44     static const RegisterID stackPointerRegister = SH4Registers::sp;
45     static const RegisterID linkRegister = SH4Registers::pr;
46     static const RegisterID scratchReg3 = SH4Registers::r13;
47
48     static const int MaximumCompactPtrAlignedAddressOffset = 60;
49
50     enum RelationalCondition {
51         Equal = SH4Assembler::EQ,
52         NotEqual = SH4Assembler::NE,
53         Above = SH4Assembler::HI,
54         AboveOrEqual = SH4Assembler::HS,
55         Below = SH4Assembler::LI,
56         BelowOrEqual = SH4Assembler::LS,
57         GreaterThan = SH4Assembler::GT,
58         GreaterThanOrEqual = SH4Assembler::GE,
59         LessThan = SH4Assembler::LT,
60         LessThanOrEqual = SH4Assembler::LE
61     };
62
63     enum ResultCondition {
64         Overflow = SH4Assembler::OF,
65         Signed = SH4Assembler::SI,
66         Zero = SH4Assembler::EQ,
67         NonZero = SH4Assembler::NE
68     };
69
70     enum DoubleCondition {
71         // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
72         DoubleEqual = SH4Assembler::EQ,
73         DoubleNotEqual = SH4Assembler::NE,
74         DoubleGreaterThan = SH4Assembler::GT,
75         DoubleGreaterThanOrEqual = SH4Assembler::GE,
76         DoubleLessThan = SH4Assembler::LT,
77         DoubleLessThanOrEqual = SH4Assembler::LE,
78         // If either operand is NaN, these conditions always evaluate to true.
79         DoubleEqualOrUnordered = SH4Assembler::EQU,
80         DoubleNotEqualOrUnordered = SH4Assembler::NEU,
81         DoubleGreaterThanOrUnordered = SH4Assembler::GTU,
82         DoubleGreaterThanOrEqualOrUnordered = SH4Assembler::GEU,
83         DoubleLessThanOrUnordered = SH4Assembler::LTU,
84         DoubleLessThanOrEqualOrUnordered = SH4Assembler::LEU,
85     };
86
87     RegisterID claimScratch()
88     {
89         return m_assembler.claimScratch();
90     }
91
92     void releaseScratch(RegisterID reg)
93     {
94         m_assembler.releaseScratch(reg);
95     }
96
97     // Integer arithmetic operations
98
99     void add32(RegisterID src, RegisterID dest)
100     {
101         m_assembler.addlRegReg(src, dest);
102     }
103
104     void add32(TrustedImm32 imm, RegisterID dest)
105     {
106         if (m_assembler.isImmediate(imm.m_value)) {
107             m_assembler.addlImm8r(imm.m_value, dest);
108             return;
109         }
110
111         RegisterID scr = claimScratch();
112         m_assembler.loadConstant(imm.m_value, scr);
113         m_assembler.addlRegReg(scr, dest);
114         releaseScratch(scr);
115     }
116
117     void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
118     {
119         if (src != dest)
120             m_assembler.movlRegReg(src, dest);
121         add32(imm, dest);
122     }
123
124     void add32(TrustedImm32 imm, Address address)
125     {
126         RegisterID scr = claimScratch();
127         load32(address, scr);
128         add32(imm, scr);
129         store32(scr, address);
130         releaseScratch(scr);
131     }
132
133     void add32(Address src, RegisterID dest)
134     {
135         RegisterID scr = claimScratch();
136         load32(src, scr);
137         m_assembler.addlRegReg(scr, dest);
138         releaseScratch(scr);
139     }
140
141     void and32(RegisterID src, RegisterID dest)
142     {
143         m_assembler.andlRegReg(src, dest);
144     }
145
146     void and32(TrustedImm32 imm, RegisterID dest)
147     {
148         if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) {
149             m_assembler.andlImm8r(imm.m_value, dest);
150             return;
151         }
152
153         RegisterID scr = claimScratch();
154         m_assembler.loadConstant((imm.m_value), scr);
155         m_assembler.andlRegReg(scr, dest);
156         releaseScratch(scr);
157     }
158
159     void lshift32(RegisterID shiftamount, RegisterID dest)
160     {
161         m_assembler.shllRegReg(dest, shiftamount);
162     }
163
164     void rshift32(int imm, RegisterID dest)
165     {
166         RegisterID scr = claimScratch();
167         m_assembler.loadConstant(-imm, scr);
168         m_assembler.shaRegReg(dest, scr);
169         releaseScratch(scr);
170     }
171
172     void lshift32(TrustedImm32 imm, RegisterID dest)
173     {
174         if ((imm.m_value == 1) || (imm.m_value == 2) || (imm.m_value == 8) || (imm.m_value == 16)) {
175             m_assembler.shllImm8r(imm.m_value, dest);
176             return;
177         }
178
179         RegisterID scr = claimScratch();
180         m_assembler.loadConstant(imm.m_value, scr);
181         m_assembler.shllRegReg(dest, scr);
182         releaseScratch(scr);
183     }
184
185     void mul32(RegisterID src, RegisterID dest)
186     {
187         m_assembler.imullRegReg(src, dest);
188         m_assembler.stsmacl(dest);
189     }
190
191     void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
192     {
193         RegisterID scr = claimScratch();
194         move(imm, scr);
195         if  (src != dest)
196             move(src, dest);
197         mul32(scr,  dest);
198         releaseScratch(scr);
199     }
200
201     void not32(RegisterID src, RegisterID dest)
202     {
203         m_assembler.notlReg(src, dest);
204     }
205
206     void or32(RegisterID src, RegisterID dest)
207     {
208         m_assembler.orlRegReg(src, dest);
209     }
210
211     void or32(TrustedImm32 imm, RegisterID dest)
212     {
213         if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) {
214             m_assembler.orlImm8r(imm.m_value, dest);
215             return;
216         }
217
218         RegisterID scr = claimScratch();
219         m_assembler.loadConstant(imm.m_value, scr);
220         m_assembler.orlRegReg(scr, dest);
221         releaseScratch(scr);
222     }
223
224     void or32(RegisterID op1, RegisterID op2, RegisterID dest)
225     {
226         if (op1 == op2)
227             move(op1, dest);
228         else if (op1 == dest)
229             or32(op2, dest);
230         else {
231             move(op2, dest);
232             or32(op1, dest);
233         }
234     }
235
236     void rshift32(RegisterID shiftamount, RegisterID dest)
237     {
238         compare32(32, shiftamount, Equal);
239         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
240         m_assembler.branch(BT_OPCODE, 1);
241         m_assembler.neg(shiftamount, shiftamount);
242         m_assembler.shaRegReg(dest, shiftamount);
243     }
244
245     void rshift32(TrustedImm32 imm, RegisterID dest)
246     {
247         if (imm.m_value & 0x1f)
248             rshift32(imm.m_value & 0x1f, dest);
249     }
250
251     void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
252     {
253         if (src != dest)
254             move(src, dest);
255         rshift32(imm, dest);
256     }
257
258     void sub32(RegisterID src, RegisterID dest)
259     {
260         m_assembler.sublRegReg(src, dest);
261     }
262
263     void sub32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg)
264     {
265         RegisterID result = claimScratch();
266
267         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
268         m_assembler.movlMemReg(scratchReg, result);
269
270         if (m_assembler.isImmediate(-imm.m_value))
271             m_assembler.addlImm8r(-imm.m_value, result);
272         else {
273             m_assembler.loadConstant(imm.m_value, scratchReg3);
274             m_assembler.sublRegReg(scratchReg3, result);
275         }
276
277         store32(result, scratchReg);
278         releaseScratch(result);
279     }
280
281     void sub32(TrustedImm32 imm, AbsoluteAddress address)
282     {
283         RegisterID result = claimScratch();
284         RegisterID scratchReg = claimScratch();
285
286         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
287         m_assembler.movlMemReg(scratchReg, result);
288
289         if (m_assembler.isImmediate(-imm.m_value))
290             m_assembler.addlImm8r(-imm.m_value, result);
291         else {
292             m_assembler.loadConstant(imm.m_value, scratchReg3);
293             m_assembler.sublRegReg(scratchReg3, result);
294         }
295
296         store32(result, scratchReg);
297         releaseScratch(result);
298         releaseScratch(scratchReg);
299     }
300
301     void add32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg)
302     {
303         RegisterID result = claimScratch();
304
305         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
306         m_assembler.movlMemReg(scratchReg, result);
307
308         if (m_assembler.isImmediate(imm.m_value))
309             m_assembler.addlImm8r(imm.m_value, result);
310         else {
311             m_assembler.loadConstant(imm.m_value, scratchReg3);
312             m_assembler.addlRegReg(scratchReg3, result);
313         }
314
315         store32(result, scratchReg);
316         releaseScratch(result);
317     }
318
319     void add32(TrustedImm32 imm, AbsoluteAddress address)
320     {
321         RegisterID result = claimScratch();
322         RegisterID scratchReg = claimScratch();
323
324         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
325         m_assembler.movlMemReg(scratchReg, result);
326
327         if (m_assembler.isImmediate(imm.m_value))
328             m_assembler.addlImm8r(imm.m_value, result);
329         else {
330             m_assembler.loadConstant(imm.m_value, scratchReg3);
331             m_assembler.addlRegReg(scratchReg3, result);
332         }
333
334         store32(result, scratchReg);
335         releaseScratch(result);
336         releaseScratch(scratchReg);
337     }
338
339     void sub32(TrustedImm32 imm, RegisterID dest)
340     {
341         if (m_assembler.isImmediate(-imm.m_value)) {
342             m_assembler.addlImm8r(-imm.m_value, dest);
343             return;
344         }
345
346         RegisterID scr = claimScratch();
347         m_assembler.loadConstant(imm.m_value, scr);
348         m_assembler.sublRegReg(scr, dest);
349         releaseScratch(scr);
350     }
351
352     void sub32(Address src, RegisterID dest)
353     {
354         RegisterID scr = claimScratch();
355         load32(src, scr);
356         m_assembler.sublRegReg(scr, dest);
357         releaseScratch(scr);
358     }
359
360     void xor32(RegisterID src, RegisterID dest)
361     {
362         m_assembler.xorlRegReg(src, dest);
363     }
364
365     void xor32(TrustedImm32 imm, RegisterID srcDest)
366     {
367         if ((srcDest != SH4Registers::r0) || (imm.m_value > 255) || (imm.m_value < 0)) {
368             RegisterID scr = claimScratch();
369             m_assembler.loadConstant((imm.m_value), scr);
370             m_assembler.xorlRegReg(scr, srcDest);
371             releaseScratch(scr);
372             return;
373         }
374
375         m_assembler.xorlImm8r(imm.m_value, srcDest);
376     }
377
378     void compare32(int imm, RegisterID dst, RelationalCondition cond)
379     {
380         if (((cond == Equal) || (cond == NotEqual)) && (dst == SH4Registers::r0) && m_assembler.isImmediate(imm)) {
381             m_assembler.cmpEqImmR0(imm, dst);
382             return;
383         }
384
385         RegisterID scr = claimScratch();
386         m_assembler.loadConstant(imm, scr);
387         m_assembler.cmplRegReg(scr, dst, SH4Condition(cond));
388         releaseScratch(scr);
389     }
390
391     void compare32(int offset, RegisterID base, RegisterID left, RelationalCondition cond)
392     {
393         RegisterID scr = claimScratch();
394         if (!offset) {
395             m_assembler.movlMemReg(base, scr);
396             m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
397             releaseScratch(scr);
398             return;
399         }
400
401         if ((offset < 0) || (offset >= 64)) {
402             m_assembler.loadConstant(offset, scr);
403             m_assembler.addlRegReg(base, scr);
404             m_assembler.movlMemReg(scr, scr);
405             m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
406             releaseScratch(scr);
407             return;
408         }
409
410         m_assembler.movlMemReg(offset >> 2, base, scr);
411         m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
412         releaseScratch(scr);
413     }
414
415     void testImm(int imm, int offset, RegisterID base)
416     {
417         RegisterID scr = claimScratch();
418         RegisterID scr1 = claimScratch();
419
420         if ((offset < 0) || (offset >= 64)) {
421             m_assembler.loadConstant(offset, scr);
422             m_assembler.addlRegReg(base, scr);
423             m_assembler.movlMemReg(scr, scr);
424         } else if (offset)
425             m_assembler.movlMemReg(offset >> 2, base, scr);
426         else
427             m_assembler.movlMemReg(base, scr);
428         if (m_assembler.isImmediate(imm))
429             m_assembler.movImm8(imm, scr1);
430         else
431             m_assembler.loadConstant(imm, scr1);
432
433         m_assembler.testlRegReg(scr, scr1);
434         releaseScratch(scr);
435         releaseScratch(scr1);
436     }
437
438     void testlImm(int imm, RegisterID dst)
439     {
440         if ((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0)) {
441             m_assembler.testlImm8r(imm, dst);
442             return;
443         }
444
445         RegisterID scr = claimScratch();
446         m_assembler.loadConstant(imm, scr);
447         m_assembler.testlRegReg(scr, dst);
448         releaseScratch(scr);
449     }
450
451     void compare32(RegisterID right, int offset, RegisterID base, RelationalCondition cond)
452     {
453         if (!offset) {
454             RegisterID scr = claimScratch();
455             m_assembler.movlMemReg(base, scr);
456             m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
457             releaseScratch(scr);
458             return;
459         }
460
461         if ((offset < 0) || (offset >= 64)) {
462             RegisterID scr = claimScratch();
463             m_assembler.loadConstant(offset, scr);
464             m_assembler.addlRegReg(base, scr);
465             m_assembler.movlMemReg(scr, scr);
466             m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
467             releaseScratch(scr);
468             return;
469         }
470
471         RegisterID scr = claimScratch();
472         m_assembler.movlMemReg(offset >> 2, base, scr);
473         m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
474         releaseScratch(scr);
475     }
476
477     void compare32(int imm, int offset, RegisterID base, RelationalCondition cond)
478     {
479         if (!offset) {
480             RegisterID scr = claimScratch();
481             RegisterID scr1 = claimScratch();
482             m_assembler.movlMemReg(base, scr);
483             m_assembler.loadConstant(imm, scr1);
484             m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
485             releaseScratch(scr1);
486             releaseScratch(scr);
487             return;
488         }
489
490         if ((offset < 0) || (offset >= 64)) {
491             RegisterID scr = claimScratch();
492             RegisterID scr1 = claimScratch();
493             m_assembler.loadConstant(offset, scr);
494             m_assembler.addlRegReg(base, scr);
495             m_assembler.movlMemReg(scr, scr);
496             m_assembler.loadConstant(imm, scr1);
497             m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
498             releaseScratch(scr1);
499             releaseScratch(scr);
500             return;
501         }
502
503         RegisterID scr = claimScratch();
504         RegisterID scr1 = claimScratch();
505         m_assembler.movlMemReg(offset >> 2, base, scr);
506         m_assembler.loadConstant(imm, scr1);
507         m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
508         releaseScratch(scr1);
509         releaseScratch(scr);
510     }
511
512     // Memory access operation
513
514     void load32(ImplicitAddress address, RegisterID dest)
515     {
516         load32(address.base, address.offset, dest);
517     }
518
519     void load8(ImplicitAddress address, RegisterID dest)
520     {
521         load8(address.base, address.offset, dest);
522     }
523
524     void load8(BaseIndex address, RegisterID dest)
525     {
526         RegisterID scr = claimScratch();
527         move(address.index, scr);
528         lshift32(TrustedImm32(address.scale), scr);
529         add32(address.base, scr);
530         load8(scr, address.offset, dest);
531         releaseScratch(scr);
532     }
533
534     void load32(BaseIndex address, RegisterID dest)
535     {
536         RegisterID scr = claimScratch();
537         move(address.index, scr);
538         lshift32(TrustedImm32(address.scale), scr);
539         add32(address.base, scr);
540         load32(scr, address.offset, dest);
541         releaseScratch(scr);
542     }
543
544     void load32(const void* address, RegisterID dest)
545     {
546         m_assembler.loadConstant(reinterpret_cast<uint32_t>(const_cast<void*>(address)), dest);
547         m_assembler.movlMemReg(dest, dest);
548     }
549
550     void load32(RegisterID base, int offset, RegisterID dest)
551     {
552         if (!offset) {
553             m_assembler.movlMemReg(base, dest);
554             return;
555         }
556
557         if ((offset >= 0) && (offset < 64)) {
558             m_assembler.movlMemReg(offset >> 2, base, dest);
559             return;
560         }
561
562         if ((dest == SH4Registers::r0) && (dest != base)) {
563             m_assembler.loadConstant((offset), dest);
564             m_assembler.movlR0mr(base, dest);
565             return;
566         }
567
568         RegisterID scr;
569         if (dest == base)
570             scr = claimScratch();
571         else
572             scr = dest;
573         m_assembler.loadConstant((offset), scr);
574         m_assembler.addlRegReg(base, scr);
575         m_assembler.movlMemReg(scr, dest);
576
577         if (dest == base)
578             releaseScratch(scr);
579     }
580
581     void load8(RegisterID base, int offset, RegisterID dest)
582     {
583         if (!offset) {
584             m_assembler.movbMemReg(base, dest);
585             return;
586         }
587
588         if ((offset > 0) && (offset < 64) && (dest == SH4Registers::r0)) {
589             m_assembler.movbMemReg(offset, base, dest);
590             return;
591         }
592
593         if (base != dest) {
594             m_assembler.loadConstant((offset), dest);
595             m_assembler.addlRegReg(base, dest);
596             m_assembler.movbMemReg(dest, dest);
597             return;
598         }
599
600         RegisterID scr = claimScratch();
601         m_assembler.loadConstant((offset), scr);
602         m_assembler.addlRegReg(base, scr);
603         m_assembler.movbMemReg(scr, dest);
604         releaseScratch(scr);
605     }
606
607     void load32(RegisterID r0, RegisterID src, RegisterID dst)
608     {
609         ASSERT(r0 == SH4Registers::r0);
610         m_assembler.movlR0mr(src, dst);
611     }
612
613     void load32(RegisterID src, RegisterID dst)
614     {
615         m_assembler.movlMemReg(src, dst);
616     }
617
618     void load16(ImplicitAddress address, RegisterID dest)
619     {
620         if (!address.offset) {
621             m_assembler.movwMemReg(address.base, dest);
622             return;
623         }
624
625         if ((address.offset > 0) && (address.offset < 64) && (dest == SH4Registers::r0)) {
626             m_assembler.movwMemReg(address.offset, address.base, dest);
627             return;
628         }
629
630         if (address.base != dest) {
631             m_assembler.loadConstant((address.offset), dest);
632             m_assembler.addlRegReg(address.base, dest);
633             m_assembler.movwMemReg(dest, dest);
634             return;
635         }
636
637         RegisterID scr = claimScratch();
638         m_assembler.loadConstant((address.offset), scr);
639         m_assembler.addlRegReg(address.base, scr);
640         m_assembler.movwMemReg(scr, dest);
641         releaseScratch(scr);
642     }
643
644     void load16(RegisterID src, RegisterID dest)
645     {
646         m_assembler.movwMemReg(src, dest);
647     }
648
649     void load16(RegisterID r0, RegisterID src, RegisterID dest)
650     {
651         ASSERT(r0 == SH4Registers::r0);
652         m_assembler.movwR0mr(src, dest);
653     }
654
655     void load16(BaseIndex address, RegisterID dest)
656     {
657         RegisterID scr = claimScratch();
658
659         move(address.index, scr);
660         lshift32(TrustedImm32(address.scale), scr);
661
662         if (address.offset)
663             add32(TrustedImm32(address.offset), scr);
664         if (scr == SH4Registers::r0)
665             m_assembler.movwR0mr(address.base, scr);
666         else {
667             add32(address.base, scr);
668             load16(scr, scr);
669         }
670
671         extuw(scr, dest);
672         releaseScratch(scr);
673     }
674
675     void store32(RegisterID src, ImplicitAddress address)
676     {
677         RegisterID scr = claimScratch();
678         store32(src, address.offset, address.base, scr);
679         releaseScratch(scr);
680     }
681
682     void store32(RegisterID src, int offset, RegisterID base, RegisterID scr)
683     {
684         if (!offset) {
685             m_assembler.movlRegMem(src, base);
686             return;
687         }
688
689         if ((offset >=0) && (offset < 64)) {
690             m_assembler.movlRegMem(src, offset >> 2, base);
691             return;
692         }
693
694         m_assembler.loadConstant((offset), scr);
695         if (scr == SH4Registers::r0) {
696             m_assembler.movlRegMemr0(src, base);
697             return;
698         }
699
700         m_assembler.addlRegReg(base, scr);
701         m_assembler.movlRegMem(src, scr);
702     }
703
704     void store32(RegisterID src, RegisterID offset, RegisterID base)
705     {
706         ASSERT(offset == SH4Registers::r0);
707         m_assembler.movlRegMemr0(src, base);
708     }
709
710     void store32(RegisterID src, RegisterID dst)
711     {
712         m_assembler.movlRegMem(src, dst);
713     }
714
715     void store32(TrustedImm32 imm, ImplicitAddress address)
716     {
717         RegisterID scr = claimScratch();
718         RegisterID scr1 = claimScratch();
719         m_assembler.loadConstant((imm.m_value), scr);
720         store32(scr, address.offset, address.base, scr1);
721         releaseScratch(scr);
722         releaseScratch(scr1);
723     }
724
725     void store32(RegisterID src, BaseIndex address)
726     {
727         RegisterID scr = claimScratch();
728
729         move(address.index, scr);
730         lshift32(TrustedImm32(address.scale), scr);
731         add32(address.base, scr);
732         store32(src, Address(scr, address.offset));
733
734         releaseScratch(scr);
735     }
736
737     void store32(TrustedImm32 imm, void* address)
738     {
739         RegisterID scr = claimScratch();
740         RegisterID scr1 = claimScratch();
741         m_assembler.loadConstant((imm.m_value), scr);
742         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr1);
743         m_assembler.movlRegMem(scr, scr1);
744         releaseScratch(scr);
745         releaseScratch(scr1);
746     }
747
748     void store32(RegisterID src, void* address)
749     {
750         RegisterID scr = claimScratch();
751         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
752         m_assembler.movlRegMem(src, scr);
753         releaseScratch(scr);
754     }
755
756     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
757     {
758         RegisterID scr = claimScratch();
759         DataLabel32 label(this);
760         m_assembler.loadConstantUnReusable(address.offset, scr);
761         m_assembler.addlRegReg(address.base, scr);
762         m_assembler.movlMemReg(scr, dest);
763         releaseScratch(scr);
764         return label;
765     }
766     
767     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
768     {
769         RegisterID scr = claimScratch();
770         DataLabel32 label(this);
771         m_assembler.loadConstantUnReusable(address.offset, scr);
772         m_assembler.addlRegReg(address.base, scr);
773         m_assembler.movlRegMem(src, scr);
774         releaseScratch(scr);
775         return label;
776     }
777
778     DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
779     {
780         DataLabelCompact dataLabel(this);
781         ASSERT(address.offset <= MaximumCompactPtrAlignedAddressOffset);
782         ASSERT(address.offset >= 0);
783         m_assembler.movlMemRegCompact(address.offset >> 2, address.base, dest);
784         return dataLabel;
785     }
786
787      // Floating-point operations
788
789     static bool supportsFloatingPoint() { return true; }
790     static bool supportsFloatingPointTruncate() { return true; }
791     static bool supportsFloatingPointSqrt() { return true; }
792     static bool supportsFloatingPointAbs() { return false; }
793
794     void loadDouble(ImplicitAddress address, FPRegisterID dest)
795     {
796         RegisterID scr = claimScratch();
797
798         m_assembler.loadConstant(address.offset, scr);
799         if (address.base == SH4Registers::r0) {
800             m_assembler.fmovsReadr0r(scr, (FPRegisterID)(dest + 1));
801             m_assembler.addlImm8r(4, scr);
802             m_assembler.fmovsReadr0r(scr, dest);
803             releaseScratch(scr);
804             return;
805         }
806
807         m_assembler.addlRegReg(address.base, scr);
808         m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
809         m_assembler.fmovsReadrm(scr, dest);
810         releaseScratch(scr);
811     }
812
813     void loadDouble(const void* address, FPRegisterID dest)
814     {
815         RegisterID scr = claimScratch();
816         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
817         m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
818         m_assembler.fmovsReadrm(scr, dest);
819         releaseScratch(scr);
820     }
821
822     void storeDouble(FPRegisterID src, ImplicitAddress address)
823     {
824         RegisterID scr = claimScratch();
825         m_assembler.loadConstant(address.offset, scr);
826         m_assembler.addlRegReg(address.base, scr);
827         m_assembler.fmovsWriterm((FPRegisterID)(src + 1), scr);
828         m_assembler.addlImm8r(4, scr);
829         m_assembler.fmovsWriterm(src, scr);
830         releaseScratch(scr);
831     }
832
833     void addDouble(FPRegisterID src, FPRegisterID dest)
834     {
835         m_assembler.daddRegReg(src, dest);
836     }
837
838     void addDouble(Address address, FPRegisterID dest)
839     {
840         loadDouble(address, fscratch);
841         addDouble(fscratch, dest);
842     }
843
844     void subDouble(FPRegisterID src, FPRegisterID dest)
845     {
846         m_assembler.dsubRegReg(src, dest);
847     }
848
849     void subDouble(Address address, FPRegisterID dest)
850     {
851         loadDouble(address, fscratch);
852         subDouble(fscratch, dest);
853     }
854
855     void mulDouble(FPRegisterID src, FPRegisterID dest)
856     {
857         m_assembler.dmulRegReg(src, dest);
858     }
859
860     void mulDouble(Address address, FPRegisterID dest)
861     {
862         loadDouble(address, fscratch);
863         mulDouble(fscratch, dest);
864     }
865
866     void divDouble(FPRegisterID src, FPRegisterID dest)
867     {
868         m_assembler.ddivRegReg(src, dest);
869     }
870
871     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
872     {
873         m_assembler.ldsrmfpul(src);
874         m_assembler.floatfpulDreg(dest);
875     }
876
877     void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
878     {
879         RegisterID scr = claimScratch();
880         m_assembler.loadConstant(reinterpret_cast<uint32_t>(src.m_ptr), scr);
881         convertInt32ToDouble(scr, dest);
882         releaseScratch(scr);
883     }
884
885     void convertInt32ToDouble(Address src, FPRegisterID dest)
886     {
887         RegisterID scr = claimScratch();
888         load32(src, scr);
889         convertInt32ToDouble(scr, dest);
890         releaseScratch(scr);
891     }
892
893     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
894     {
895         RegisterID scr = claimScratch();
896
897         move(address.index, scr);
898         lshift32(TrustedImm32(address.scale), scr);
899         add32(address.base, scr);
900
901         if (address.offset)
902             add32(TrustedImm32(address.offset), scr);
903
904         RegisterID scr1 = claimScratch();
905         load16(scr, scr1);
906         add32(TrustedImm32(2), scr);
907         load16(scr, dest);
908         move(TrustedImm32(16), scr);
909         m_assembler.shllRegReg(dest, scr);
910         or32(scr1, dest);
911
912         releaseScratch(scr);
913         releaseScratch(scr1);
914     }
915
916     Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
917     {
918         RegisterID scr = scratchReg3;
919         load32WithUnalignedHalfWords(left, scr);
920         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
921             m_assembler.testlRegReg(scr, scr);
922         else
923             compare32(right.m_value, scr, cond);
924
925         if (cond == NotEqual)
926             return branchFalse();
927         return branchTrue();
928     }
929
930     Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
931     {
932         m_assembler.movImm8(0, scratchReg3);
933         convertInt32ToDouble(scratchReg3, scratch);
934         return branchDouble(DoubleNotEqual, reg, scratch);
935     }
936
937     Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
938     {
939         m_assembler.movImm8(0, scratchReg3);
940         convertInt32ToDouble(scratchReg3, scratch);
941         return branchDouble(DoubleEqualOrUnordered, reg, scratch);
942     }
943
944     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
945     {
946         if (cond == DoubleEqual) {
947             m_assembler.dcmppeq(right, left);
948             return branchTrue();
949         }
950
951         if (cond == DoubleNotEqual) {
952             RegisterID scr = claimScratch();
953             m_assembler.loadConstant(0x7fbfffff, scratchReg3);
954             m_assembler.dcnvds(right);
955             m_assembler.stsfpulReg(scr);
956             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
957             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
958             m_assembler.branch(BT_OPCODE, 8);
959             m_assembler.dcnvds(left);
960             m_assembler.stsfpulReg(scr);
961             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
962             m_assembler.branch(BT_OPCODE, 4);
963             m_assembler.dcmppeq(right, left);
964             releaseScratch(scr);
965             return branchFalse();
966         }
967
968         if (cond == DoubleGreaterThan) {
969             m_assembler.dcmppgt(right, left);
970             return branchTrue();
971         }
972
973         if (cond == DoubleGreaterThanOrEqual) {
974             m_assembler.dcmppgt(left, right);
975             return branchFalse();
976         }
977
978         if (cond == DoubleLessThan) {
979             m_assembler.dcmppgt(left, right);
980             return branchTrue();
981         }
982
983         if (cond == DoubleLessThanOrEqual) {
984             m_assembler.dcmppgt(right, left);
985             return branchFalse();
986         }
987
988         if (cond == DoubleEqualOrUnordered) {
989             RegisterID scr = claimScratch();
990             m_assembler.loadConstant(0x7fbfffff, scratchReg3);
991             m_assembler.dcnvds(right);
992             m_assembler.stsfpulReg(scr);
993             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
994             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
995             m_assembler.branch(BT_OPCODE, 5);
996             m_assembler.dcnvds(left);
997             m_assembler.stsfpulReg(scr);
998             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
999             m_assembler.branch(BT_OPCODE, 1);
1000             m_assembler.dcmppeq(left, right);
1001             releaseScratch(scr);
1002             return branchTrue();
1003         }
1004
1005         if (cond == DoubleGreaterThanOrUnordered) {
1006             RegisterID scr = claimScratch();
1007             m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1008             m_assembler.dcnvds(right);
1009             m_assembler.stsfpulReg(scr);
1010             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1011             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1012             m_assembler.branch(BT_OPCODE, 5);
1013             m_assembler.dcnvds(left);
1014             m_assembler.stsfpulReg(scr);
1015             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1016             m_assembler.branch(BT_OPCODE, 1);
1017             m_assembler.dcmppgt(right, left);
1018             releaseScratch(scr);
1019             return branchTrue();
1020         }
1021
1022         if (cond == DoubleGreaterThanOrEqualOrUnordered) {
1023             RegisterID scr = claimScratch();
1024             m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1025             m_assembler.dcnvds(right);
1026             m_assembler.stsfpulReg(scr);
1027             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1028             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1029             m_assembler.branch(BT_OPCODE, 5);
1030             m_assembler.dcnvds(left);
1031             m_assembler.stsfpulReg(scr);
1032             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1033             m_assembler.branch(BT_OPCODE, 1);
1034             m_assembler.dcmppgt(left, right);
1035             releaseScratch(scr);
1036             return branchFalse();
1037         }
1038
1039         if (cond == DoubleLessThanOrUnordered) {
1040             RegisterID scr = claimScratch();
1041             m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1042             m_assembler.dcnvds(right);
1043             m_assembler.stsfpulReg(scr);
1044             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1045             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1046             m_assembler.branch(BT_OPCODE, 5);
1047             m_assembler.dcnvds(left);
1048             m_assembler.stsfpulReg(scr);
1049             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1050             m_assembler.branch(BT_OPCODE, 1);
1051             m_assembler.dcmppgt(left, right);
1052             releaseScratch(scr);
1053             return branchTrue();
1054         }
1055
1056         if (cond == DoubleLessThanOrEqualOrUnordered) {
1057             RegisterID scr = claimScratch();
1058             m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1059             m_assembler.dcnvds(right);
1060             m_assembler.stsfpulReg(scr);
1061             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1062             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1063             m_assembler.branch(BT_OPCODE, 5);
1064             m_assembler.dcnvds(left);
1065             m_assembler.stsfpulReg(scr);
1066             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1067             m_assembler.branch(BT_OPCODE, 1);
1068             m_assembler.dcmppgt(right, left);
1069             releaseScratch(scr);
1070             return branchFalse();
1071         }
1072
1073         ASSERT(cond == DoubleNotEqualOrUnordered);
1074         RegisterID scr = claimScratch();
1075         m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1076         m_assembler.dcnvds(right);
1077         m_assembler.stsfpulReg(scr);
1078         m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1079         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1080         m_assembler.branch(BT_OPCODE, 5);
1081         m_assembler.dcnvds(left);
1082         m_assembler.stsfpulReg(scr);
1083         m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1084         m_assembler.branch(BT_OPCODE, 1);
1085         m_assembler.dcmppeq(right, left);
1086         releaseScratch(scr);
1087         return branchFalse();
1088     }
1089
1090     Jump branchTrue()
1091     {
1092         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
1093         Jump m_jump = Jump(m_assembler.je());
1094         m_assembler.loadConstantUnReusable(0x0, scratchReg3);
1095         m_assembler.nop();
1096         m_assembler.nop();
1097         return m_jump;
1098     }
1099
1100     Jump branchFalse()
1101     {
1102         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
1103         Jump m_jump = Jump(m_assembler.jne());
1104         m_assembler.loadConstantUnReusable(0x0, scratchReg3);
1105         m_assembler.nop();
1106         m_assembler.nop();
1107         return m_jump;
1108     }
1109
1110     Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1111     {
1112         RegisterID scr = claimScratch();
1113         move(left.index, scr);
1114         lshift32(TrustedImm32(left.scale), scr);
1115         add32(left.base, scr);
1116         load32(scr, left.offset, scr);
1117         compare32(right.m_value, scr, cond);
1118         releaseScratch(scr);
1119
1120         if (cond == NotEqual)
1121             return branchFalse();
1122         return branchTrue();
1123     }
1124
1125     void sqrtDouble(FPRegisterID src, FPRegisterID dest)
1126     {
1127         if (dest != src)
1128             m_assembler.dmovRegReg(src, dest);
1129         m_assembler.dsqrt(dest);
1130     }
1131     
1132     void absDouble(FPRegisterID, FPRegisterID)
1133     {
1134         ASSERT_NOT_REACHED();
1135     }
1136
1137     Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1138     {
1139         RegisterID addressTempRegister = claimScratch();
1140         load8(address, addressTempRegister);
1141         Jump jmp = branchTest32(cond, addressTempRegister, mask);
1142         releaseScratch(addressTempRegister);
1143         return jmp;
1144     }
1145
1146     void signExtend32ToPtr(RegisterID src, RegisterID dest)
1147     {
1148         if (src != dest)
1149             move(src, dest);
1150     }
1151
1152     Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
1153     {
1154         RegisterID addressTempRegister = claimScratch();
1155         load8(left, addressTempRegister);
1156         Jump jmp = branch32(cond, addressTempRegister, right);
1157         releaseScratch(addressTempRegister);
1158         return jmp;
1159     }
1160
1161     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
1162     {
1163         m_assembler.ftrcdrmfpul(src);
1164         m_assembler.stsfpulReg(dest);
1165         m_assembler.loadConstant(0x7fffffff, scratchReg3);
1166         m_assembler.cmplRegReg(dest, scratchReg3, SH4Condition(Equal));
1167         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 14, sizeof(uint32_t));
1168         m_assembler.branch(BT_OPCODE, 2);
1169         m_assembler.addlImm8r(1, scratchReg3);
1170         m_assembler.cmplRegReg(dest, scratchReg3, SH4Condition(Equal));
1171         return branchTrue();
1172     }
1173
1174     // Stack manipulation operations
1175
1176     void pop(RegisterID dest)
1177     {
1178         m_assembler.popReg(dest);
1179     }
1180
1181     void push(RegisterID src)
1182     {
1183         m_assembler.pushReg(src);
1184     }
1185
1186     void push(Address address)
1187     {
1188         if (!address.offset) {
1189             push(address.base);
1190             return;
1191         }
1192
1193         if ((address.offset < 0) || (address.offset >= 64)) {
1194             RegisterID scr = claimScratch();
1195             m_assembler.loadConstant(address.offset, scr);
1196             m_assembler.addlRegReg(address.base, scr);
1197             m_assembler.movlMemReg(scr, SH4Registers::sp);
1198             m_assembler.addlImm8r(-4, SH4Registers::sp);
1199             releaseScratch(scr);
1200             return;
1201         }
1202
1203         m_assembler.movlMemReg(address.offset >> 2, address.base, SH4Registers::sp);
1204         m_assembler.addlImm8r(-4, SH4Registers::sp);
1205     }
1206
1207     void push(TrustedImm32 imm)
1208     {
1209         RegisterID scr = claimScratch();
1210         m_assembler.loadConstant(imm.m_value, scr);
1211         push(scr);
1212         releaseScratch(scr);
1213     }
1214
1215     // Register move operations
1216
1217     void move(TrustedImm32 imm, RegisterID dest)
1218     {
1219         m_assembler.loadConstant(imm.m_value, dest);
1220     }
1221
1222     DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
1223     {
1224         m_assembler.ensureSpace(m_assembler.maxInstructionSize, sizeof(uint32_t));
1225         DataLabelPtr dataLabel(this);
1226         m_assembler.loadConstantUnReusable(reinterpret_cast<uint32_t>(initialValue.m_value), dest);
1227         return dataLabel;
1228     }
1229
1230     void move(RegisterID src, RegisterID dest)
1231     {
1232         m_assembler.movlRegReg(src, dest);
1233     }
1234
1235     void move(TrustedImmPtr imm, RegisterID dest)
1236     {
1237         m_assembler.loadConstant(imm.asIntptr(), dest);
1238     }
1239
1240     void extuw(RegisterID src, RegisterID dst)
1241     {
1242         m_assembler.extuw(src, dst);
1243     }
1244
1245     void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
1246     {
1247         m_assembler.cmplRegReg(right, left, SH4Condition(cond));
1248         if (cond != NotEqual) {
1249             m_assembler.movt(dest);
1250             return;
1251         }
1252
1253         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
1254         m_assembler.movImm8(0, dest);
1255         m_assembler.branch(BT_OPCODE, 0);
1256         m_assembler.movImm8(1, dest);
1257     }
1258
1259     void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
1260     {
1261         if (left != dest) {
1262             move(right, dest);
1263             compare32(cond, left, dest, dest);
1264             return;
1265         }
1266
1267         RegisterID scr = claimScratch();
1268         move(right, scr);
1269         compare32(cond, left, scr, dest);
1270         releaseScratch(scr);
1271     }
1272
1273     void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
1274     {
1275         ASSERT((cond == Zero) || (cond == NonZero));
1276
1277         load8(address, dest);
1278         if (mask.m_value == -1)
1279             compare32(0, dest, static_cast<RelationalCondition>(cond));
1280         else
1281             testlImm(mask.m_value, dest);
1282         if (cond != NonZero) {
1283             m_assembler.movt(dest);
1284             return;
1285         }
1286
1287         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
1288         m_assembler.movImm8(0, dest);
1289         m_assembler.branch(BT_OPCODE, 0);
1290         m_assembler.movImm8(1, dest);
1291     }
1292
1293     void loadPtrLinkReg(ImplicitAddress address)
1294     {
1295         RegisterID scr = claimScratch();
1296         load32(address, scr);
1297         m_assembler.ldspr(scr);
1298         releaseScratch(scr);
1299     }
1300
1301     Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
1302     {
1303         m_assembler.cmplRegReg(right, left, SH4Condition(cond));
1304         /* BT label => BF off
1305            nop         LDR reg
1306            nop         braf @reg
1307            nop         nop
1308          */
1309         if (cond == NotEqual)
1310             return branchFalse();
1311         return branchTrue();
1312     }
1313
1314     Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
1315     {
1316         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1317             m_assembler.testlRegReg(left, left);
1318         else
1319             compare32(right.m_value, left, cond);
1320
1321         if (cond == NotEqual)
1322             return branchFalse();
1323         return branchTrue();
1324     }
1325
1326     Jump branch32(RelationalCondition cond, RegisterID left, Address right)
1327     {
1328         compare32(right.offset, right.base, left, cond);
1329         if (cond == NotEqual)
1330             return branchFalse();
1331         return branchTrue();
1332     }
1333
1334     Jump branch32(RelationalCondition cond, Address left, RegisterID right)
1335     {
1336         compare32(right, left.offset, left.base, cond);
1337         if (cond == NotEqual)
1338             return branchFalse();
1339         return branchTrue();
1340     }
1341
1342     Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
1343     {
1344         compare32(right.m_value, left.offset, left.base, cond);
1345         if (cond == NotEqual)
1346             return branchFalse();
1347         return branchTrue();
1348     }
1349
1350     Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
1351     {
1352         RegisterID scr = claimScratch();
1353
1354         move(TrustedImm32(reinterpret_cast<uint32_t>(left.m_ptr)), scr);
1355         m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
1356         releaseScratch(scr);
1357
1358         if (cond == NotEqual)
1359             return branchFalse();
1360         return branchTrue();
1361     }
1362
1363     Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
1364     {
1365         RegisterID addressTempRegister = claimScratch();
1366
1367         m_assembler.loadConstant(reinterpret_cast<uint32_t>(left.m_ptr), addressTempRegister);
1368         m_assembler.movlMemReg(addressTempRegister, addressTempRegister);
1369         compare32(right.m_value, addressTempRegister, cond);
1370         releaseScratch(addressTempRegister);
1371
1372         if (cond == NotEqual)
1373             return branchFalse();
1374         return branchTrue();
1375     }
1376
1377     Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1378     {
1379         ASSERT(!(right.m_value & 0xFFFFFF00));
1380         RegisterID scr = claimScratch();
1381
1382         move(left.index, scr);
1383         lshift32(TrustedImm32(left.scale), scr);
1384
1385         if (left.offset)
1386             add32(TrustedImm32(left.offset), scr);
1387         add32(left.base, scr);
1388         load8(scr, scr);
1389         m_assembler.extub(scr, scr);
1390         RegisterID scr1 = claimScratch();
1391         m_assembler.loadConstant(right.m_value, scr1);
1392         releaseScratch(scr);
1393         releaseScratch(scr1);
1394
1395         return branch32(cond, scr, scr1);
1396     }
1397
1398     Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
1399     {
1400         ASSERT((cond == Zero) || (cond == NonZero));
1401
1402         m_assembler.testlRegReg(reg, mask);
1403
1404         if (cond == NotEqual)
1405             return branchFalse();
1406         return branchTrue();
1407     }
1408
1409     Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
1410     {
1411         ASSERT((cond == Zero) || (cond == NonZero));
1412
1413         if (mask.m_value == -1)
1414             m_assembler.testlRegReg(reg, reg);
1415         else
1416             testlImm(mask.m_value, reg);
1417
1418         if (cond == NotEqual)
1419             return branchFalse();
1420         return branchTrue();
1421     }
1422
1423     Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1424     {
1425         ASSERT((cond == Zero) || (cond == NonZero));
1426
1427         if (mask.m_value == -1)
1428             compare32(0, address.offset, address.base, static_cast<RelationalCondition>(cond));
1429         else
1430             testImm(mask.m_value, address.offset, address.base);
1431
1432         if (cond == NotEqual)
1433             return branchFalse();
1434         return branchTrue();
1435     }
1436
1437     Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
1438     {
1439         RegisterID scr = claimScratch();
1440
1441         move(address.index, scr);
1442         lshift32(TrustedImm32(address.scale), scr);
1443         add32(address.base, scr);
1444         load32(scr, address.offset, scr);
1445
1446         if (mask.m_value == -1)
1447             m_assembler.testlRegReg(scr, scr);
1448         else
1449             testlImm(mask.m_value, scr);
1450
1451         releaseScratch(scr);
1452
1453         if (cond == NotEqual)
1454             return branchFalse();
1455         return branchTrue();
1456     }
1457
1458     Jump jump()
1459     {
1460         return Jump(m_assembler.jmp());
1461     }
1462
1463     void jump(RegisterID target)
1464     {
1465         m_assembler.jmpReg(target);
1466     }
1467
1468     void jump(Address address)
1469     {
1470         RegisterID scr = claimScratch();
1471
1472         if ((address.offset < 0) || (address.offset >= 64)) {
1473             m_assembler.loadConstant(address.offset, scr);
1474             m_assembler.addlRegReg(address.base, scr);
1475             m_assembler.movlMemReg(scr, scr);
1476         } else if (address.offset)
1477             m_assembler.movlMemReg(address.offset >> 2, address.base, scr);
1478         else
1479             m_assembler.movlMemReg(address.base, scr);
1480         m_assembler.jmpReg(scr);
1481
1482         releaseScratch(scr);
1483     }
1484
1485     // Arithmetic control flow operations
1486
1487     Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
1488     {
1489         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1490
1491         if (cond == Overflow) {
1492             m_assembler.addvlRegReg(src, dest);
1493             return branchTrue();
1494         }
1495
1496         if (cond == Signed) {
1497             m_assembler.addlRegReg(src, dest);
1498             // Check if dest is negative
1499             m_assembler.cmppz(dest);
1500             return branchFalse();
1501         }
1502
1503         m_assembler.addlRegReg(src, dest);
1504         compare32(0, dest, Equal);
1505
1506         if (cond == NotEqual)
1507             return branchFalse();
1508         return branchTrue();
1509     }
1510
1511     Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
1512     {
1513         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1514
1515         move(imm, scratchReg3);
1516         return branchAdd32(cond, scratchReg3, dest);
1517     }
1518
1519     Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
1520     {
1521         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1522
1523         if (cond == Overflow) {
1524             RegisterID scr1 = claimScratch();
1525             RegisterID scr = claimScratch();
1526             m_assembler.dmullRegReg(src, dest);
1527             m_assembler.stsmacl(dest);
1528             m_assembler.movImm8(-31, scr);
1529             m_assembler.movlRegReg(dest, scr1);
1530             m_assembler.shaRegReg(scr1, scr);
1531             m_assembler.stsmach(scr);
1532             m_assembler.cmplRegReg(scr, scr1, SH4Condition(Equal));
1533             releaseScratch(scr1);
1534             releaseScratch(scr);
1535             return branchFalse();
1536         }
1537
1538         m_assembler.imullRegReg(src, dest);
1539         m_assembler.stsmacl(dest);
1540         if (cond == Signed) {
1541             // Check if dest is negative
1542             m_assembler.cmppz(dest);
1543             return branchFalse();
1544         }
1545
1546         compare32(0, dest, static_cast<RelationalCondition>(cond));
1547
1548         if (cond == NotEqual)
1549             return branchFalse();
1550         return branchTrue();
1551     }
1552
1553     Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
1554     {
1555         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1556
1557         move(imm, scratchReg3);
1558         if (src != dest)
1559             move(src, dest);
1560
1561         return branchMul32(cond, scratchReg3, dest);
1562     }
1563
1564     Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
1565     {
1566         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1567
1568         if (cond == Overflow) {
1569             m_assembler.subvlRegReg(src, dest);
1570             return branchTrue();
1571         }
1572
1573         if (cond == Signed) {
1574             // Check if dest is negative
1575             m_assembler.sublRegReg(src, dest);
1576             compare32(0, dest, LessThan);
1577             return branchTrue();
1578         }
1579
1580         sub32(src, dest);
1581         compare32(0, dest, static_cast<RelationalCondition>(cond));
1582
1583         if (cond == NotEqual)
1584             return branchFalse();
1585         return branchTrue();
1586     }
1587
1588     Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
1589     {
1590         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1591
1592         move(imm, scratchReg3);
1593         return branchSub32(cond, scratchReg3, dest);
1594     }
1595
1596     Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
1597     {
1598         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
1599
1600         if (cond == Signed) {
1601             or32(src, dest);
1602             compare32(0, dest, static_cast<RelationalCondition>(LessThan));
1603             return branchTrue();
1604         }
1605
1606         or32(src, dest);
1607         compare32(0, dest, static_cast<RelationalCondition>(cond));
1608
1609         if (cond == NotEqual)
1610             return branchFalse();
1611         return branchTrue();
1612     }
1613
1614     void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
1615     {
1616         m_assembler.ftrcdrmfpul(src);
1617         m_assembler.stsfpulReg(dest);
1618         convertInt32ToDouble(dest, fscratch);
1619         failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fscratch, src));
1620
1621         if (dest == SH4Registers::r0)
1622             m_assembler.cmpEqImmR0(0, dest);
1623         else {
1624             m_assembler.movImm8(0, scratchReg3);
1625             m_assembler.cmplRegReg(scratchReg3, dest, SH4Condition(Equal));
1626         }
1627         failureCases.append(branchTrue());
1628     }
1629
1630     void neg32(RegisterID dst)
1631     {
1632         m_assembler.neg(dst, dst);
1633     }
1634
1635     void not32(RegisterID dst)
1636     {
1637         m_assembler.notlReg(dst, dst);
1638     }
1639
1640     void urshift32(RegisterID shiftamount, RegisterID dest)
1641     {
1642         compare32(32, shiftamount, Equal);
1643         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
1644         m_assembler.branch(BT_OPCODE, 1);
1645         m_assembler.neg(shiftamount, shiftamount);
1646         m_assembler.shllRegReg(dest, shiftamount);
1647     }
1648
1649     void urshift32(TrustedImm32 imm, RegisterID dest)
1650     {
1651         RegisterID scr = claimScratch();
1652         m_assembler.loadConstant(-(imm.m_value), scr);
1653         m_assembler.shaRegReg(dest, scr);
1654         releaseScratch(scr);
1655     }
1656
1657     Call call()
1658     {
1659         return Call(m_assembler.call(), Call::Linkable);
1660     }
1661
1662     Call nearCall()
1663     {
1664         return Call(m_assembler.call(), Call::LinkableNear);
1665     }
1666
1667     Call call(RegisterID target)
1668     {
1669         return Call(m_assembler.call(target), Call::None);
1670     }
1671
1672     void call(Address address, RegisterID target)
1673     {
1674         load32(address.base, address.offset, target);
1675         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 2);
1676         m_assembler.branch(JSR_OPCODE, target);
1677         m_assembler.nop();
1678     }
1679
1680     void breakpoint()
1681     {
1682         m_assembler.bkpt();
1683         m_assembler.nop();
1684     }
1685
1686     Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
1687     {
1688         RegisterID dataTempRegister = claimScratch();
1689
1690         dataLabel = moveWithPatch(initialRightValue, dataTempRegister);
1691         m_assembler.cmplRegReg(dataTempRegister, left, SH4Condition(cond));
1692         releaseScratch(dataTempRegister);
1693
1694         if (cond == NotEqual)
1695             return branchFalse();
1696         return branchTrue();
1697     }
1698
1699     Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
1700     {
1701         RegisterID scr = claimScratch();
1702
1703         m_assembler.loadConstant(left.offset, scr);
1704         m_assembler.addlRegReg(left.base, scr);
1705         m_assembler.movlMemReg(scr, scr);
1706         RegisterID scr1 = claimScratch();
1707         dataLabel = moveWithPatch(initialRightValue, scr1);
1708         m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
1709         releaseScratch(scr);
1710         releaseScratch(scr1);
1711
1712         if (cond == NotEqual)
1713             return branchFalse();
1714         return branchTrue();
1715     }
1716
1717     void ret()
1718     {
1719         m_assembler.ret();
1720         m_assembler.nop();
1721     }
1722
1723     DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
1724     {
1725         RegisterID scr = claimScratch();
1726         DataLabelPtr label = moveWithPatch(initialValue, scr);
1727         store32(scr, address);
1728         releaseScratch(scr);
1729         return label;
1730     }
1731
1732     DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(TrustedImmPtr(0), address); }
1733
1734     int sizeOfConstantPool()
1735     {
1736         return m_assembler.sizeOfConstantPool();
1737     }
1738
1739     Call tailRecursiveCall()
1740     {
1741         RegisterID scr = claimScratch();
1742
1743         m_assembler.loadConstantUnReusable(0x0, scr, true);
1744         Jump m_jump = Jump(m_assembler.jmp(scr));
1745         releaseScratch(scr);
1746
1747         return Call::fromTailJump(m_jump);
1748     }
1749
1750     Call makeTailRecursiveCall(Jump oldJump)
1751     {
1752         oldJump.link(this);
1753         return tailRecursiveCall();
1754     }
1755
1756     void nop()
1757     {
1758         m_assembler.nop();
1759     }
1760
1761 protected:
1762     SH4Assembler::Condition SH4Condition(RelationalCondition cond)
1763     {
1764         return static_cast<SH4Assembler::Condition>(cond);
1765     }
1766
1767     SH4Assembler::Condition SH4Condition(ResultCondition cond)
1768     {
1769         return static_cast<SH4Assembler::Condition>(cond);
1770     }
1771 private:
1772     friend class LinkBuffer;
1773     friend class RepatchBuffer;
1774
1775     static void linkCall(void*, Call, FunctionPtr);
1776     static void repatchCall(CodeLocationCall, CodeLocationLabel);
1777     static void repatchCall(CodeLocationCall, FunctionPtr);
1778 };
1779
1780 } // namespace JSC
1781
1782 #endif // ENABLE(ASSEMBLER)
1783
1784 #endif // MacroAssemblerSH4_h