]> git.saurik.com Git - apple/javascriptcore.git/blob - assembler/MacroAssemblerSH4.h
8bed14caa4035709f603fbfc386da31223d9798c
[apple/javascriptcore.git] / assembler / MacroAssemblerSH4.h
1 /*
2 * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved.
3 * Copyright (C) 2008 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #ifndef MacroAssemblerSH4_h
28 #define MacroAssemblerSH4_h
29
30 #if ENABLE(ASSEMBLER) && CPU(SH4)
31
32 #include "AbstractMacroAssembler.h"
33 #include "SH4Assembler.h"
34 #include <wtf/Assertions.h>
35
36 namespace JSC {
37
38 class MacroAssemblerSH4 : public AbstractMacroAssembler<SH4Assembler> {
39 public:
40 typedef SH4Assembler::FPRegisterID FPRegisterID;
41
42 static const Scale ScalePtr = TimesFour;
43 static const FPRegisterID fscratch = SH4Registers::fr10;
44 static const RegisterID stackPointerRegister = SH4Registers::sp;
45 static const RegisterID linkRegister = SH4Registers::pr;
46 static const RegisterID scratchReg3 = SH4Registers::r13;
47
48 static const int MaximumCompactPtrAlignedAddressOffset = 0x7FFFFFFF;
49
50 enum RelationalCondition {
51 Equal = SH4Assembler::EQ,
52 NotEqual = SH4Assembler::NE,
53 Above = SH4Assembler::HI,
54 AboveOrEqual = SH4Assembler::HS,
55 Below = SH4Assembler::LI,
56 BelowOrEqual = SH4Assembler::LS,
57 GreaterThan = SH4Assembler::GT,
58 GreaterThanOrEqual = SH4Assembler::GE,
59 LessThan = SH4Assembler::LT,
60 LessThanOrEqual = SH4Assembler::LE
61 };
62
63 enum ResultCondition {
64 Overflow = SH4Assembler::OF,
65 Signed = SH4Assembler::SI,
66 Zero = SH4Assembler::EQ,
67 NonZero = SH4Assembler::NE
68 };
69
70 enum DoubleCondition {
71 // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
72 DoubleEqual = SH4Assembler::EQ,
73 DoubleNotEqual = SH4Assembler::NE,
74 DoubleGreaterThan = SH4Assembler::GT,
75 DoubleGreaterThanOrEqual = SH4Assembler::GE,
76 DoubleLessThan = SH4Assembler::LT,
77 DoubleLessThanOrEqual = SH4Assembler::LE,
78 // If either operand is NaN, these conditions always evaluate to true.
79 DoubleEqualOrUnordered = SH4Assembler::EQU,
80 DoubleNotEqualOrUnordered = SH4Assembler::NEU,
81 DoubleGreaterThanOrUnordered = SH4Assembler::GTU,
82 DoubleGreaterThanOrEqualOrUnordered = SH4Assembler::GEU,
83 DoubleLessThanOrUnordered = SH4Assembler::LTU,
84 DoubleLessThanOrEqualOrUnordered = SH4Assembler::LEU,
85 };
86
87 RegisterID claimScratch()
88 {
89 return m_assembler.claimScratch();
90 }
91
92 void releaseScratch(RegisterID reg)
93 {
94 m_assembler.releaseScratch(reg);
95 }
96
97 // Integer arithmetic operations
98
99 void add32(RegisterID src, RegisterID dest)
100 {
101 m_assembler.addlRegReg(src, dest);
102 }
103
104 void add32(TrustedImm32 imm, RegisterID dest)
105 {
106 if (m_assembler.isImmediate(imm.m_value)) {
107 m_assembler.addlImm8r(imm.m_value, dest);
108 return;
109 }
110
111 RegisterID scr = claimScratch();
112 m_assembler.loadConstant(imm.m_value, scr);
113 m_assembler.addlRegReg(scr, dest);
114 releaseScratch(scr);
115 }
116
117 void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
118 {
119 if (src != dest)
120 m_assembler.movlRegReg(src, dest);
121 add32(imm, dest);
122 }
123
124 void add32(TrustedImm32 imm, Address address)
125 {
126 RegisterID scr = claimScratch();
127 load32(address, scr);
128 add32(imm, scr);
129 store32(scr, address);
130 releaseScratch(scr);
131 }
132
133 void add32(Address src, RegisterID dest)
134 {
135 RegisterID scr = claimScratch();
136 load32(src, scr);
137 m_assembler.addlRegReg(scr, dest);
138 releaseScratch(scr);
139 }
140
141 void and32(RegisterID src, RegisterID dest)
142 {
143 m_assembler.andlRegReg(src, dest);
144 }
145
146 void and32(TrustedImm32 imm, RegisterID dest)
147 {
148 if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) {
149 m_assembler.andlImm8r(imm.m_value, dest);
150 return;
151 }
152
153 RegisterID scr = claimScratch();
154 m_assembler.loadConstant((imm.m_value), scr);
155 m_assembler.andlRegReg(scr, dest);
156 releaseScratch(scr);
157 }
158
159 void lshift32(RegisterID shiftamount, RegisterID dest)
160 {
161 m_assembler.shllRegReg(dest, shiftamount);
162 }
163
164 void rshift32(int imm, RegisterID dest)
165 {
166 RegisterID scr = claimScratch();
167 m_assembler.loadConstant(-imm, scr);
168 m_assembler.shaRegReg(dest, scr);
169 releaseScratch(scr);
170 }
171
172 void lshift32(TrustedImm32 imm, RegisterID dest)
173 {
174 if ((imm.m_value == 1) || (imm.m_value == 2) || (imm.m_value == 8) || (imm.m_value == 16)) {
175 m_assembler.shllImm8r(imm.m_value, dest);
176 return;
177 }
178
179 RegisterID scr = claimScratch();
180 m_assembler.loadConstant(imm.m_value, scr);
181 m_assembler.shllRegReg(dest, scr);
182 releaseScratch(scr);
183 }
184
185 void mul32(RegisterID src, RegisterID dest)
186 {
187 m_assembler.imullRegReg(src, dest);
188 m_assembler.stsmacl(dest);
189 }
190
191 void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
192 {
193 RegisterID scr = claimScratch();
194 move(imm, scr);
195 if (src != dest)
196 move(src, dest);
197 mul32(scr, dest);
198 releaseScratch(scr);
199 }
200
201 void not32(RegisterID src, RegisterID dest)
202 {
203 m_assembler.notlReg(src, dest);
204 }
205
206 void or32(RegisterID src, RegisterID dest)
207 {
208 m_assembler.orlRegReg(src, dest);
209 }
210
211 void or32(TrustedImm32 imm, RegisterID dest)
212 {
213 if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) {
214 m_assembler.orlImm8r(imm.m_value, dest);
215 return;
216 }
217
218 RegisterID scr = claimScratch();
219 m_assembler.loadConstant(imm.m_value, scr);
220 m_assembler.orlRegReg(scr, dest);
221 releaseScratch(scr);
222 }
223
224 void rshift32(RegisterID shiftamount, RegisterID dest)
225 {
226 compare32(32, shiftamount, Equal);
227 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
228 m_assembler.branch(BT_OPCODE, 1);
229 m_assembler.neg(shiftamount, shiftamount);
230 m_assembler.shaRegReg(dest, shiftamount);
231 }
232
233 void rshift32(TrustedImm32 imm, RegisterID dest)
234 {
235 if (imm.m_value & 0x1f)
236 rshift32(imm.m_value & 0x1f, dest);
237 }
238
239 void sub32(RegisterID src, RegisterID dest)
240 {
241 m_assembler.sublRegReg(src, dest);
242 }
243
244 void sub32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg)
245 {
246 RegisterID result = claimScratch();
247
248 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
249 m_assembler.movlMemReg(scratchReg, result);
250
251 if (m_assembler.isImmediate(-imm.m_value))
252 m_assembler.addlImm8r(-imm.m_value, result);
253 else {
254 m_assembler.loadConstant(imm.m_value, scratchReg3);
255 m_assembler.sublRegReg(scratchReg3, result);
256 }
257
258 store32(result, scratchReg);
259 releaseScratch(result);
260 }
261
262 void sub32(TrustedImm32 imm, AbsoluteAddress address)
263 {
264 RegisterID result = claimScratch();
265 RegisterID scratchReg = claimScratch();
266
267 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
268 m_assembler.movlMemReg(scratchReg, result);
269
270 if (m_assembler.isImmediate(-imm.m_value))
271 m_assembler.addlImm8r(-imm.m_value, result);
272 else {
273 m_assembler.loadConstant(imm.m_value, scratchReg3);
274 m_assembler.sublRegReg(scratchReg3, result);
275 }
276
277 store32(result, scratchReg);
278 releaseScratch(result);
279 releaseScratch(scratchReg);
280 }
281
282 void add32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg)
283 {
284 RegisterID result = claimScratch();
285
286 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
287 m_assembler.movlMemReg(scratchReg, result);
288
289 if (m_assembler.isImmediate(imm.m_value))
290 m_assembler.addlImm8r(imm.m_value, result);
291 else {
292 m_assembler.loadConstant(imm.m_value, scratchReg3);
293 m_assembler.addlRegReg(scratchReg3, result);
294 }
295
296 store32(result, scratchReg);
297 releaseScratch(result);
298 }
299
300 void add32(TrustedImm32 imm, AbsoluteAddress address)
301 {
302 RegisterID result = claimScratch();
303 RegisterID scratchReg = claimScratch();
304
305 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
306 m_assembler.movlMemReg(scratchReg, result);
307
308 if (m_assembler.isImmediate(imm.m_value))
309 m_assembler.addlImm8r(imm.m_value, result);
310 else {
311 m_assembler.loadConstant(imm.m_value, scratchReg3);
312 m_assembler.addlRegReg(scratchReg3, result);
313 }
314
315 store32(result, scratchReg);
316 releaseScratch(result);
317 releaseScratch(scratchReg);
318 }
319
320 void sub32(TrustedImm32 imm, RegisterID dest)
321 {
322 if (m_assembler.isImmediate(-imm.m_value)) {
323 m_assembler.addlImm8r(-imm.m_value, dest);
324 return;
325 }
326
327 RegisterID scr = claimScratch();
328 m_assembler.loadConstant(imm.m_value, scr);
329 m_assembler.sublRegReg(scr, dest);
330 releaseScratch(scr);
331 }
332
333 void sub32(Address src, RegisterID dest)
334 {
335 RegisterID scr = claimScratch();
336 load32(src, scr);
337 m_assembler.sublRegReg(scr, dest);
338 releaseScratch(scr);
339 }
340
341 void xor32(RegisterID src, RegisterID dest)
342 {
343 m_assembler.xorlRegReg(src, dest);
344 }
345
346 void xor32(TrustedImm32 imm, RegisterID srcDest)
347 {
348 if ((srcDest != SH4Registers::r0) || (imm.m_value > 255) || (imm.m_value < 0)) {
349 RegisterID scr = claimScratch();
350 m_assembler.loadConstant((imm.m_value), scr);
351 m_assembler.xorlRegReg(scr, srcDest);
352 releaseScratch(scr);
353 return;
354 }
355
356 m_assembler.xorlImm8r(imm.m_value, srcDest);
357 }
358
359 void compare32(int imm, RegisterID dst, RelationalCondition cond)
360 {
361 if (((cond == Equal) || (cond == NotEqual)) && (dst == SH4Registers::r0) && m_assembler.isImmediate(imm)) {
362 m_assembler.cmpEqImmR0(imm, dst);
363 return;
364 }
365
366 RegisterID scr = claimScratch();
367 m_assembler.loadConstant(imm, scr);
368 m_assembler.cmplRegReg(scr, dst, SH4Condition(cond));
369 releaseScratch(scr);
370 }
371
372 void compare32(int offset, RegisterID base, RegisterID left, RelationalCondition cond)
373 {
374 RegisterID scr = claimScratch();
375 if (!offset) {
376 m_assembler.movlMemReg(base, scr);
377 m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
378 releaseScratch(scr);
379 return;
380 }
381
382 if ((offset < 0) || (offset >= 64)) {
383 m_assembler.loadConstant(offset, scr);
384 m_assembler.addlRegReg(base, scr);
385 m_assembler.movlMemReg(scr, scr);
386 m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
387 releaseScratch(scr);
388 return;
389 }
390
391 m_assembler.movlMemReg(offset >> 2, base, scr);
392 m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
393 releaseScratch(scr);
394 }
395
396 void testImm(int imm, int offset, RegisterID base)
397 {
398 RegisterID scr = claimScratch();
399 RegisterID scr1 = claimScratch();
400
401 if ((offset < 0) || (offset >= 64)) {
402 m_assembler.loadConstant(offset, scr);
403 m_assembler.addlRegReg(base, scr);
404 m_assembler.movlMemReg(scr, scr);
405 } else if (offset)
406 m_assembler.movlMemReg(offset >> 2, base, scr);
407 else
408 m_assembler.movlMemReg(base, scr);
409 if (m_assembler.isImmediate(imm))
410 m_assembler.movImm8(imm, scr1);
411 else
412 m_assembler.loadConstant(imm, scr1);
413
414 m_assembler.testlRegReg(scr, scr1);
415 releaseScratch(scr);
416 releaseScratch(scr1);
417 }
418
419 void testlImm(int imm, RegisterID dst)
420 {
421 if ((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0)) {
422 m_assembler.testlImm8r(imm, dst);
423 return;
424 }
425
426 RegisterID scr = claimScratch();
427 m_assembler.loadConstant(imm, scr);
428 m_assembler.testlRegReg(scr, dst);
429 releaseScratch(scr);
430 }
431
432 void compare32(RegisterID right, int offset, RegisterID base, RelationalCondition cond)
433 {
434 if (!offset) {
435 RegisterID scr = claimScratch();
436 m_assembler.movlMemReg(base, scr);
437 m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
438 releaseScratch(scr);
439 return;
440 }
441
442 if ((offset < 0) || (offset >= 64)) {
443 RegisterID scr = claimScratch();
444 m_assembler.loadConstant(offset, scr);
445 m_assembler.addlRegReg(base, scr);
446 m_assembler.movlMemReg(scr, scr);
447 m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
448 releaseScratch(scr);
449 return;
450 }
451
452 RegisterID scr = claimScratch();
453 m_assembler.movlMemReg(offset >> 2, base, scr);
454 m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
455 releaseScratch(scr);
456 }
457
458 void compare32(int imm, int offset, RegisterID base, RelationalCondition cond)
459 {
460 if (!offset) {
461 RegisterID scr = claimScratch();
462 RegisterID scr1 = claimScratch();
463 m_assembler.movlMemReg(base, scr);
464 m_assembler.loadConstant(imm, scr1);
465 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
466 releaseScratch(scr1);
467 releaseScratch(scr);
468 return;
469 }
470
471 if ((offset < 0) || (offset >= 64)) {
472 RegisterID scr = claimScratch();
473 RegisterID scr1 = claimScratch();
474 m_assembler.loadConstant(offset, scr);
475 m_assembler.addlRegReg(base, scr);
476 m_assembler.movlMemReg(scr, scr);
477 m_assembler.loadConstant(imm, scr1);
478 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
479 releaseScratch(scr1);
480 releaseScratch(scr);
481 return;
482 }
483
484 RegisterID scr = claimScratch();
485 RegisterID scr1 = claimScratch();
486 m_assembler.movlMemReg(offset >> 2, base, scr);
487 m_assembler.loadConstant(imm, scr1);
488 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
489 releaseScratch(scr1);
490 releaseScratch(scr);
491 }
492
493 // Memory access operation
494
495 void load32(ImplicitAddress address, RegisterID dest)
496 {
497 load32(address.base, address.offset, dest);
498 }
499
500 void load8(ImplicitAddress address, RegisterID dest)
501 {
502 load8(address.base, address.offset, dest);
503 }
504
505 void load32(BaseIndex address, RegisterID dest)
506 {
507 RegisterID scr = claimScratch();
508 move(address.index, scr);
509 lshift32(TrustedImm32(address.scale), scr);
510 add32(address.base, scr);
511 load32(scr, address.offset, dest);
512 releaseScratch(scr);
513 }
514
515 void load32(void* address, RegisterID dest)
516 {
517 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), dest);
518 m_assembler.movlMemReg(dest, dest);
519 }
520
521 void load32(RegisterID base, int offset, RegisterID dest)
522 {
523 if (!offset) {
524 m_assembler.movlMemReg(base, dest);
525 return;
526 }
527
528 if ((offset >= 0) && (offset < 64)) {
529 m_assembler.movlMemReg(offset >> 2, base, dest);
530 return;
531 }
532
533 if ((dest == SH4Registers::r0) && (dest != base)) {
534 m_assembler.loadConstant((offset), dest);
535 m_assembler.movlR0mr(base, dest);
536 return;
537 }
538
539 RegisterID scr;
540 if (dest == base)
541 scr = claimScratch();
542 else
543 scr = dest;
544 m_assembler.loadConstant((offset), scr);
545 m_assembler.addlRegReg(base, scr);
546 m_assembler.movlMemReg(scr, dest);
547
548 if (dest == base)
549 releaseScratch(scr);
550 }
551
552 void load8(RegisterID base, int offset, RegisterID dest)
553 {
554 if (!offset) {
555 m_assembler.movbMemReg(base, dest);
556 return;
557 }
558
559 if ((offset > 0) && (offset < 64) && (dest == SH4Registers::r0)) {
560 m_assembler.movbMemReg(offset, base, dest);
561 return;
562 }
563
564 if (base != dest) {
565 m_assembler.loadConstant((offset), dest);
566 m_assembler.addlRegReg(base, dest);
567 m_assembler.movbMemReg(dest, dest);
568 return;
569 }
570
571 RegisterID scr = claimScratch();
572 m_assembler.loadConstant((offset), scr);
573 m_assembler.addlRegReg(base, scr);
574 m_assembler.movbMemReg(scr, dest);
575 releaseScratch(scr);
576 }
577
578 void load32(RegisterID r0, RegisterID src, RegisterID dst)
579 {
580 ASSERT(r0 == SH4Registers::r0);
581 m_assembler.movlR0mr(src, dst);
582 }
583
584 void load32(RegisterID src, RegisterID dst)
585 {
586 m_assembler.movlMemReg(src, dst);
587 }
588
589 void load16(ImplicitAddress address, RegisterID dest)
590 {
591 if (!address.offset) {
592 m_assembler.movwMemReg(address.base, dest);
593 return;
594 }
595
596 if ((address.offset > 0) && (address.offset < 64) && (dest == SH4Registers::r0)) {
597 m_assembler.movwMemReg(address.offset, address.base, dest);
598 return;
599 }
600
601 if (address.base != dest) {
602 m_assembler.loadConstant((address.offset), dest);
603 m_assembler.addlRegReg(address.base, dest);
604 m_assembler.movwMemReg(dest, dest);
605 return;
606 }
607
608 RegisterID scr = claimScratch();
609 m_assembler.loadConstant((address.offset), scr);
610 m_assembler.addlRegReg(address.base, scr);
611 m_assembler.movwMemReg(scr, dest);
612 releaseScratch(scr);
613 }
614
615 void load16(RegisterID src, RegisterID dest)
616 {
617 m_assembler.movwMemReg(src, dest);
618 }
619
620 void load16(RegisterID r0, RegisterID src, RegisterID dest)
621 {
622 ASSERT(r0 == SH4Registers::r0);
623 m_assembler.movwR0mr(src, dest);
624 }
625
626 void load16(BaseIndex address, RegisterID dest)
627 {
628 RegisterID scr = claimScratch();
629
630 move(address.index, scr);
631 lshift32(TrustedImm32(address.scale), scr);
632
633 if (address.offset)
634 add32(TrustedImm32(address.offset), scr);
635 if (scr == SH4Registers::r0)
636 m_assembler.movwR0mr(address.base, scr);
637 else {
638 add32(address.base, scr);
639 load16(scr, scr);
640 }
641
642 extuw(scr, dest);
643 releaseScratch(scr);
644 }
645
646 void store32(RegisterID src, ImplicitAddress address)
647 {
648 RegisterID scr = claimScratch();
649 store32(src, address.offset, address.base, scr);
650 releaseScratch(scr);
651 }
652
653 void store32(RegisterID src, int offset, RegisterID base, RegisterID scr)
654 {
655 if (!offset) {
656 m_assembler.movlRegMem(src, base);
657 return;
658 }
659
660 if ((offset >=0) && (offset < 64)) {
661 m_assembler.movlRegMem(src, offset >> 2, base);
662 return;
663 }
664
665 m_assembler.loadConstant((offset), scr);
666 if (scr == SH4Registers::r0) {
667 m_assembler.movlRegMemr0(src, base);
668 return;
669 }
670
671 m_assembler.addlRegReg(base, scr);
672 m_assembler.movlRegMem(src, scr);
673 }
674
675 void store32(RegisterID src, RegisterID offset, RegisterID base)
676 {
677 ASSERT(offset == SH4Registers::r0);
678 m_assembler.movlRegMemr0(src, base);
679 }
680
681 void store32(RegisterID src, RegisterID dst)
682 {
683 m_assembler.movlRegMem(src, dst);
684 }
685
686 void store32(TrustedImm32 imm, ImplicitAddress address)
687 {
688 RegisterID scr = claimScratch();
689 RegisterID scr1 = claimScratch();
690 m_assembler.loadConstant((imm.m_value), scr);
691 store32(scr, address.offset, address.base, scr1);
692 releaseScratch(scr);
693 releaseScratch(scr1);
694 }
695
696 void store32(RegisterID src, BaseIndex address)
697 {
698 RegisterID scr = claimScratch();
699
700 move(address.index, scr);
701 lshift32(TrustedImm32(address.scale), scr);
702 add32(address.base, scr);
703 store32(src, Address(scr, address.offset));
704
705 releaseScratch(scr);
706 }
707
708 void store32(TrustedImm32 imm, void* address)
709 {
710 RegisterID scr = claimScratch();
711 RegisterID scr1 = claimScratch();
712 m_assembler.loadConstant((imm.m_value), scr);
713 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr1);
714 m_assembler.movlMemReg(scr, scr1);
715 releaseScratch(scr);
716 releaseScratch(scr1);
717 }
718
719 void store32(RegisterID src, void* address)
720 {
721 RegisterID scr = claimScratch();
722 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
723 m_assembler.movlMemReg(src, scr);
724 releaseScratch(scr);
725 }
726
727 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
728 {
729 RegisterID scr = claimScratch();
730 DataLabel32 label(this);
731 m_assembler.loadConstantUnReusable(address.offset, scr);
732 m_assembler.addlRegReg(address.base, scr);
733 m_assembler.movlMemReg(scr, dest);
734 releaseScratch(scr);
735 return label;
736 }
737
738 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
739 {
740 RegisterID scr = claimScratch();
741 DataLabelCompact label(this);
742 m_assembler.loadConstantUnReusable(address.offset, scr);
743 m_assembler.addlRegReg(address.base, scr);
744 m_assembler.movlMemReg(scr, dest);
745 releaseScratch(scr);
746 return label;
747 }
748
749 DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
750 {
751 RegisterID scr = claimScratch();
752 DataLabel32 label(this);
753 m_assembler.loadConstantUnReusable(address.offset, scr);
754 m_assembler.addlRegReg(address.base, scr);
755 m_assembler.movlRegMem(src, scr);
756 releaseScratch(scr);
757 return label;
758 }
759
760 // Floating-point operations
761
762 bool supportsFloatingPoint() const { return true; }
763 bool supportsFloatingPointTruncate() const { return true; }
764 bool supportsFloatingPointSqrt() const { return true; }
765
766 void loadDouble(ImplicitAddress address, FPRegisterID dest)
767 {
768 RegisterID scr = claimScratch();
769
770 m_assembler.loadConstant(address.offset, scr);
771 if (address.base == SH4Registers::r0) {
772 m_assembler.fmovsReadr0r(scr, (FPRegisterID)(dest + 1));
773 m_assembler.addlImm8r(4, scr);
774 m_assembler.fmovsReadr0r(scr, dest);
775 releaseScratch(scr);
776 return;
777 }
778
779 m_assembler.addlRegReg(address.base, scr);
780 m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
781 m_assembler.fmovsReadrm(scr, dest);
782 releaseScratch(scr);
783 }
784
785 void loadDouble(const void* address, FPRegisterID dest)
786 {
787 RegisterID scr = claimScratch();
788 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
789 m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
790 m_assembler.fmovsReadrm(scr, dest);
791 releaseScratch(scr);
792 }
793
794 void storeDouble(FPRegisterID src, ImplicitAddress address)
795 {
796 RegisterID scr = claimScratch();
797 m_assembler.loadConstant(address.offset, scr);
798 m_assembler.addlRegReg(address.base, scr);
799 m_assembler.fmovsWriterm((FPRegisterID)(src + 1), scr);
800 m_assembler.addlImm8r(4, scr);
801 m_assembler.fmovsWriterm(src, scr);
802 releaseScratch(scr);
803 }
804
805 void addDouble(FPRegisterID src, FPRegisterID dest)
806 {
807 m_assembler.daddRegReg(src, dest);
808 }
809
810 void addDouble(Address address, FPRegisterID dest)
811 {
812 loadDouble(address, fscratch);
813 addDouble(fscratch, dest);
814 }
815
816 void subDouble(FPRegisterID src, FPRegisterID dest)
817 {
818 m_assembler.dsubRegReg(src, dest);
819 }
820
821 void subDouble(Address address, FPRegisterID dest)
822 {
823 loadDouble(address, fscratch);
824 subDouble(fscratch, dest);
825 }
826
827 void mulDouble(FPRegisterID src, FPRegisterID dest)
828 {
829 m_assembler.dmulRegReg(src, dest);
830 }
831
832 void mulDouble(Address address, FPRegisterID dest)
833 {
834 loadDouble(address, fscratch);
835 mulDouble(fscratch, dest);
836 }
837
838 void divDouble(FPRegisterID src, FPRegisterID dest)
839 {
840 m_assembler.ddivRegReg(src, dest);
841 }
842
843 void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
844 {
845 m_assembler.ldsrmfpul(src);
846 m_assembler.floatfpulDreg(dest);
847 }
848
849 void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
850 {
851 RegisterID scr = claimScratch();
852 m_assembler.loadConstant(reinterpret_cast<uint32_t>(src.m_ptr), scr);
853 convertInt32ToDouble(scr, dest);
854 releaseScratch(scr);
855 }
856
857 void convertInt32ToDouble(Address src, FPRegisterID dest)
858 {
859 RegisterID scr = claimScratch();
860 load32(src, scr);
861 convertInt32ToDouble(scr, dest);
862 releaseScratch(scr);
863 }
864
865 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
866 {
867 RegisterID scr = claimScratch();
868
869 move(address.index, scr);
870 lshift32(TrustedImm32(address.scale), scr);
871 add32(address.base, scr);
872
873 if (address.offset)
874 add32(TrustedImm32(address.offset), scr);
875
876 RegisterID scr1 = claimScratch();
877 load16(scr, scr1);
878 add32(TrustedImm32(2), scr);
879 load16(scr, dest);
880 move(TrustedImm32(16), scr);
881 m_assembler.shllRegReg(dest, scr);
882 or32(scr1, dest);
883
884 releaseScratch(scr);
885 releaseScratch(scr1);
886 }
887
888 Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
889 {
890 RegisterID scr = scratchReg3;
891 load32WithUnalignedHalfWords(left, scr);
892 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
893 m_assembler.testlRegReg(scr, scr);
894 else
895 compare32(right.m_value, scr, cond);
896
897 if (cond == NotEqual)
898 return branchFalse();
899 return branchTrue();
900 }
901
902 Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
903 {
904 m_assembler.movImm8(0, scratchReg3);
905 convertInt32ToDouble(scratchReg3, scratch);
906 return branchDouble(DoubleNotEqual, reg, scratch);
907 }
908
909 Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
910 {
911 m_assembler.movImm8(0, scratchReg3);
912 convertInt32ToDouble(scratchReg3, scratch);
913 return branchDouble(DoubleEqualOrUnordered, reg, scratch);
914 }
915
916 Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
917 {
918 if (cond == DoubleEqual) {
919 m_assembler.dcmppeq(right, left);
920 return branchTrue();
921 }
922
923 if (cond == DoubleNotEqual) {
924 RegisterID scr = claimScratch();
925 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
926 m_assembler.dcnvds(right);
927 m_assembler.stsfpulReg(scr);
928 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
929 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
930 m_assembler.branch(BT_OPCODE, 8);
931 m_assembler.dcnvds(left);
932 m_assembler.stsfpulReg(scr);
933 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
934 m_assembler.branch(BT_OPCODE, 4);
935 m_assembler.dcmppeq(right, left);
936 releaseScratch(scr);
937 return branchFalse();
938 }
939
940 if (cond == DoubleGreaterThan) {
941 m_assembler.dcmppgt(right, left);
942 return branchTrue();
943 }
944
945 if (cond == DoubleGreaterThanOrEqual) {
946 m_assembler.dcmppgt(left, right);
947 return branchFalse();
948 }
949
950 if (cond == DoubleLessThan) {
951 m_assembler.dcmppgt(left, right);
952 return branchTrue();
953 }
954
955 if (cond == DoubleLessThanOrEqual) {
956 m_assembler.dcmppgt(right, left);
957 return branchFalse();
958 }
959
960 if (cond == DoubleEqualOrUnordered) {
961 RegisterID scr = claimScratch();
962 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
963 m_assembler.dcnvds(right);
964 m_assembler.stsfpulReg(scr);
965 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
966 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
967 m_assembler.branch(BT_OPCODE, 5);
968 m_assembler.dcnvds(left);
969 m_assembler.stsfpulReg(scr);
970 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
971 m_assembler.branch(BT_OPCODE, 1);
972 m_assembler.dcmppeq(left, right);
973 releaseScratch(scr);
974 return branchTrue();
975 }
976
977 if (cond == DoubleGreaterThanOrUnordered) {
978 RegisterID scr = claimScratch();
979 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
980 m_assembler.dcnvds(right);
981 m_assembler.stsfpulReg(scr);
982 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
983 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
984 m_assembler.branch(BT_OPCODE, 5);
985 m_assembler.dcnvds(left);
986 m_assembler.stsfpulReg(scr);
987 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
988 m_assembler.branch(BT_OPCODE, 1);
989 m_assembler.dcmppgt(right, left);
990 releaseScratch(scr);
991 return branchTrue();
992 }
993
994 if (cond == DoubleGreaterThanOrEqualOrUnordered) {
995 RegisterID scr = claimScratch();
996 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
997 m_assembler.dcnvds(right);
998 m_assembler.stsfpulReg(scr);
999 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1000 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1001 m_assembler.branch(BT_OPCODE, 5);
1002 m_assembler.dcnvds(left);
1003 m_assembler.stsfpulReg(scr);
1004 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1005 m_assembler.branch(BT_OPCODE, 1);
1006 m_assembler.dcmppgt(left, right);
1007 releaseScratch(scr);
1008 return branchFalse();
1009 }
1010
1011 if (cond == DoubleLessThanOrUnordered) {
1012 RegisterID scr = claimScratch();
1013 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1014 m_assembler.dcnvds(right);
1015 m_assembler.stsfpulReg(scr);
1016 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1017 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1018 m_assembler.branch(BT_OPCODE, 5);
1019 m_assembler.dcnvds(left);
1020 m_assembler.stsfpulReg(scr);
1021 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1022 m_assembler.branch(BT_OPCODE, 1);
1023 m_assembler.dcmppgt(left, right);
1024 releaseScratch(scr);
1025 return branchTrue();
1026 }
1027
1028 if (cond == DoubleLessThanOrEqualOrUnordered) {
1029 RegisterID scr = claimScratch();
1030 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1031 m_assembler.dcnvds(right);
1032 m_assembler.stsfpulReg(scr);
1033 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1034 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1035 m_assembler.branch(BT_OPCODE, 5);
1036 m_assembler.dcnvds(left);
1037 m_assembler.stsfpulReg(scr);
1038 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1039 m_assembler.branch(BT_OPCODE, 1);
1040 m_assembler.dcmppgt(right, left);
1041 releaseScratch(scr);
1042 return branchFalse();
1043 }
1044
1045 ASSERT(cond == DoubleNotEqualOrUnordered);
1046 RegisterID scr = claimScratch();
1047 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1048 m_assembler.dcnvds(right);
1049 m_assembler.stsfpulReg(scr);
1050 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1051 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1052 m_assembler.branch(BT_OPCODE, 5);
1053 m_assembler.dcnvds(left);
1054 m_assembler.stsfpulReg(scr);
1055 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1056 m_assembler.branch(BT_OPCODE, 1);
1057 m_assembler.dcmppeq(right, left);
1058 releaseScratch(scr);
1059 return branchFalse();
1060 }
1061
1062 Jump branchTrue()
1063 {
1064 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
1065 Jump m_jump = Jump(m_assembler.je());
1066 m_assembler.loadConstantUnReusable(0x0, scratchReg3);
1067 m_assembler.nop();
1068 m_assembler.nop();
1069 return m_jump;
1070 }
1071
1072 Jump branchFalse()
1073 {
1074 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
1075 Jump m_jump = Jump(m_assembler.jne());
1076 m_assembler.loadConstantUnReusable(0x0, scratchReg3);
1077 m_assembler.nop();
1078 m_assembler.nop();
1079 return m_jump;
1080 }
1081
1082 Jump branch32(RelationalCondition 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
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(ResultCondition 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
1113 void signExtend32ToPtr(RegisterID src, RegisterID dest)
1114 {
1115 if (src != dest)
1116 move(src, dest);
1117 }
1118
1119 Jump branch8(RelationalCondition 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
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, SH4Condition(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, SH4Condition(Equal));
1138 return branchTrue();
1139 }
1140
1141 // Stack manipulation operations
1142
1143 void pop(RegisterID dest)
1144 {
1145 m_assembler.popReg(dest);
1146 }
1147
1148 void push(RegisterID src)
1149 {
1150 m_assembler.pushReg(src);
1151 }
1152
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
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
1184 void move(TrustedImm32 imm, RegisterID dest)
1185 {
1186 m_assembler.loadConstant(imm.m_value, dest);
1187 }
1188
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
1196 void move(RegisterID src, RegisterID dest)
1197 {
1198 m_assembler.movlRegReg(src, dest);
1199 }
1200
1201 void move(TrustedImmPtr imm, RegisterID dest)
1202 {
1203 m_assembler.loadConstant(imm.asIntptr(), dest);
1204 }
1205
1206 void extuw(RegisterID src, RegisterID dst)
1207 {
1208 m_assembler.extuw(src, dst);
1209 }
1210
1211 void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
1212 {
1213 m_assembler.cmplRegReg(right, left, SH4Condition(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
1225 void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
1226 {
1227 if (left != dest) {
1228 move(right, dest);
1229 compare32(cond, left, dest, dest);
1230 return;
1231 }
1232
1233 RegisterID scr = claimScratch();
1234 move(right, scr);
1235 compare32(cond, left, scr, dest);
1236 releaseScratch(scr);
1237 }
1238
1239 void test8(ResultCondition 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, static_cast<RelationalCondition>(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
1259 void loadPtrLinkReg(ImplicitAddress address)
1260 {
1261 RegisterID scr = claimScratch();
1262 load32(address, scr);
1263 m_assembler.ldspr(scr);
1264 releaseScratch(scr);
1265 }
1266
1267 Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
1268 {
1269 m_assembler.cmplRegReg(right, left, SH4Condition(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
1280 Jump branch32(RelationalCondition 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
1292 Jump branch32(RelationalCondition 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
1300 Jump branch32(RelationalCondition 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
1308 Jump branch32(RelationalCondition 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
1316 Jump branch32(RelationalCondition 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, SH4Condition(cond));
1322 releaseScratch(scr);
1323
1324 if (cond == NotEqual)
1325 return branchFalse();
1326 return branchTrue();
1327 }
1328
1329 Jump branch32(RelationalCondition 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
1343 Jump branch16(RelationalCondition 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
1360 Jump branch16(RelationalCondition 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
1380 Jump branchTest32(ResultCondition 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(ResultCondition 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(ResultCondition 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, static_cast<RelationalCondition>(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(ResultCondition 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
1440 Jump jump()
1441 {
1442 return Jump(m_assembler.jmp());
1443 }
1444
1445 void jump(RegisterID target)
1446 {
1447 m_assembler.jmpReg(target);
1448 }
1449
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
1469 Jump branchAdd32(ResultCondition 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
1493 Jump branchAdd32(ResultCondition 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
1501 Jump branchMul32(ResultCondition 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, SH4Condition(Equal));
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, static_cast<RelationalCondition>(cond));
1529
1530 if (cond == NotEqual)
1531 return branchFalse();
1532 return branchTrue();
1533 }
1534
1535 Jump branchMul32(ResultCondition 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
1546 Jump branchSub32(ResultCondition 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, static_cast<RelationalCondition>(cond));
1564
1565 if (cond == NotEqual)
1566 return branchFalse();
1567 return branchTrue();
1568 }
1569
1570 Jump branchSub32(ResultCondition 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
1578 Jump branchOr32(ResultCondition 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, static_cast<RelationalCondition>(LessThan));
1585 return branchTrue();
1586 }
1587
1588 or32(src, dest);
1589 compare32(0, dest, static_cast<RelationalCondition>(cond));
1590
1591 if (cond == NotEqual)
1592 return branchFalse();
1593 return branchTrue();
1594 }
1595
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);
1605 else {
1606 m_assembler.movImm8(0, scratchReg3);
1607 m_assembler.cmplRegReg(scratchReg3, dest, SH4Condition(Equal));
1608 }
1609 failureCases.append(branchTrue());
1610 }
1611
1612 void neg32(RegisterID dst)
1613 {
1614 m_assembler.neg(dst, dst);
1615 }
1616
1617 void not32(RegisterID dst)
1618 {
1619 m_assembler.notlReg(dst, dst);
1620 }
1621
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
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
1639 Call call()
1640 {
1641 return Call(m_assembler.call(), Call::Linkable);
1642 }
1643
1644 Call nearCall()
1645 {
1646 return Call(m_assembler.call(), Call::LinkableNear);
1647 }
1648
1649 Call call(RegisterID target)
1650 {
1651 return Call(m_assembler.call(target), Call::None);
1652 }
1653
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
1662 void breakpoint()
1663 {
1664 m_assembler.bkpt();
1665 m_assembler.nop();
1666 }
1667
1668 Jump branchPtrWithPatch(RelationalCondition 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, SH4Condition(cond));
1674 releaseScratch(dataTempRegister);
1675
1676 if (cond == NotEqual)
1677 return branchFalse();
1678 return branchTrue();
1679 }
1680
1681 Jump branchPtrWithPatch(RelationalCondition 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, SH4Condition(cond));
1691 releaseScratch(scr);
1692 releaseScratch(scr1);
1693
1694 if (cond == NotEqual)
1695 return branchFalse();
1696 return branchTrue();
1697 }
1698
1699 void ret()
1700 {
1701 m_assembler.ret();
1702 m_assembler.nop();
1703 }
1704
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
1714 DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(TrustedImmPtr(0), address); }
1715
1716 int sizeOfConstantPool()
1717 {
1718 return m_assembler.sizeOfConstantPool();
1719 }
1720
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
1732 Call makeTailRecursiveCall(Jump oldJump)
1733 {
1734 oldJump.link(this);
1735 return tailRecursiveCall();
1736 }
1737
1738 void nop()
1739 {
1740 m_assembler.nop();
1741 }
1742
1743 protected:
1744 SH4Assembler::Condition SH4Condition(RelationalCondition cond)
1745 {
1746 return static_cast<SH4Assembler::Condition>(cond);
1747 }
1748
1749 SH4Assembler::Condition SH4Condition(ResultCondition cond)
1750 {
1751 return static_cast<SH4Assembler::Condition>(cond);
1752 }
1753 private:
1754 friend class LinkBuffer;
1755 friend class RepatchBuffer;
1756
1757 static void linkCall(void*, Call, FunctionPtr);
1758 static void repatchCall(CodeLocationCall, CodeLocationLabel);
1759 static void repatchCall(CodeLocationCall, FunctionPtr);
1760 };
1761
1762 } // namespace JSC
1763
1764 #endif // ENABLE(ASSEMBLER)
1765
1766 #endif // MacroAssemblerSH4_h