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 or32(RegisterID op1, RegisterID op2, RegisterID dest)
228 else if (op1 == dest)
236 void rshift32(RegisterID shiftamount, RegisterID dest)
238 compare32(32, shiftamount, Equal);
239 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
240 m_assembler.branch(BT_OPCODE, 1);
241 m_assembler.neg(shiftamount, shiftamount);
242 m_assembler.shaRegReg(dest, shiftamount);
245 void rshift32(TrustedImm32 imm, RegisterID dest)
247 if (imm.m_value & 0x1f)
248 rshift32(imm.m_value & 0x1f, dest);
251 void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
258 void sub32(RegisterID src, RegisterID dest)
260 m_assembler.sublRegReg(src, dest);
263 void sub32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg)
265 RegisterID result = claimScratch();
267 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
268 m_assembler.movlMemReg(scratchReg, result);
270 if (m_assembler.isImmediate(-imm.m_value))
271 m_assembler.addlImm8r(-imm.m_value, result);
273 m_assembler.loadConstant(imm.m_value, scratchReg3);
274 m_assembler.sublRegReg(scratchReg3, result);
277 store32(result, scratchReg);
278 releaseScratch(result);
281 void sub32(TrustedImm32 imm, AbsoluteAddress address)
283 RegisterID result = claimScratch();
284 RegisterID scratchReg = claimScratch();
286 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
287 m_assembler.movlMemReg(scratchReg, result);
289 if (m_assembler.isImmediate(-imm.m_value))
290 m_assembler.addlImm8r(-imm.m_value, result);
292 m_assembler.loadConstant(imm.m_value, scratchReg3);
293 m_assembler.sublRegReg(scratchReg3, result);
296 store32(result, scratchReg);
297 releaseScratch(result);
298 releaseScratch(scratchReg);
301 void add32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg)
303 RegisterID result = claimScratch();
305 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
306 m_assembler.movlMemReg(scratchReg, result);
308 if (m_assembler.isImmediate(imm.m_value))
309 m_assembler.addlImm8r(imm.m_value, result);
311 m_assembler.loadConstant(imm.m_value, scratchReg3);
312 m_assembler.addlRegReg(scratchReg3, result);
315 store32(result, scratchReg);
316 releaseScratch(result);
319 void add32(TrustedImm32 imm, AbsoluteAddress address)
321 RegisterID result = claimScratch();
322 RegisterID scratchReg = claimScratch();
324 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
325 m_assembler.movlMemReg(scratchReg, result);
327 if (m_assembler.isImmediate(imm.m_value))
328 m_assembler.addlImm8r(imm.m_value, result);
330 m_assembler.loadConstant(imm.m_value, scratchReg3);
331 m_assembler.addlRegReg(scratchReg3, result);
334 store32(result, scratchReg);
335 releaseScratch(result);
336 releaseScratch(scratchReg);
339 void sub32(TrustedImm32 imm, RegisterID dest)
341 if (m_assembler.isImmediate(-imm.m_value)) {
342 m_assembler.addlImm8r(-imm.m_value, dest);
346 RegisterID scr = claimScratch();
347 m_assembler.loadConstant(imm.m_value, scr);
348 m_assembler.sublRegReg(scr, dest);
352 void sub32(Address src, RegisterID dest)
354 RegisterID scr = claimScratch();
356 m_assembler.sublRegReg(scr, dest);
360 void xor32(RegisterID src, RegisterID dest)
362 m_assembler.xorlRegReg(src, dest);
365 void xor32(TrustedImm32 imm, RegisterID srcDest)
367 if ((srcDest != SH4Registers::r0) || (imm.m_value > 255) || (imm.m_value < 0)) {
368 RegisterID scr = claimScratch();
369 m_assembler.loadConstant((imm.m_value), scr);
370 m_assembler.xorlRegReg(scr, srcDest);
375 m_assembler.xorlImm8r(imm.m_value, srcDest);
378 void compare32(int imm, RegisterID dst, RelationalCondition cond)
380 if (((cond == Equal) || (cond == NotEqual)) && (dst == SH4Registers::r0) && m_assembler.isImmediate(imm)) {
381 m_assembler.cmpEqImmR0(imm, dst);
385 RegisterID scr = claimScratch();
386 m_assembler.loadConstant(imm, scr);
387 m_assembler.cmplRegReg(scr, dst, SH4Condition(cond));
391 void compare32(int offset, RegisterID base, RegisterID left, RelationalCondition cond)
393 RegisterID scr = claimScratch();
395 m_assembler.movlMemReg(base, scr);
396 m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
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 m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
410 m_assembler.movlMemReg(offset >> 2, base, scr);
411 m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
415 void testImm(int imm, int offset, RegisterID base)
417 RegisterID scr = claimScratch();
418 RegisterID scr1 = claimScratch();
420 if ((offset < 0) || (offset >= 64)) {
421 m_assembler.loadConstant(offset, scr);
422 m_assembler.addlRegReg(base, scr);
423 m_assembler.movlMemReg(scr, scr);
425 m_assembler.movlMemReg(offset >> 2, base, scr);
427 m_assembler.movlMemReg(base, scr);
428 if (m_assembler.isImmediate(imm))
429 m_assembler.movImm8(imm, scr1);
431 m_assembler.loadConstant(imm, scr1);
433 m_assembler.testlRegReg(scr, scr1);
435 releaseScratch(scr1);
438 void testlImm(int imm, RegisterID dst)
440 if ((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0)) {
441 m_assembler.testlImm8r(imm, dst);
445 RegisterID scr = claimScratch();
446 m_assembler.loadConstant(imm, scr);
447 m_assembler.testlRegReg(scr, dst);
451 void compare32(RegisterID right, int offset, RegisterID base, RelationalCondition cond)
454 RegisterID scr = claimScratch();
455 m_assembler.movlMemReg(base, scr);
456 m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
461 if ((offset < 0) || (offset >= 64)) {
462 RegisterID scr = claimScratch();
463 m_assembler.loadConstant(offset, scr);
464 m_assembler.addlRegReg(base, scr);
465 m_assembler.movlMemReg(scr, scr);
466 m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
471 RegisterID scr = claimScratch();
472 m_assembler.movlMemReg(offset >> 2, base, scr);
473 m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
477 void compare32(int imm, int offset, RegisterID base, RelationalCondition cond)
480 RegisterID scr = claimScratch();
481 RegisterID scr1 = claimScratch();
482 m_assembler.movlMemReg(base, scr);
483 m_assembler.loadConstant(imm, scr1);
484 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
485 releaseScratch(scr1);
490 if ((offset < 0) || (offset >= 64)) {
491 RegisterID scr = claimScratch();
492 RegisterID scr1 = claimScratch();
493 m_assembler.loadConstant(offset, scr);
494 m_assembler.addlRegReg(base, scr);
495 m_assembler.movlMemReg(scr, scr);
496 m_assembler.loadConstant(imm, scr1);
497 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
498 releaseScratch(scr1);
503 RegisterID scr = claimScratch();
504 RegisterID scr1 = claimScratch();
505 m_assembler.movlMemReg(offset >> 2, base, scr);
506 m_assembler.loadConstant(imm, scr1);
507 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
508 releaseScratch(scr1);
512 // Memory access operation
514 void load32(ImplicitAddress address, RegisterID dest)
516 load32(address.base, address.offset, dest);
519 void load8(ImplicitAddress address, RegisterID dest)
521 load8(address.base, address.offset, dest);
524 void load8(BaseIndex address, RegisterID dest)
526 RegisterID scr = claimScratch();
527 move(address.index, scr);
528 lshift32(TrustedImm32(address.scale), scr);
529 add32(address.base, scr);
530 load8(scr, address.offset, dest);
534 void load32(BaseIndex address, RegisterID dest)
536 RegisterID scr = claimScratch();
537 move(address.index, scr);
538 lshift32(TrustedImm32(address.scale), scr);
539 add32(address.base, scr);
540 load32(scr, address.offset, dest);
544 void load32(const void* address, RegisterID dest)
546 m_assembler.loadConstant(reinterpret_cast<uint32_t>(const_cast<void*>(address)), dest);
547 m_assembler.movlMemReg(dest, dest);
550 void load32(RegisterID base, int offset, RegisterID dest)
553 m_assembler.movlMemReg(base, dest);
557 if ((offset >= 0) && (offset < 64)) {
558 m_assembler.movlMemReg(offset >> 2, base, dest);
562 if ((dest == SH4Registers::r0) && (dest != base)) {
563 m_assembler.loadConstant((offset), dest);
564 m_assembler.movlR0mr(base, dest);
570 scr = claimScratch();
573 m_assembler.loadConstant((offset), scr);
574 m_assembler.addlRegReg(base, scr);
575 m_assembler.movlMemReg(scr, dest);
581 void load8(RegisterID base, int offset, RegisterID dest)
584 m_assembler.movbMemReg(base, dest);
588 if ((offset > 0) && (offset < 64) && (dest == SH4Registers::r0)) {
589 m_assembler.movbMemReg(offset, base, dest);
594 m_assembler.loadConstant((offset), dest);
595 m_assembler.addlRegReg(base, dest);
596 m_assembler.movbMemReg(dest, dest);
600 RegisterID scr = claimScratch();
601 m_assembler.loadConstant((offset), scr);
602 m_assembler.addlRegReg(base, scr);
603 m_assembler.movbMemReg(scr, dest);
607 void load32(RegisterID r0, RegisterID src, RegisterID dst)
609 ASSERT(r0 == SH4Registers::r0);
610 m_assembler.movlR0mr(src, dst);
613 void load32(RegisterID src, RegisterID dst)
615 m_assembler.movlMemReg(src, dst);
618 void load16(ImplicitAddress address, RegisterID dest)
620 if (!address.offset) {
621 m_assembler.movwMemReg(address.base, dest);
625 if ((address.offset > 0) && (address.offset < 64) && (dest == SH4Registers::r0)) {
626 m_assembler.movwMemReg(address.offset, address.base, dest);
630 if (address.base != dest) {
631 m_assembler.loadConstant((address.offset), dest);
632 m_assembler.addlRegReg(address.base, dest);
633 m_assembler.movwMemReg(dest, dest);
637 RegisterID scr = claimScratch();
638 m_assembler.loadConstant((address.offset), scr);
639 m_assembler.addlRegReg(address.base, scr);
640 m_assembler.movwMemReg(scr, dest);
644 void load16(RegisterID src, RegisterID dest)
646 m_assembler.movwMemReg(src, dest);
649 void load16(RegisterID r0, RegisterID src, RegisterID dest)
651 ASSERT(r0 == SH4Registers::r0);
652 m_assembler.movwR0mr(src, dest);
655 void load16(BaseIndex address, RegisterID dest)
657 RegisterID scr = claimScratch();
659 move(address.index, scr);
660 lshift32(TrustedImm32(address.scale), scr);
663 add32(TrustedImm32(address.offset), scr);
664 if (scr == SH4Registers::r0)
665 m_assembler.movwR0mr(address.base, scr);
667 add32(address.base, scr);
675 void store32(RegisterID src, ImplicitAddress address)
677 RegisterID scr = claimScratch();
678 store32(src, address.offset, address.base, scr);
682 void store32(RegisterID src, int offset, RegisterID base, RegisterID scr)
685 m_assembler.movlRegMem(src, base);
689 if ((offset >=0) && (offset < 64)) {
690 m_assembler.movlRegMem(src, offset >> 2, base);
694 m_assembler.loadConstant((offset), scr);
695 if (scr == SH4Registers::r0) {
696 m_assembler.movlRegMemr0(src, base);
700 m_assembler.addlRegReg(base, scr);
701 m_assembler.movlRegMem(src, scr);
704 void store32(RegisterID src, RegisterID offset, RegisterID base)
706 ASSERT(offset == SH4Registers::r0);
707 m_assembler.movlRegMemr0(src, base);
710 void store32(RegisterID src, RegisterID dst)
712 m_assembler.movlRegMem(src, dst);
715 void store32(TrustedImm32 imm, ImplicitAddress address)
717 RegisterID scr = claimScratch();
718 RegisterID scr1 = claimScratch();
719 m_assembler.loadConstant((imm.m_value), scr);
720 store32(scr, address.offset, address.base, scr1);
722 releaseScratch(scr1);
725 void store32(RegisterID src, BaseIndex address)
727 RegisterID scr = claimScratch();
729 move(address.index, scr);
730 lshift32(TrustedImm32(address.scale), scr);
731 add32(address.base, scr);
732 store32(src, Address(scr, address.offset));
737 void store32(TrustedImm32 imm, void* address)
739 RegisterID scr = claimScratch();
740 RegisterID scr1 = claimScratch();
741 m_assembler.loadConstant((imm.m_value), scr);
742 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr1);
743 m_assembler.movlRegMem(scr, scr1);
745 releaseScratch(scr1);
748 void store32(RegisterID src, void* address)
750 RegisterID scr = claimScratch();
751 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
752 m_assembler.movlRegMem(src, scr);
756 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
758 RegisterID scr = claimScratch();
759 DataLabel32 label(this);
760 m_assembler.loadConstantUnReusable(address.offset, scr);
761 m_assembler.addlRegReg(address.base, scr);
762 m_assembler.movlMemReg(scr, dest);
767 DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
769 RegisterID scr = claimScratch();
770 DataLabel32 label(this);
771 m_assembler.loadConstantUnReusable(address.offset, scr);
772 m_assembler.addlRegReg(address.base, scr);
773 m_assembler.movlRegMem(src, scr);
778 DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
780 DataLabelCompact dataLabel(this);
781 ASSERT(address.offset <= MaximumCompactPtrAlignedAddressOffset);
782 ASSERT(address.offset >= 0);
783 m_assembler.movlMemRegCompact(address.offset >> 2, address.base, dest);
787 // Floating-point operations
789 static bool supportsFloatingPoint() { return true; }
790 static bool supportsFloatingPointTruncate() { return true; }
791 static bool supportsFloatingPointSqrt() { return true; }
792 static bool supportsFloatingPointAbs() { return false; }
794 void loadDouble(ImplicitAddress address, FPRegisterID dest)
796 RegisterID scr = claimScratch();
798 m_assembler.loadConstant(address.offset, scr);
799 if (address.base == SH4Registers::r0) {
800 m_assembler.fmovsReadr0r(scr, (FPRegisterID)(dest + 1));
801 m_assembler.addlImm8r(4, scr);
802 m_assembler.fmovsReadr0r(scr, dest);
807 m_assembler.addlRegReg(address.base, scr);
808 m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
809 m_assembler.fmovsReadrm(scr, dest);
813 void loadDouble(const void* address, FPRegisterID dest)
815 RegisterID scr = claimScratch();
816 m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
817 m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
818 m_assembler.fmovsReadrm(scr, dest);
822 void storeDouble(FPRegisterID src, ImplicitAddress address)
824 RegisterID scr = claimScratch();
825 m_assembler.loadConstant(address.offset, scr);
826 m_assembler.addlRegReg(address.base, scr);
827 m_assembler.fmovsWriterm((FPRegisterID)(src + 1), scr);
828 m_assembler.addlImm8r(4, scr);
829 m_assembler.fmovsWriterm(src, scr);
833 void addDouble(FPRegisterID src, FPRegisterID dest)
835 m_assembler.daddRegReg(src, dest);
838 void addDouble(Address address, FPRegisterID dest)
840 loadDouble(address, fscratch);
841 addDouble(fscratch, dest);
844 void subDouble(FPRegisterID src, FPRegisterID dest)
846 m_assembler.dsubRegReg(src, dest);
849 void subDouble(Address address, FPRegisterID dest)
851 loadDouble(address, fscratch);
852 subDouble(fscratch, dest);
855 void mulDouble(FPRegisterID src, FPRegisterID dest)
857 m_assembler.dmulRegReg(src, dest);
860 void mulDouble(Address address, FPRegisterID dest)
862 loadDouble(address, fscratch);
863 mulDouble(fscratch, dest);
866 void divDouble(FPRegisterID src, FPRegisterID dest)
868 m_assembler.ddivRegReg(src, dest);
871 void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
873 m_assembler.ldsrmfpul(src);
874 m_assembler.floatfpulDreg(dest);
877 void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
879 RegisterID scr = claimScratch();
880 m_assembler.loadConstant(reinterpret_cast<uint32_t>(src.m_ptr), scr);
881 convertInt32ToDouble(scr, dest);
885 void convertInt32ToDouble(Address src, FPRegisterID dest)
887 RegisterID scr = claimScratch();
889 convertInt32ToDouble(scr, dest);
893 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
895 RegisterID scr = claimScratch();
897 move(address.index, scr);
898 lshift32(TrustedImm32(address.scale), scr);
899 add32(address.base, scr);
902 add32(TrustedImm32(address.offset), scr);
904 RegisterID scr1 = claimScratch();
906 add32(TrustedImm32(2), scr);
908 move(TrustedImm32(16), scr);
909 m_assembler.shllRegReg(dest, scr);
913 releaseScratch(scr1);
916 Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
918 RegisterID scr = scratchReg3;
919 load32WithUnalignedHalfWords(left, scr);
920 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
921 m_assembler.testlRegReg(scr, scr);
923 compare32(right.m_value, scr, cond);
925 if (cond == NotEqual)
926 return branchFalse();
930 Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
932 m_assembler.movImm8(0, scratchReg3);
933 convertInt32ToDouble(scratchReg3, scratch);
934 return branchDouble(DoubleNotEqual, reg, scratch);
937 Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
939 m_assembler.movImm8(0, scratchReg3);
940 convertInt32ToDouble(scratchReg3, scratch);
941 return branchDouble(DoubleEqualOrUnordered, reg, scratch);
944 Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
946 if (cond == DoubleEqual) {
947 m_assembler.dcmppeq(right, left);
951 if (cond == DoubleNotEqual) {
952 RegisterID scr = claimScratch();
953 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
954 m_assembler.dcnvds(right);
955 m_assembler.stsfpulReg(scr);
956 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
957 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
958 m_assembler.branch(BT_OPCODE, 8);
959 m_assembler.dcnvds(left);
960 m_assembler.stsfpulReg(scr);
961 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
962 m_assembler.branch(BT_OPCODE, 4);
963 m_assembler.dcmppeq(right, left);
965 return branchFalse();
968 if (cond == DoubleGreaterThan) {
969 m_assembler.dcmppgt(right, left);
973 if (cond == DoubleGreaterThanOrEqual) {
974 m_assembler.dcmppgt(left, right);
975 return branchFalse();
978 if (cond == DoubleLessThan) {
979 m_assembler.dcmppgt(left, right);
983 if (cond == DoubleLessThanOrEqual) {
984 m_assembler.dcmppgt(right, left);
985 return branchFalse();
988 if (cond == DoubleEqualOrUnordered) {
989 RegisterID scr = claimScratch();
990 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
991 m_assembler.dcnvds(right);
992 m_assembler.stsfpulReg(scr);
993 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
994 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
995 m_assembler.branch(BT_OPCODE, 5);
996 m_assembler.dcnvds(left);
997 m_assembler.stsfpulReg(scr);
998 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
999 m_assembler.branch(BT_OPCODE, 1);
1000 m_assembler.dcmppeq(left, right);
1001 releaseScratch(scr);
1002 return branchTrue();
1005 if (cond == DoubleGreaterThanOrUnordered) {
1006 RegisterID scr = claimScratch();
1007 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1008 m_assembler.dcnvds(right);
1009 m_assembler.stsfpulReg(scr);
1010 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1011 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1012 m_assembler.branch(BT_OPCODE, 5);
1013 m_assembler.dcnvds(left);
1014 m_assembler.stsfpulReg(scr);
1015 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1016 m_assembler.branch(BT_OPCODE, 1);
1017 m_assembler.dcmppgt(right, left);
1018 releaseScratch(scr);
1019 return branchTrue();
1022 if (cond == DoubleGreaterThanOrEqualOrUnordered) {
1023 RegisterID scr = claimScratch();
1024 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1025 m_assembler.dcnvds(right);
1026 m_assembler.stsfpulReg(scr);
1027 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1028 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1029 m_assembler.branch(BT_OPCODE, 5);
1030 m_assembler.dcnvds(left);
1031 m_assembler.stsfpulReg(scr);
1032 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1033 m_assembler.branch(BT_OPCODE, 1);
1034 m_assembler.dcmppgt(left, right);
1035 releaseScratch(scr);
1036 return branchFalse();
1039 if (cond == DoubleLessThanOrUnordered) {
1040 RegisterID scr = claimScratch();
1041 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1042 m_assembler.dcnvds(right);
1043 m_assembler.stsfpulReg(scr);
1044 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1045 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1046 m_assembler.branch(BT_OPCODE, 5);
1047 m_assembler.dcnvds(left);
1048 m_assembler.stsfpulReg(scr);
1049 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1050 m_assembler.branch(BT_OPCODE, 1);
1051 m_assembler.dcmppgt(left, right);
1052 releaseScratch(scr);
1053 return branchTrue();
1056 if (cond == DoubleLessThanOrEqualOrUnordered) {
1057 RegisterID scr = claimScratch();
1058 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1059 m_assembler.dcnvds(right);
1060 m_assembler.stsfpulReg(scr);
1061 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1062 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1063 m_assembler.branch(BT_OPCODE, 5);
1064 m_assembler.dcnvds(left);
1065 m_assembler.stsfpulReg(scr);
1066 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1067 m_assembler.branch(BT_OPCODE, 1);
1068 m_assembler.dcmppgt(right, left);
1069 releaseScratch(scr);
1070 return branchFalse();
1073 ASSERT(cond == DoubleNotEqualOrUnordered);
1074 RegisterID scr = claimScratch();
1075 m_assembler.loadConstant(0x7fbfffff, scratchReg3);
1076 m_assembler.dcnvds(right);
1077 m_assembler.stsfpulReg(scr);
1078 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1079 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1080 m_assembler.branch(BT_OPCODE, 5);
1081 m_assembler.dcnvds(left);
1082 m_assembler.stsfpulReg(scr);
1083 m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
1084 m_assembler.branch(BT_OPCODE, 1);
1085 m_assembler.dcmppeq(right, left);
1086 releaseScratch(scr);
1087 return branchFalse();
1092 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
1093 Jump m_jump = Jump(m_assembler.je());
1094 m_assembler.loadConstantUnReusable(0x0, scratchReg3);
1102 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
1103 Jump m_jump = Jump(m_assembler.jne());
1104 m_assembler.loadConstantUnReusable(0x0, scratchReg3);
1110 Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1112 RegisterID scr = claimScratch();
1113 move(left.index, scr);
1114 lshift32(TrustedImm32(left.scale), scr);
1115 add32(left.base, scr);
1116 load32(scr, left.offset, scr);
1117 compare32(right.m_value, scr, cond);
1118 releaseScratch(scr);
1120 if (cond == NotEqual)
1121 return branchFalse();
1122 return branchTrue();
1125 void sqrtDouble(FPRegisterID src, FPRegisterID dest)
1128 m_assembler.dmovRegReg(src, dest);
1129 m_assembler.dsqrt(dest);
1132 void absDouble(FPRegisterID, FPRegisterID)
1134 ASSERT_NOT_REACHED();
1137 Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1139 RegisterID addressTempRegister = claimScratch();
1140 load8(address, addressTempRegister);
1141 Jump jmp = branchTest32(cond, addressTempRegister, mask);
1142 releaseScratch(addressTempRegister);
1146 void signExtend32ToPtr(RegisterID src, RegisterID dest)
1152 Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
1154 RegisterID addressTempRegister = claimScratch();
1155 load8(left, addressTempRegister);
1156 Jump jmp = branch32(cond, addressTempRegister, right);
1157 releaseScratch(addressTempRegister);
1161 Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
1163 m_assembler.ftrcdrmfpul(src);
1164 m_assembler.stsfpulReg(dest);
1165 m_assembler.loadConstant(0x7fffffff, scratchReg3);
1166 m_assembler.cmplRegReg(dest, scratchReg3, SH4Condition(Equal));
1167 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 14, sizeof(uint32_t));
1168 m_assembler.branch(BT_OPCODE, 2);
1169 m_assembler.addlImm8r(1, scratchReg3);
1170 m_assembler.cmplRegReg(dest, scratchReg3, SH4Condition(Equal));
1171 return branchTrue();
1174 // Stack manipulation operations
1176 void pop(RegisterID dest)
1178 m_assembler.popReg(dest);
1181 void push(RegisterID src)
1183 m_assembler.pushReg(src);
1186 void push(Address address)
1188 if (!address.offset) {
1193 if ((address.offset < 0) || (address.offset >= 64)) {
1194 RegisterID scr = claimScratch();
1195 m_assembler.loadConstant(address.offset, scr);
1196 m_assembler.addlRegReg(address.base, scr);
1197 m_assembler.movlMemReg(scr, SH4Registers::sp);
1198 m_assembler.addlImm8r(-4, SH4Registers::sp);
1199 releaseScratch(scr);
1203 m_assembler.movlMemReg(address.offset >> 2, address.base, SH4Registers::sp);
1204 m_assembler.addlImm8r(-4, SH4Registers::sp);
1207 void push(TrustedImm32 imm)
1209 RegisterID scr = claimScratch();
1210 m_assembler.loadConstant(imm.m_value, scr);
1212 releaseScratch(scr);
1215 // Register move operations
1217 void move(TrustedImm32 imm, RegisterID dest)
1219 m_assembler.loadConstant(imm.m_value, dest);
1222 DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
1224 m_assembler.ensureSpace(m_assembler.maxInstructionSize, sizeof(uint32_t));
1225 DataLabelPtr dataLabel(this);
1226 m_assembler.loadConstantUnReusable(reinterpret_cast<uint32_t>(initialValue.m_value), dest);
1230 void move(RegisterID src, RegisterID dest)
1232 m_assembler.movlRegReg(src, dest);
1235 void move(TrustedImmPtr imm, RegisterID dest)
1237 m_assembler.loadConstant(imm.asIntptr(), dest);
1240 void extuw(RegisterID src, RegisterID dst)
1242 m_assembler.extuw(src, dst);
1245 void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
1247 m_assembler.cmplRegReg(right, left, SH4Condition(cond));
1248 if (cond != NotEqual) {
1249 m_assembler.movt(dest);
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);
1259 void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
1263 compare32(cond, left, dest, dest);
1267 RegisterID scr = claimScratch();
1269 compare32(cond, left, scr, dest);
1270 releaseScratch(scr);
1273 void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
1275 ASSERT((cond == Zero) || (cond == NonZero));
1277 load8(address, dest);
1278 if (mask.m_value == -1)
1279 compare32(0, dest, static_cast<RelationalCondition>(cond));
1281 testlImm(mask.m_value, dest);
1282 if (cond != NonZero) {
1283 m_assembler.movt(dest);
1287 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
1288 m_assembler.movImm8(0, dest);
1289 m_assembler.branch(BT_OPCODE, 0);
1290 m_assembler.movImm8(1, dest);
1293 void loadPtrLinkReg(ImplicitAddress address)
1295 RegisterID scr = claimScratch();
1296 load32(address, scr);
1297 m_assembler.ldspr(scr);
1298 releaseScratch(scr);
1301 Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
1303 m_assembler.cmplRegReg(right, left, SH4Condition(cond));
1304 /* BT label => BF off
1309 if (cond == NotEqual)
1310 return branchFalse();
1311 return branchTrue();
1314 Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
1316 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1317 m_assembler.testlRegReg(left, left);
1319 compare32(right.m_value, left, cond);
1321 if (cond == NotEqual)
1322 return branchFalse();
1323 return branchTrue();
1326 Jump branch32(RelationalCondition cond, RegisterID left, Address right)
1328 compare32(right.offset, right.base, left, cond);
1329 if (cond == NotEqual)
1330 return branchFalse();
1331 return branchTrue();
1334 Jump branch32(RelationalCondition cond, Address left, RegisterID right)
1336 compare32(right, left.offset, left.base, cond);
1337 if (cond == NotEqual)
1338 return branchFalse();
1339 return branchTrue();
1342 Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
1344 compare32(right.m_value, left.offset, left.base, cond);
1345 if (cond == NotEqual)
1346 return branchFalse();
1347 return branchTrue();
1350 Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
1352 RegisterID scr = claimScratch();
1354 move(TrustedImm32(reinterpret_cast<uint32_t>(left.m_ptr)), scr);
1355 m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
1356 releaseScratch(scr);
1358 if (cond == NotEqual)
1359 return branchFalse();
1360 return branchTrue();
1363 Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
1365 RegisterID addressTempRegister = claimScratch();
1367 m_assembler.loadConstant(reinterpret_cast<uint32_t>(left.m_ptr), addressTempRegister);
1368 m_assembler.movlMemReg(addressTempRegister, addressTempRegister);
1369 compare32(right.m_value, addressTempRegister, cond);
1370 releaseScratch(addressTempRegister);
1372 if (cond == NotEqual)
1373 return branchFalse();
1374 return branchTrue();
1377 Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1379 ASSERT(!(right.m_value & 0xFFFFFF00));
1380 RegisterID scr = claimScratch();
1382 move(left.index, scr);
1383 lshift32(TrustedImm32(left.scale), scr);
1386 add32(TrustedImm32(left.offset), scr);
1387 add32(left.base, scr);
1389 m_assembler.extub(scr, scr);
1390 RegisterID scr1 = claimScratch();
1391 m_assembler.loadConstant(right.m_value, scr1);
1392 releaseScratch(scr);
1393 releaseScratch(scr1);
1395 return branch32(cond, scr, scr1);
1398 Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
1400 ASSERT((cond == Zero) || (cond == NonZero));
1402 m_assembler.testlRegReg(reg, mask);
1404 if (cond == NotEqual)
1405 return branchFalse();
1406 return branchTrue();
1409 Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
1411 ASSERT((cond == Zero) || (cond == NonZero));
1413 if (mask.m_value == -1)
1414 m_assembler.testlRegReg(reg, reg);
1416 testlImm(mask.m_value, reg);
1418 if (cond == NotEqual)
1419 return branchFalse();
1420 return branchTrue();
1423 Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1425 ASSERT((cond == Zero) || (cond == NonZero));
1427 if (mask.m_value == -1)
1428 compare32(0, address.offset, address.base, static_cast<RelationalCondition>(cond));
1430 testImm(mask.m_value, address.offset, address.base);
1432 if (cond == NotEqual)
1433 return branchFalse();
1434 return branchTrue();
1437 Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
1439 RegisterID scr = claimScratch();
1441 move(address.index, scr);
1442 lshift32(TrustedImm32(address.scale), scr);
1443 add32(address.base, scr);
1444 load32(scr, address.offset, scr);
1446 if (mask.m_value == -1)
1447 m_assembler.testlRegReg(scr, scr);
1449 testlImm(mask.m_value, scr);
1451 releaseScratch(scr);
1453 if (cond == NotEqual)
1454 return branchFalse();
1455 return branchTrue();
1460 return Jump(m_assembler.jmp());
1463 void jump(RegisterID target)
1465 m_assembler.jmpReg(target);
1468 void jump(Address address)
1470 RegisterID scr = claimScratch();
1472 if ((address.offset < 0) || (address.offset >= 64)) {
1473 m_assembler.loadConstant(address.offset, scr);
1474 m_assembler.addlRegReg(address.base, scr);
1475 m_assembler.movlMemReg(scr, scr);
1476 } else if (address.offset)
1477 m_assembler.movlMemReg(address.offset >> 2, address.base, scr);
1479 m_assembler.movlMemReg(address.base, scr);
1480 m_assembler.jmpReg(scr);
1482 releaseScratch(scr);
1485 // Arithmetic control flow operations
1487 Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
1489 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1491 if (cond == Overflow) {
1492 m_assembler.addvlRegReg(src, dest);
1493 return branchTrue();
1496 if (cond == Signed) {
1497 m_assembler.addlRegReg(src, dest);
1498 // Check if dest is negative
1499 m_assembler.cmppz(dest);
1500 return branchFalse();
1503 m_assembler.addlRegReg(src, dest);
1504 compare32(0, dest, Equal);
1506 if (cond == NotEqual)
1507 return branchFalse();
1508 return branchTrue();
1511 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
1513 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1515 move(imm, scratchReg3);
1516 return branchAdd32(cond, scratchReg3, dest);
1519 Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
1521 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1523 if (cond == Overflow) {
1524 RegisterID scr1 = claimScratch();
1525 RegisterID scr = claimScratch();
1526 m_assembler.dmullRegReg(src, dest);
1527 m_assembler.stsmacl(dest);
1528 m_assembler.movImm8(-31, scr);
1529 m_assembler.movlRegReg(dest, scr1);
1530 m_assembler.shaRegReg(scr1, scr);
1531 m_assembler.stsmach(scr);
1532 m_assembler.cmplRegReg(scr, scr1, SH4Condition(Equal));
1533 releaseScratch(scr1);
1534 releaseScratch(scr);
1535 return branchFalse();
1538 m_assembler.imullRegReg(src, dest);
1539 m_assembler.stsmacl(dest);
1540 if (cond == Signed) {
1541 // Check if dest is negative
1542 m_assembler.cmppz(dest);
1543 return branchFalse();
1546 compare32(0, dest, static_cast<RelationalCondition>(cond));
1548 if (cond == NotEqual)
1549 return branchFalse();
1550 return branchTrue();
1553 Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
1555 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1557 move(imm, scratchReg3);
1561 return branchMul32(cond, scratchReg3, dest);
1564 Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
1566 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1568 if (cond == Overflow) {
1569 m_assembler.subvlRegReg(src, dest);
1570 return branchTrue();
1573 if (cond == Signed) {
1574 // Check if dest is negative
1575 m_assembler.sublRegReg(src, dest);
1576 compare32(0, dest, LessThan);
1577 return branchTrue();
1581 compare32(0, dest, static_cast<RelationalCondition>(cond));
1583 if (cond == NotEqual)
1584 return branchFalse();
1585 return branchTrue();
1588 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
1590 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1592 move(imm, scratchReg3);
1593 return branchSub32(cond, scratchReg3, dest);
1596 Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
1598 ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
1600 if (cond == Signed) {
1602 compare32(0, dest, static_cast<RelationalCondition>(LessThan));
1603 return branchTrue();
1607 compare32(0, dest, static_cast<RelationalCondition>(cond));
1609 if (cond == NotEqual)
1610 return branchFalse();
1611 return branchTrue();
1614 void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
1616 m_assembler.ftrcdrmfpul(src);
1617 m_assembler.stsfpulReg(dest);
1618 convertInt32ToDouble(dest, fscratch);
1619 failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fscratch, src));
1621 if (dest == SH4Registers::r0)
1622 m_assembler.cmpEqImmR0(0, dest);
1624 m_assembler.movImm8(0, scratchReg3);
1625 m_assembler.cmplRegReg(scratchReg3, dest, SH4Condition(Equal));
1627 failureCases.append(branchTrue());
1630 void neg32(RegisterID dst)
1632 m_assembler.neg(dst, dst);
1635 void not32(RegisterID dst)
1637 m_assembler.notlReg(dst, dst);
1640 void urshift32(RegisterID shiftamount, RegisterID dest)
1642 compare32(32, shiftamount, Equal);
1643 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
1644 m_assembler.branch(BT_OPCODE, 1);
1645 m_assembler.neg(shiftamount, shiftamount);
1646 m_assembler.shllRegReg(dest, shiftamount);
1649 void urshift32(TrustedImm32 imm, RegisterID dest)
1651 RegisterID scr = claimScratch();
1652 m_assembler.loadConstant(-(imm.m_value), scr);
1653 m_assembler.shaRegReg(dest, scr);
1654 releaseScratch(scr);
1659 return Call(m_assembler.call(), Call::Linkable);
1664 return Call(m_assembler.call(), Call::LinkableNear);
1667 Call call(RegisterID target)
1669 return Call(m_assembler.call(target), Call::None);
1672 void call(Address address, RegisterID target)
1674 load32(address.base, address.offset, target);
1675 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 2);
1676 m_assembler.branch(JSR_OPCODE, target);
1686 Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
1688 RegisterID dataTempRegister = claimScratch();
1690 dataLabel = moveWithPatch(initialRightValue, dataTempRegister);
1691 m_assembler.cmplRegReg(dataTempRegister, left, SH4Condition(cond));
1692 releaseScratch(dataTempRegister);
1694 if (cond == NotEqual)
1695 return branchFalse();
1696 return branchTrue();
1699 Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
1701 RegisterID scr = claimScratch();
1703 m_assembler.loadConstant(left.offset, scr);
1704 m_assembler.addlRegReg(left.base, scr);
1705 m_assembler.movlMemReg(scr, scr);
1706 RegisterID scr1 = claimScratch();
1707 dataLabel = moveWithPatch(initialRightValue, scr1);
1708 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
1709 releaseScratch(scr);
1710 releaseScratch(scr1);
1712 if (cond == NotEqual)
1713 return branchFalse();
1714 return branchTrue();
1723 DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
1725 RegisterID scr = claimScratch();
1726 DataLabelPtr label = moveWithPatch(initialValue, scr);
1727 store32(scr, address);
1728 releaseScratch(scr);
1732 DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(TrustedImmPtr(0), address); }
1734 int sizeOfConstantPool()
1736 return m_assembler.sizeOfConstantPool();
1739 Call tailRecursiveCall()
1741 RegisterID scr = claimScratch();
1743 m_assembler.loadConstantUnReusable(0x0, scr, true);
1744 Jump m_jump = Jump(m_assembler.jmp(scr));
1745 releaseScratch(scr);
1747 return Call::fromTailJump(m_jump);
1750 Call makeTailRecursiveCall(Jump oldJump)
1753 return tailRecursiveCall();
1762 SH4Assembler::Condition SH4Condition(RelationalCondition cond)
1764 return static_cast<SH4Assembler::Condition>(cond);
1767 SH4Assembler::Condition SH4Condition(ResultCondition cond)
1769 return static_cast<SH4Assembler::Condition>(cond);
1772 friend class LinkBuffer;
1773 friend class RepatchBuffer;
1775 static void linkCall(void*, Call, FunctionPtr);
1776 static void repatchCall(CodeLocationCall, CodeLocationLabel);
1777 static void repatchCall(CodeLocationCall, FunctionPtr);
1782 #endif // ENABLE(ASSEMBLER)
1784 #endif // MacroAssemblerSH4_h