2 * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved.
3 * Copyright (C) 2008 Apple Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
27 #ifndef MacroAssemblerSH4_h
28 #define MacroAssemblerSH4_h
30 #if ENABLE(ASSEMBLER) && CPU(SH4)
32 #include "SH4Assembler.h"
33 #include "AbstractMacroAssembler.h"
34 #include <wtf/Assertions.h>
38 class MacroAssemblerSH4 : public AbstractMacroAssembler<SH4Assembler> {
40 typedef SH4Assembler::FPRegisterID FPRegisterID;
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;
48 static const int MaximumCompactPtrAlignedAddressOffset = 60;
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
63 enum ResultCondition {
64 Overflow = SH4Assembler::OF,
65 Signed = SH4Assembler::SI,
66 Zero = SH4Assembler::EQ,
67 NonZero = SH4Assembler::NE
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,
87 RegisterID claimScratch()
89 return m_assembler.claimScratch();
92 void releaseScratch(RegisterID reg)
94 m_assembler.releaseScratch(reg);
97 // Integer arithmetic operations
99 void add32(RegisterID src, RegisterID dest)
101 m_assembler.addlRegReg(src, dest);
104 void add32(TrustedImm32 imm, RegisterID dest)
106 if (m_assembler.isImmediate(imm.m_value)) {
107 m_assembler.addlImm8r(imm.m_value, dest);
111 RegisterID scr = claimScratch();
112 m_assembler.loadConstant(imm.m_value, scr);
113 m_assembler.addlRegReg(scr, dest);
117 void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
120 m_assembler.movlRegReg(src, dest);
124 void add32(TrustedImm32 imm, Address address)
126 RegisterID scr = claimScratch();
127 load32(address, scr);
129 store32(scr, address);
133 void add32(Address src, RegisterID dest)
135 RegisterID scr = claimScratch();
137 m_assembler.addlRegReg(scr, dest);
141 void and32(RegisterID src, RegisterID dest)
143 m_assembler.andlRegReg(src, dest);
146 void and32(TrustedImm32 imm, RegisterID dest)
148 if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) {
149 m_assembler.andlImm8r(imm.m_value, dest);
153 RegisterID scr = claimScratch();
154 m_assembler.loadConstant((imm.m_value), scr);
155 m_assembler.andlRegReg(scr, dest);
159 void lshift32(RegisterID shiftamount, RegisterID dest)
161 m_assembler.shllRegReg(dest, shiftamount);
164 void rshift32(int imm, RegisterID dest)
166 RegisterID scr = claimScratch();
167 m_assembler.loadConstant(-imm, scr);
168 m_assembler.shaRegReg(dest, scr);
172 void lshift32(TrustedImm32 imm, RegisterID dest)
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);
179 RegisterID scr = claimScratch();
180 m_assembler.loadConstant(imm.m_value, scr);
181 m_assembler.shllRegReg(dest, scr);
185 void mul32(RegisterID src, RegisterID dest)
187 m_assembler.imullRegReg(src, dest);
188 m_assembler.stsmacl(dest);
191 void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
193 RegisterID scr = claimScratch();
201 void not32(RegisterID src, RegisterID dest)
203 m_assembler.notlReg(src, dest);
206 void or32(RegisterID src, RegisterID dest)
208 m_assembler.orlRegReg(src, dest);
211 void or32(TrustedImm32 imm, RegisterID dest)
213 if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) {
214 m_assembler.orlImm8r(imm.m_value, dest);
218 RegisterID scr = claimScratch();
219 m_assembler.loadConstant(imm.m_value, scr);
220 m_assembler.orlRegReg(scr, dest);
224 void rshift32(RegisterID shiftamount, RegisterID dest)
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);
233 void rshift32(TrustedImm32 imm, RegisterID dest)
235 if (imm.m_value & 0x1f)
236 rshift32(imm.m_value & 0x1f, dest);
239 void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
246 void sub32(RegisterID src, RegisterID dest)
248 m_assembler.sublRegReg(src, dest);
251 void sub32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg)
253 RegisterID result = claimScratch();
255 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
256 m_assembler.movlMemReg(scratchReg, result);
258 if (m_assembler.isImmediate(-imm.m_value))
259 m_assembler.addlImm8r(-imm.m_value, result);
261 m_assembler.loadConstant(imm.m_value, scratchReg3);
262 m_assembler.sublRegReg(scratchReg3, result);
265 store32(result, scratchReg);
266 releaseScratch(result);
269 void sub32(TrustedImm32 imm, AbsoluteAddress address)
271 RegisterID result = claimScratch();
272 RegisterID scratchReg = claimScratch();
274 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
275 m_assembler.movlMemReg(scratchReg, result);
277 if (m_assembler.isImmediate(-imm.m_value))
278 m_assembler.addlImm8r(-imm.m_value, result);
280 m_assembler.loadConstant(imm.m_value, scratchReg3);
281 m_assembler.sublRegReg(scratchReg3, result);
284 store32(result, scratchReg);
285 releaseScratch(result);
286 releaseScratch(scratchReg);
289 void add32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg)
291 RegisterID result = claimScratch();
293 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
294 m_assembler.movlMemReg(scratchReg, result);
296 if (m_assembler.isImmediate(imm.m_value))
297 m_assembler.addlImm8r(imm.m_value, result);
299 m_assembler.loadConstant(imm.m_value, scratchReg3);
300 m_assembler.addlRegReg(scratchReg3, result);
303 store32(result, scratchReg);
304 releaseScratch(result);
307 void add32(TrustedImm32 imm, AbsoluteAddress address)
309 RegisterID result = claimScratch();
310 RegisterID scratchReg = claimScratch();
312 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
313 m_assembler.movlMemReg(scratchReg, result);
315 if (m_assembler.isImmediate(imm.m_value))
316 m_assembler.addlImm8r(imm.m_value, result);
318 m_assembler.loadConstant(imm.m_value, scratchReg3);
319 m_assembler.addlRegReg(scratchReg3, result);
322 store32(result, scratchReg);
323 releaseScratch(result);
324 releaseScratch(scratchReg);
327 void sub32(TrustedImm32 imm, RegisterID dest)
329 if (m_assembler.isImmediate(-imm.m_value)) {
330 m_assembler.addlImm8r(-imm.m_value, dest);
334 RegisterID scr = claimScratch();
335 m_assembler.loadConstant(imm.m_value, scr);
336 m_assembler.sublRegReg(scr, dest);
340 void sub32(Address src, RegisterID dest)
342 RegisterID scr = claimScratch();
344 m_assembler.sublRegReg(scr, dest);
348 void xor32(RegisterID src, RegisterID dest)
350 m_assembler.xorlRegReg(src, dest);
353 void xor32(TrustedImm32 imm, RegisterID srcDest)
355 if ((srcDest != SH4Registers::r0) || (imm.m_value > 255) || (imm.m_value < 0)) {
356 RegisterID scr = claimScratch();
357 m_assembler.loadConstant((imm.m_value), scr);
358 m_assembler.xorlRegReg(scr, srcDest);
363 m_assembler.xorlImm8r(imm.m_value, srcDest);
366 void compare32(int imm, RegisterID dst, RelationalCondition cond)
368 if (((cond == Equal) || (cond == NotEqual)) && (dst == SH4Registers::r0) && m_assembler.isImmediate(imm)) {
369 m_assembler.cmpEqImmR0(imm, dst);
373 RegisterID scr = claimScratch();
374 m_assembler.loadConstant(imm, scr);
375 m_assembler.cmplRegReg(scr, dst, SH4Condition(cond));
379 void compare32(int offset, RegisterID base, RegisterID left, RelationalCondition cond)
381 RegisterID scr = claimScratch();
383 m_assembler.movlMemReg(base, scr);
384 m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
389 if ((offset < 0) || (offset >= 64)) {
390 m_assembler.loadConstant(offset, scr);
391 m_assembler.addlRegReg(base, scr);
392 m_assembler.movlMemReg(scr, scr);
393 m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
398 m_assembler.movlMemReg(offset >> 2, base, scr);
399 m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
403 void testImm(int imm, int offset, RegisterID base)
405 RegisterID scr = claimScratch();
406 RegisterID scr1 = claimScratch();
408 if ((offset < 0) || (offset >= 64)) {
409 m_assembler.loadConstant(offset, scr);
410 m_assembler.addlRegReg(base, scr);
411 m_assembler.movlMemReg(scr, scr);
413 m_assembler.movlMemReg(offset >> 2, base, scr);
415 m_assembler.movlMemReg(base, scr);
416 if (m_assembler.isImmediate(imm))
417 m_assembler.movImm8(imm, scr1);
419 m_assembler.loadConstant(imm, scr1);
421 m_assembler.testlRegReg(scr, scr1);
423 releaseScratch(scr1);
426 void testlImm(int imm, RegisterID dst)
428 if ((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0)) {
429 m_assembler.testlImm8r(imm, dst);
433 RegisterID scr = claimScratch();
434 m_assembler.loadConstant(imm, scr);
435 m_assembler.testlRegReg(scr, dst);
439 void compare32(RegisterID right, int offset, RegisterID base, RelationalCondition cond)
442 RegisterID scr = claimScratch();
443 m_assembler.movlMemReg(base, scr);
444 m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
449 if ((offset < 0) || (offset >= 64)) {
450 RegisterID scr = claimScratch();
451 m_assembler.loadConstant(offset, scr);
452 m_assembler.addlRegReg(base, scr);
453 m_assembler.movlMemReg(scr, scr);
454 m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
459 RegisterID scr = claimScratch();
460 m_assembler.movlMemReg(offset >> 2, base, scr);
461 m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
465 void compare32(int imm, int offset, RegisterID base, RelationalCondition cond)
468 RegisterID scr = claimScratch();
469 RegisterID scr1 = claimScratch();
470 m_assembler.movlMemReg(base, scr);
471 m_assembler.loadConstant(imm, scr1);
472 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
473 releaseScratch(scr1);
478 if ((offset < 0) || (offset >= 64)) {
479 RegisterID scr = claimScratch();
480 RegisterID scr1 = claimScratch();
481 m_assembler.loadConstant(offset, scr);
482 m_assembler.addlRegReg(base, scr);
483 m_assembler.movlMemReg(scr, scr);
484 m_assembler.loadConstant(imm, scr1);
485 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
486 releaseScratch(scr1);
491 RegisterID scr = claimScratch();
492 RegisterID scr1 = claimScratch();
493 m_assembler.movlMemReg(offset >> 2, base, scr);
494 m_assembler.loadConstant(imm, scr1);
495 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
496 releaseScratch(scr1);
500 // Memory access operation
502 void load32(ImplicitAddress address, RegisterID dest)
504 load32(address.base, address.offset, dest);
507 void load8(ImplicitAddress address, RegisterID dest)
509 load8(address.base, address.offset, dest);
512 void load8(BaseIndex address, RegisterID dest)
514 RegisterID scr = claimScratch();
515 move(address.index, scr);
516 lshift32(TrustedImm32(address.scale), scr);
517 add32(address.base, scr);
518 load8(scr, address.offset, dest);
522 void load32(BaseIndex address, RegisterID dest)
524 RegisterID scr = claimScratch();
525 move(address.index, scr);
526 lshift32(TrustedImm32(address.scale), scr);
527 add32(address.base, scr);
528 load32(scr, address.offset, dest);
532 void load32(void* address, RegisterID dest)
534 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), dest);
535 m_assembler.movlMemReg(dest, dest);
538 void load32(RegisterID base, int offset, RegisterID dest)
541 m_assembler.movlMemReg(base, dest);
545 if ((offset >= 0) && (offset < 64)) {
546 m_assembler.movlMemReg(offset >> 2, base, dest);
550 if ((dest == SH4Registers::r0) && (dest != base)) {
551 m_assembler.loadConstant((offset), dest);
552 m_assembler.movlR0mr(base, dest);
558 scr = claimScratch();
561 m_assembler.loadConstant((offset), scr);
562 m_assembler.addlRegReg(base, scr);
563 m_assembler.movlMemReg(scr, dest);
569 void load8(RegisterID base, int offset, RegisterID dest)
572 m_assembler.movbMemReg(base, dest);
576 if ((offset > 0) && (offset < 64) && (dest == SH4Registers::r0)) {
577 m_assembler.movbMemReg(offset, base, dest);
582 m_assembler.loadConstant((offset), dest);
583 m_assembler.addlRegReg(base, dest);
584 m_assembler.movbMemReg(dest, dest);
588 RegisterID scr = claimScratch();
589 m_assembler.loadConstant((offset), scr);
590 m_assembler.addlRegReg(base, scr);
591 m_assembler.movbMemReg(scr, dest);
595 void load32(RegisterID r0, RegisterID src, RegisterID dst)
597 ASSERT(r0 == SH4Registers::r0);
598 m_assembler.movlR0mr(src, dst);
601 void load32(RegisterID src, RegisterID dst)
603 m_assembler.movlMemReg(src, dst);
606 void load16(ImplicitAddress address, RegisterID dest)
608 if (!address.offset) {
609 m_assembler.movwMemReg(address.base, dest);
613 if ((address.offset > 0) && (address.offset < 64) && (dest == SH4Registers::r0)) {
614 m_assembler.movwMemReg(address.offset, address.base, dest);
618 if (address.base != dest) {
619 m_assembler.loadConstant((address.offset), dest);
620 m_assembler.addlRegReg(address.base, dest);
621 m_assembler.movwMemReg(dest, dest);
625 RegisterID scr = claimScratch();
626 m_assembler.loadConstant((address.offset), scr);
627 m_assembler.addlRegReg(address.base, scr);
628 m_assembler.movwMemReg(scr, dest);
632 void load16(RegisterID src, RegisterID dest)
634 m_assembler.movwMemReg(src, dest);
637 void load16(RegisterID r0, RegisterID src, RegisterID dest)
639 ASSERT(r0 == SH4Registers::r0);
640 m_assembler.movwR0mr(src, dest);
643 void load16(BaseIndex address, RegisterID dest)
645 RegisterID scr = claimScratch();
647 move(address.index, scr);
648 lshift32(TrustedImm32(address.scale), scr);
651 add32(TrustedImm32(address.offset), scr);
652 if (scr == SH4Registers::r0)
653 m_assembler.movwR0mr(address.base, scr);
655 add32(address.base, scr);
663 void store32(RegisterID src, ImplicitAddress address)
665 RegisterID scr = claimScratch();
666 store32(src, address.offset, address.base, scr);
670 void store32(RegisterID src, int offset, RegisterID base, RegisterID scr)
673 m_assembler.movlRegMem(src, base);
677 if ((offset >=0) && (offset < 64)) {
678 m_assembler.movlRegMem(src, offset >> 2, base);
682 m_assembler.loadConstant((offset), scr);
683 if (scr == SH4Registers::r0) {
684 m_assembler.movlRegMemr0(src, base);
688 m_assembler.addlRegReg(base, scr);
689 m_assembler.movlRegMem(src, scr);
692 void store32(RegisterID src, RegisterID offset, RegisterID base)
694 ASSERT(offset == SH4Registers::r0);
695 m_assembler.movlRegMemr0(src, base);
698 void store32(RegisterID src, RegisterID dst)
700 m_assembler.movlRegMem(src, dst);
703 void store32(TrustedImm32 imm, ImplicitAddress address)
705 RegisterID scr = claimScratch();
706 RegisterID scr1 = claimScratch();
707 m_assembler.loadConstant((imm.m_value), scr);
708 store32(scr, address.offset, address.base, scr1);
710 releaseScratch(scr1);
713 void store32(RegisterID src, BaseIndex address)
715 RegisterID scr = claimScratch();
717 move(address.index, scr);
718 lshift32(TrustedImm32(address.scale), scr);
719 add32(address.base, scr);
720 store32(src, Address(scr, address.offset));
725 void store32(TrustedImm32 imm, void* address)
727 RegisterID scr = claimScratch();
728 RegisterID scr1 = claimScratch();
729 m_assembler.loadConstant((imm.m_value), scr);
730 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr1);
731 m_assembler.movlRegMem(scr, scr1);
733 releaseScratch(scr1);
736 void store32(RegisterID src, void* address)
738 RegisterID scr = claimScratch();
739 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
740 m_assembler.movlRegMem(src, scr);
744 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
746 RegisterID scr = claimScratch();
747 DataLabel32 label(this);
748 m_assembler.loadConstantUnReusable(address.offset, scr);
749 m_assembler.addlRegReg(address.base, scr);
750 m_assembler.movlMemReg(scr, dest);
755 DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
757 RegisterID scr = claimScratch();
758 DataLabel32 label(this);
759 m_assembler.loadConstantUnReusable(address.offset, scr);
760 m_assembler.addlRegReg(address.base, scr);
761 m_assembler.movlRegMem(src, scr);
766 DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
768 DataLabelCompact dataLabel(this);
769 ASSERT(address.offset <= MaximumCompactPtrAlignedAddressOffset);
770 ASSERT(address.offset >= 0);
771 m_assembler.movlMemRegCompact(address.offset >> 2, address.base, dest);
775 // Floating-point operations
777 bool supportsFloatingPoint() const { return true; }
778 bool supportsFloatingPointTruncate() const { return true; }
779 bool supportsFloatingPointSqrt() const { return true; }
780 bool supportsDoubleBitops() const { return false; }
782 void loadDouble(ImplicitAddress address, FPRegisterID dest)
784 RegisterID scr = claimScratch();
786 m_assembler.loadConstant(address.offset, scr);
787 if (address.base == SH4Registers::r0) {
788 m_assembler.fmovsReadr0r(scr, (FPRegisterID)(dest + 1));
789 m_assembler.addlImm8r(4, scr);
790 m_assembler.fmovsReadr0r(scr, dest);
795 m_assembler.addlRegReg(address.base, scr);
796 m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
797 m_assembler.fmovsReadrm(scr, dest);
801 void loadDouble(const void* address, FPRegisterID dest)
803 RegisterID scr = claimScratch();
804 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
805 m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
806 m_assembler.fmovsReadrm(scr, dest);
810 void storeDouble(FPRegisterID src, ImplicitAddress address)
812 RegisterID scr = claimScratch();
813 m_assembler.loadConstant(address.offset, scr);
814 m_assembler.addlRegReg(address.base, scr);
815 m_assembler.fmovsWriterm((FPRegisterID)(src + 1), scr);
816 m_assembler.addlImm8r(4, scr);
817 m_assembler.fmovsWriterm(src, scr);
821 void addDouble(FPRegisterID src, FPRegisterID dest)
823 m_assembler.daddRegReg(src, dest);
826 void addDouble(Address address, FPRegisterID dest)
828 loadDouble(address, fscratch);
829 addDouble(fscratch, dest);
832 void subDouble(FPRegisterID src, FPRegisterID dest)
834 m_assembler.dsubRegReg(src, dest);
837 void subDouble(Address address, FPRegisterID dest)
839 loadDouble(address, fscratch);
840 subDouble(fscratch, dest);
843 void mulDouble(FPRegisterID src, FPRegisterID dest)
845 m_assembler.dmulRegReg(src, dest);
848 void mulDouble(Address address, FPRegisterID dest)
850 loadDouble(address, fscratch);
851 mulDouble(fscratch, dest);
854 void divDouble(FPRegisterID src, FPRegisterID dest)
856 m_assembler.ddivRegReg(src, dest);
859 void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
861 m_assembler.ldsrmfpul(src);
862 m_assembler.floatfpulDreg(dest);
865 void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
867 RegisterID scr = claimScratch();
868 m_assembler.loadConstant(reinterpret_cast<uint32_t>(src.m_ptr), scr);
869 convertInt32ToDouble(scr, dest);
873 void convertInt32ToDouble(Address src, FPRegisterID dest)
875 RegisterID scr = claimScratch();
877 convertInt32ToDouble(scr, dest);
881 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
883 RegisterID scr = claimScratch();
885 move(address.index, scr);
886 lshift32(TrustedImm32(address.scale), scr);
887 add32(address.base, scr);
890 add32(TrustedImm32(address.offset), scr);
892 RegisterID scr1 = claimScratch();
894 add32(TrustedImm32(2), scr);
896 move(TrustedImm32(16), scr);
897 m_assembler.shllRegReg(dest, scr);
901 releaseScratch(scr1);
904 Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
906 RegisterID scr = scratchReg3;
907 load32WithUnalignedHalfWords(left, scr);
908 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
909 m_assembler.testlRegReg(scr, scr);
911 compare32(right.m_value, scr, cond);
913 if (cond == NotEqual)
914 return branchFalse();
918 Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
920 m_assembler.movImm8(0, scratchReg3);
921 convertInt32ToDouble(scratchReg3, scratch);
922 return branchDouble(DoubleNotEqual, reg, scratch);
925 Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
927 m_assembler.movImm8(0, scratchReg3);
928 convertInt32ToDouble(scratchReg3, scratch);
929 return branchDouble(DoubleEqualOrUnordered, reg, scratch);
932 Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
934 if (cond == DoubleEqual) {
935 m_assembler.dcmppeq(right, left);
939 if (cond == DoubleNotEqual) {
940 RegisterID scr = claimScratch();
941 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
942 m_assembler.dcnvds(right);
943 m_assembler.stsfpulReg(scr);
944 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
945 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
946 m_assembler.branch(BT_OPCODE, 8);
947 m_assembler.dcnvds(left);
948 m_assembler.stsfpulReg(scr);
949 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
950 m_assembler.branch(BT_OPCODE, 4);
951 m_assembler.dcmppeq(right, left);
953 return branchFalse();
956 if (cond == DoubleGreaterThan) {
957 m_assembler.dcmppgt(right, left);
961 if (cond == DoubleGreaterThanOrEqual) {
962 m_assembler.dcmppgt(left, right);
963 return branchFalse();
966 if (cond == DoubleLessThan) {
967 m_assembler.dcmppgt(left, right);
971 if (cond == DoubleLessThanOrEqual) {
972 m_assembler.dcmppgt(right, left);
973 return branchFalse();
976 if (cond == DoubleEqualOrUnordered) {
977 RegisterID scr = claimScratch();
978 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
979 m_assembler.dcnvds(right);
980 m_assembler.stsfpulReg(scr);
981 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
982 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
983 m_assembler.branch(BT_OPCODE, 5);
984 m_assembler.dcnvds(left);
985 m_assembler.stsfpulReg(scr);
986 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
987 m_assembler.branch(BT_OPCODE, 1);
988 m_assembler.dcmppeq(left, right);
993 if (cond == DoubleGreaterThanOrUnordered) {
994 RegisterID scr = claimScratch();
995 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
996 m_assembler.dcnvds(right);
997 m_assembler.stsfpulReg(scr);
998 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
999 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1000 m_assembler.branch(BT_OPCODE, 5);
1001 m_assembler.dcnvds(left);
1002 m_assembler.stsfpulReg(scr);
1003 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1004 m_assembler.branch(BT_OPCODE, 1);
1005 m_assembler.dcmppgt(right, left);
1006 releaseScratch(scr);
1007 return branchTrue();
1010 if (cond == DoubleGreaterThanOrEqualOrUnordered) {
1011 RegisterID scr = claimScratch();
1012 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1013 m_assembler.dcnvds(right);
1014 m_assembler.stsfpulReg(scr);
1015 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1016 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1017 m_assembler.branch(BT_OPCODE, 5);
1018 m_assembler.dcnvds(left);
1019 m_assembler.stsfpulReg(scr);
1020 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1021 m_assembler.branch(BT_OPCODE, 1);
1022 m_assembler.dcmppgt(left, right);
1023 releaseScratch(scr);
1024 return branchFalse();
1027 if (cond == DoubleLessThanOrUnordered) {
1028 RegisterID scr = claimScratch();
1029 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1030 m_assembler.dcnvds(right);
1031 m_assembler.stsfpulReg(scr);
1032 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1033 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1034 m_assembler.branch(BT_OPCODE, 5);
1035 m_assembler.dcnvds(left);
1036 m_assembler.stsfpulReg(scr);
1037 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1038 m_assembler.branch(BT_OPCODE, 1);
1039 m_assembler.dcmppgt(left, right);
1040 releaseScratch(scr);
1041 return branchTrue();
1044 if (cond == DoubleLessThanOrEqualOrUnordered) {
1045 RegisterID scr = claimScratch();
1046 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1047 m_assembler.dcnvds(right);
1048 m_assembler.stsfpulReg(scr);
1049 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1050 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1051 m_assembler.branch(BT_OPCODE, 5);
1052 m_assembler.dcnvds(left);
1053 m_assembler.stsfpulReg(scr);
1054 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1055 m_assembler.branch(BT_OPCODE, 1);
1056 m_assembler.dcmppgt(right, left);
1057 releaseScratch(scr);
1058 return branchFalse();
1061 ASSERT(cond == DoubleNotEqualOrUnordered);
1062 RegisterID scr = claimScratch();
1063 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1064 m_assembler.dcnvds(right);
1065 m_assembler.stsfpulReg(scr);
1066 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1067 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1068 m_assembler.branch(BT_OPCODE, 5);
1069 m_assembler.dcnvds(left);
1070 m_assembler.stsfpulReg(scr);
1071 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1072 m_assembler.branch(BT_OPCODE, 1);
1073 m_assembler.dcmppeq(right, left);
1074 releaseScratch(scr);
1075 return branchFalse();
1080 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
1081 Jump m_jump = Jump(m_assembler.je());
1082 m_assembler.loadConstantUnReusable(0x0, scratchReg3);
1090 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
1091 Jump m_jump = Jump(m_assembler.jne());
1092 m_assembler.loadConstantUnReusable(0x0, scratchReg3);
1098 Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1100 RegisterID scr = claimScratch();
1101 move(left.index, scr);
1102 lshift32(TrustedImm32(left.scale), scr);
1103 add32(left.base, scr);
1104 load32(scr, left.offset, scr);
1105 compare32(right.m_value, scr, cond);
1106 releaseScratch(scr);
1108 if (cond == NotEqual)
1109 return branchFalse();
1110 return branchTrue();
1113 void sqrtDouble(FPRegisterID src, FPRegisterID dest)
1116 m_assembler.dmovRegReg(src, dest);
1117 m_assembler.dsqrt(dest);
1120 void andnotDouble(FPRegisterID, FPRegisterID)
1122 ASSERT_NOT_REACHED();
1125 Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1127 RegisterID addressTempRegister = claimScratch();
1128 load8(address, addressTempRegister);
1129 Jump jmp = branchTest32(cond, addressTempRegister, mask);
1130 releaseScratch(addressTempRegister);
1134 void signExtend32ToPtr(RegisterID src, RegisterID dest)
1140 Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
1142 RegisterID addressTempRegister = claimScratch();
1143 load8(left, addressTempRegister);
1144 Jump jmp = branch32(cond, addressTempRegister, right);
1145 releaseScratch(addressTempRegister);
1149 Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
1151 m_assembler.ftrcdrmfpul(src);
1152 m_assembler.stsfpulReg(dest);
1153 m_assembler.loadConstant(0x7fffffff, scratchReg3);
1154 m_assembler.cmplRegReg(dest, scratchReg3, SH4Condition(Equal));
1155 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 14, sizeof(uint32_t));
1156 m_assembler.branch(BT_OPCODE, 2);
1157 m_assembler.addlImm8r(1, scratchReg3);
1158 m_assembler.cmplRegReg(dest, scratchReg3, SH4Condition(Equal));
1159 return branchTrue();
1162 // Stack manipulation operations
1164 void pop(RegisterID dest)
1166 m_assembler.popReg(dest);
1169 void push(RegisterID src)
1171 m_assembler.pushReg(src);
1174 void push(Address address)
1176 if (!address.offset) {
1181 if ((address.offset < 0) || (address.offset >= 64)) {
1182 RegisterID scr = claimScratch();
1183 m_assembler.loadConstant(address.offset, scr);
1184 m_assembler.addlRegReg(address.base, scr);
1185 m_assembler.movlMemReg(scr, SH4Registers::sp);
1186 m_assembler.addlImm8r(-4, SH4Registers::sp);
1187 releaseScratch(scr);
1191 m_assembler.movlMemReg(address.offset >> 2, address.base, SH4Registers::sp);
1192 m_assembler.addlImm8r(-4, SH4Registers::sp);
1195 void push(TrustedImm32 imm)
1197 RegisterID scr = claimScratch();
1198 m_assembler.loadConstant(imm.m_value, scr);
1200 releaseScratch(scr);
1203 // Register move operations
1205 void move(TrustedImm32 imm, RegisterID dest)
1207 m_assembler.loadConstant(imm.m_value, dest);
1210 DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
1212 m_assembler.ensureSpace(m_assembler.maxInstructionSize, sizeof(uint32_t));
1213 DataLabelPtr dataLabel(this);
1214 m_assembler.loadConstantUnReusable(reinterpret_cast<uint32_t>(initialValue.m_value), dest);
1218 void move(RegisterID src, RegisterID dest)
1220 m_assembler.movlRegReg(src, dest);
1223 void move(TrustedImmPtr imm, RegisterID dest)
1225 m_assembler.loadConstant(imm.asIntptr(), dest);
1228 void extuw(RegisterID src, RegisterID dst)
1230 m_assembler.extuw(src, dst);
1233 void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
1235 m_assembler.cmplRegReg(right, left, SH4Condition(cond));
1236 if (cond != NotEqual) {
1237 m_assembler.movt(dest);
1241 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
1242 m_assembler.movImm8(0, dest);
1243 m_assembler.branch(BT_OPCODE, 0);
1244 m_assembler.movImm8(1, dest);
1247 void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
1251 compare32(cond, left, dest, dest);
1255 RegisterID scr = claimScratch();
1257 compare32(cond, left, scr, dest);
1258 releaseScratch(scr);
1261 void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
1263 ASSERT((cond == Zero) || (cond == NonZero));
1265 load8(address, dest);
1266 if (mask.m_value == -1)
1267 compare32(0, dest, static_cast<RelationalCondition>(cond));
1269 testlImm(mask.m_value, dest);
1270 if (cond != NonZero) {
1271 m_assembler.movt(dest);
1275 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
1276 m_assembler.movImm8(0, dest);
1277 m_assembler.branch(BT_OPCODE, 0);
1278 m_assembler.movImm8(1, dest);
1281 void loadPtrLinkReg(ImplicitAddress address)
1283 RegisterID scr = claimScratch();
1284 load32(address, scr);
1285 m_assembler.ldspr(scr);
1286 releaseScratch(scr);
1289 Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
1291 m_assembler.cmplRegReg(right, left, SH4Condition(cond));
1292 /* BT label => BF off
1297 if (cond == NotEqual)
1298 return branchFalse();
1299 return branchTrue();
1302 Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
1304 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1305 m_assembler.testlRegReg(left, left);
1307 compare32(right.m_value, left, cond);
1309 if (cond == NotEqual)
1310 return branchFalse();
1311 return branchTrue();
1314 Jump branch32(RelationalCondition cond, RegisterID left, Address right)
1316 compare32(right.offset, right.base, left, cond);
1317 if (cond == NotEqual)
1318 return branchFalse();
1319 return branchTrue();
1322 Jump branch32(RelationalCondition cond, Address left, RegisterID right)
1324 compare32(right, left.offset, left.base, cond);
1325 if (cond == NotEqual)
1326 return branchFalse();
1327 return branchTrue();
1330 Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
1332 compare32(right.m_value, left.offset, left.base, cond);
1333 if (cond == NotEqual)
1334 return branchFalse();
1335 return branchTrue();
1338 Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
1340 RegisterID scr = claimScratch();
1342 move(TrustedImm32(reinterpret_cast<uint32_t>(left.m_ptr)), scr);
1343 m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
1344 releaseScratch(scr);
1346 if (cond == NotEqual)
1347 return branchFalse();
1348 return branchTrue();
1351 Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
1353 RegisterID addressTempRegister = claimScratch();
1355 m_assembler.loadConstant(reinterpret_cast<uint32_t>(left.m_ptr), addressTempRegister);
1356 m_assembler.movlMemReg(addressTempRegister, addressTempRegister);
1357 compare32(right.m_value, addressTempRegister, cond);
1358 releaseScratch(addressTempRegister);
1360 if (cond == NotEqual)
1361 return branchFalse();
1362 return branchTrue();
1365 Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1367 ASSERT(!(right.m_value & 0xFFFFFF00));
1368 RegisterID scr = claimScratch();
1370 move(left.index, scr);
1371 lshift32(TrustedImm32(left.scale), scr);
1374 add32(TrustedImm32(left.offset), scr);
1375 add32(left.base, scr);
1378 RegisterID scr1 = claimScratch();
1379 m_assembler.loadConstant(right.m_value, scr1);
1380 releaseScratch(scr);
1381 releaseScratch(scr1);
1383 return branch32(cond, scr, scr1);
1386 Jump branch16(RelationalCondition cond, RegisterID left, TrustedImm32 right)
1388 ASSERT(!(right.m_value & 0xFFFF0000));
1389 RegisterID scr = claimScratch();
1392 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1393 m_assembler.testlRegReg(scr, scr);
1395 compare32(right.m_value, scr, cond);
1397 releaseScratch(scr);
1399 if (cond == NotEqual)
1400 return branchFalse();
1401 return branchTrue();
1404 Jump branch16(RelationalCondition cond, BaseIndex left, RegisterID right)
1406 RegisterID scr = claimScratch();
1408 move(left.index, scr);
1409 lshift32(TrustedImm32(left.scale), scr);
1412 add32(TrustedImm32(left.offset), scr);
1413 add32(left.base, scr);
1416 releaseScratch(scr);
1418 return branch32(cond, scr, right);
1421 Jump branch16(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1423 RegisterID scr = claimScratch();
1425 move(left.index, scr);
1426 lshift32(TrustedImm32(left.scale), scr);
1429 add32(TrustedImm32(left.offset), scr);
1430 add32(left.base, scr);
1433 RegisterID scr1 = claimScratch();
1434 m_assembler.loadConstant(right.m_value, scr1);
1435 releaseScratch(scr);
1436 releaseScratch(scr1);
1438 return branch32(cond, scr, scr1);
1441 Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
1443 ASSERT((cond == Zero) || (cond == NonZero));
1445 m_assembler.testlRegReg(reg, mask);
1447 if (cond == NotEqual)
1448 return branchFalse();
1449 return branchTrue();
1452 Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
1454 ASSERT((cond == Zero) || (cond == NonZero));
1456 if (mask.m_value == -1)
1457 m_assembler.testlRegReg(reg, reg);
1459 testlImm(mask.m_value, reg);
1461 if (cond == NotEqual)
1462 return branchFalse();
1463 return branchTrue();
1466 Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1468 ASSERT((cond == Zero) || (cond == NonZero));
1470 if (mask.m_value == -1)
1471 compare32(0, address.offset, address.base, static_cast<RelationalCondition>(cond));
1473 testImm(mask.m_value, address.offset, address.base);
1475 if (cond == NotEqual)
1476 return branchFalse();
1477 return branchTrue();
1480 Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
1482 RegisterID scr = claimScratch();
1484 move(address.index, scr);
1485 lshift32(TrustedImm32(address.scale), scr);
1486 add32(address.base, scr);
1487 load32(scr, address.offset, scr);
1489 if (mask.m_value == -1)
1490 m_assembler.testlRegReg(scr, scr);
1492 testlImm(mask.m_value, scr);
1494 releaseScratch(scr);
1496 if (cond == NotEqual)
1497 return branchFalse();
1498 return branchTrue();
1503 return Jump(m_assembler.jmp());
1506 void jump(RegisterID target)
1508 m_assembler.jmpReg(target);
1511 void jump(Address address)
1513 RegisterID scr = claimScratch();
1515 if ((address.offset < 0) || (address.offset >= 64)) {
1516 m_assembler.loadConstant(address.offset, scr);
1517 m_assembler.addlRegReg(address.base, scr);
1518 m_assembler.movlMemReg(scr, scr);
1519 } else if (address.offset)
1520 m_assembler.movlMemReg(address.offset >> 2, address.base, scr);
1522 m_assembler.movlMemReg(address.base, scr);
1523 m_assembler.jmpReg(scr);
1525 releaseScratch(scr);
1528 // Arithmetic control flow operations
1530 Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
1532 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1534 if (cond == Overflow) {
1535 m_assembler.addvlRegReg(src, dest);
1536 return branchTrue();
1539 if (cond == Signed) {
1540 m_assembler.addlRegReg(src, dest);
1541 // Check if dest is negative
1542 m_assembler.cmppz(dest);
1543 return branchFalse();
1546 m_assembler.addlRegReg(src, dest);
1547 compare32(0, dest, Equal);
1549 if (cond == NotEqual)
1550 return branchFalse();
1551 return branchTrue();
1554 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
1556 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1558 move(imm, scratchReg3);
1559 return branchAdd32(cond, scratchReg3, dest);
1562 Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
1564 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1566 if (cond == Overflow) {
1567 RegisterID scr1 = claimScratch();
1568 RegisterID scr = claimScratch();
1569 m_assembler.dmullRegReg(src, dest);
1570 m_assembler.stsmacl(dest);
1571 m_assembler.movImm8(-31, scr);
1572 m_assembler.movlRegReg(dest, scr1);
1573 m_assembler.shaRegReg(scr1, scr);
1574 m_assembler.stsmach(scr);
1575 m_assembler.cmplRegReg(scr, scr1, SH4Condition(Equal));
1576 releaseScratch(scr1);
1577 releaseScratch(scr);
1578 return branchFalse();
1581 m_assembler.imullRegReg(src, dest);
1582 m_assembler.stsmacl(dest);
1583 if (cond == Signed) {
1584 // Check if dest is negative
1585 m_assembler.cmppz(dest);
1586 return branchFalse();
1589 compare32(0, dest, static_cast<RelationalCondition>(cond));
1591 if (cond == NotEqual)
1592 return branchFalse();
1593 return branchTrue();
1596 Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
1598 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1600 move(imm, scratchReg3);
1604 return branchMul32(cond, scratchReg3, dest);
1607 Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
1609 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1611 if (cond == Overflow) {
1612 m_assembler.subvlRegReg(src, dest);
1613 return branchTrue();
1616 if (cond == Signed) {
1617 // Check if dest is negative
1618 m_assembler.sublRegReg(src, dest);
1619 compare32(0, dest, LessThan);
1620 return branchTrue();
1624 compare32(0, dest, static_cast<RelationalCondition>(cond));
1626 if (cond == NotEqual)
1627 return branchFalse();
1628 return branchTrue();
1631 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
1633 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1635 move(imm, scratchReg3);
1636 return branchSub32(cond, scratchReg3, dest);
1639 Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
1641 ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
1643 if (cond == Signed) {
1645 compare32(0, dest, static_cast<RelationalCondition>(LessThan));
1646 return branchTrue();
1650 compare32(0, dest, static_cast<RelationalCondition>(cond));
1652 if (cond == NotEqual)
1653 return branchFalse();
1654 return branchTrue();
1657 void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
1659 m_assembler.ftrcdrmfpul(src);
1660 m_assembler.stsfpulReg(dest);
1661 convertInt32ToDouble(dest, fscratch);
1662 failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fscratch, src));
1664 if (dest == SH4Registers::r0)
1665 m_assembler.cmpEqImmR0(0, dest);
1667 m_assembler.movImm8(0, scratchReg3);
1668 m_assembler.cmplRegReg(scratchReg3, dest, SH4Condition(Equal));
1670 failureCases.append(branchTrue());
1673 void neg32(RegisterID dst)
1675 m_assembler.neg(dst, dst);
1678 void not32(RegisterID dst)
1680 m_assembler.notlReg(dst, dst);
1683 void urshift32(RegisterID shiftamount, RegisterID dest)
1685 compare32(32, shiftamount, Equal);
1686 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
1687 m_assembler.branch(BT_OPCODE, 1);
1688 m_assembler.neg(shiftamount, shiftamount);
1689 m_assembler.shllRegReg(dest, shiftamount);
1692 void urshift32(TrustedImm32 imm, RegisterID dest)
1694 RegisterID scr = claimScratch();
1695 m_assembler.loadConstant(-(imm.m_value), scr);
1696 m_assembler.shaRegReg(dest, scr);
1697 releaseScratch(scr);
1702 return Call(m_assembler.call(), Call::Linkable);
1707 return Call(m_assembler.call(), Call::LinkableNear);
1710 Call call(RegisterID target)
1712 return Call(m_assembler.call(target), Call::None);
1715 void call(Address address, RegisterID target)
1717 load32(address.base, address.offset, target);
1718 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 2);
1719 m_assembler.branch(JSR_OPCODE, target);
1729 Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
1731 RegisterID dataTempRegister = claimScratch();
1733 dataLabel = moveWithPatch(initialRightValue, dataTempRegister);
1734 m_assembler.cmplRegReg(dataTempRegister, left, SH4Condition(cond));
1735 releaseScratch(dataTempRegister);
1737 if (cond == NotEqual)
1738 return branchFalse();
1739 return branchTrue();
1742 Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
1744 RegisterID scr = claimScratch();
1746 m_assembler.loadConstant(left.offset, scr);
1747 m_assembler.addlRegReg(left.base, scr);
1748 m_assembler.movlMemReg(scr, scr);
1749 RegisterID scr1 = claimScratch();
1750 dataLabel = moveWithPatch(initialRightValue, scr1);
1751 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
1752 releaseScratch(scr);
1753 releaseScratch(scr1);
1755 if (cond == NotEqual)
1756 return branchFalse();
1757 return branchTrue();
1766 DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
1768 RegisterID scr = claimScratch();
1769 DataLabelPtr label = moveWithPatch(initialValue, scr);
1770 store32(scr, address);
1771 releaseScratch(scr);
1775 DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(TrustedImmPtr(0), address); }
1777 int sizeOfConstantPool()
1779 return m_assembler.sizeOfConstantPool();
1782 Call tailRecursiveCall()
1784 RegisterID scr = claimScratch();
1786 m_assembler.loadConstantUnReusable(0x0, scr, true);
1787 Jump m_jump = Jump(m_assembler.jmp(scr));
1788 releaseScratch(scr);
1790 return Call::fromTailJump(m_jump);
1793 Call makeTailRecursiveCall(Jump oldJump)
1796 return tailRecursiveCall();
1805 SH4Assembler::Condition SH4Condition(RelationalCondition cond)
1807 return static_cast<SH4Assembler::Condition>(cond);
1810 SH4Assembler::Condition SH4Condition(ResultCondition cond)
1812 return static_cast<SH4Assembler::Condition>(cond);
1815 friend class LinkBuffer;
1816 friend class RepatchBuffer;
1818 static void linkCall(void*, Call, FunctionPtr);
1819 static void repatchCall(CodeLocationCall, CodeLocationLabel);
1820 static void repatchCall(CodeLocationCall, FunctionPtr);
1825 #endif // ENABLE(ASSEMBLER)
1827 #endif // MacroAssemblerSH4_h