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