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