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