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