]> git.saurik.com Git - apple/javascriptcore.git/blame - assembler/MacroAssemblerSH4.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / assembler / MacroAssemblerSH4.h
CommitLineData
14957cd0 1/*
93a37866 2 * Copyright (C) 2013 Cisco Systems, Inc. All rights reserved.
14957cd0 3 * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved.
ed1e77d3 4 * Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
14957cd0
A
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28#ifndef MacroAssemblerSH4_h
29#define MacroAssemblerSH4_h
30
31#if ENABLE(ASSEMBLER) && CPU(SH4)
32
14957cd0 33#include "SH4Assembler.h"
6fe7ccc8 34#include "AbstractMacroAssembler.h"
14957cd0
A
35#include <wtf/Assertions.h>
36
37namespace JSC {
38
ed1e77d3 39class MacroAssemblerSH4 : public AbstractMacroAssembler<SH4Assembler, MacroAssemblerSH4> {
14957cd0
A
40public:
41 typedef SH4Assembler::FPRegisterID FPRegisterID;
42
43 static const Scale ScalePtr = TimesFour;
81345200 44 static const FPRegisterID fscratch = SH4Registers::dr10;
14957cd0 45 static const RegisterID stackPointerRegister = SH4Registers::sp;
81345200 46 static const RegisterID framePointerRegister = SH4Registers::fp;
14957cd0
A
47 static const RegisterID linkRegister = SH4Registers::pr;
48 static const RegisterID scratchReg3 = SH4Registers::r13;
49
6fe7ccc8 50 static const int MaximumCompactPtrAlignedAddressOffset = 60;
14957cd0 51
93a37866
A
52 static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value)
53 {
81345200 54 return (value >= 0) && (value <= MaximumCompactPtrAlignedAddressOffset) && (!(value & 3));
93a37866
A
55 }
56
14957cd0
A
57 enum RelationalCondition {
58 Equal = SH4Assembler::EQ,
59 NotEqual = SH4Assembler::NE,
60 Above = SH4Assembler::HI,
61 AboveOrEqual = SH4Assembler::HS,
62 Below = SH4Assembler::LI,
63 BelowOrEqual = SH4Assembler::LS,
64 GreaterThan = SH4Assembler::GT,
65 GreaterThanOrEqual = SH4Assembler::GE,
66 LessThan = SH4Assembler::LT,
67 LessThanOrEqual = SH4Assembler::LE
68 };
69
70 enum ResultCondition {
71 Overflow = SH4Assembler::OF,
72 Signed = SH4Assembler::SI,
93a37866 73 PositiveOrZero = SH4Assembler::NS,
14957cd0
A
74 Zero = SH4Assembler::EQ,
75 NonZero = SH4Assembler::NE
76 };
77
78 enum DoubleCondition {
79 // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
80 DoubleEqual = SH4Assembler::EQ,
81 DoubleNotEqual = SH4Assembler::NE,
82 DoubleGreaterThan = SH4Assembler::GT,
83 DoubleGreaterThanOrEqual = SH4Assembler::GE,
84 DoubleLessThan = SH4Assembler::LT,
85 DoubleLessThanOrEqual = SH4Assembler::LE,
86 // If either operand is NaN, these conditions always evaluate to true.
87 DoubleEqualOrUnordered = SH4Assembler::EQU,
88 DoubleNotEqualOrUnordered = SH4Assembler::NEU,
89 DoubleGreaterThanOrUnordered = SH4Assembler::GTU,
90 DoubleGreaterThanOrEqualOrUnordered = SH4Assembler::GEU,
91 DoubleLessThanOrUnordered = SH4Assembler::LTU,
92 DoubleLessThanOrEqualOrUnordered = SH4Assembler::LEU,
93 };
94
95 RegisterID claimScratch()
96 {
97 return m_assembler.claimScratch();
98 }
99
100 void releaseScratch(RegisterID reg)
101 {
102 m_assembler.releaseScratch(reg);
103 }
104
81345200
A
105 static RelationalCondition invert(RelationalCondition cond)
106 {
107 switch (cond) {
108 case Equal:
109 return NotEqual;
110 case NotEqual:
111 return Equal;
112 case Above:
113 return BelowOrEqual;
114 case AboveOrEqual:
115 return Below;
116 case Below:
117 return AboveOrEqual;
118 case BelowOrEqual:
119 return Above;
120 case GreaterThan:
121 return LessThanOrEqual;
122 case GreaterThanOrEqual:
123 return LessThan;
124 case LessThan:
125 return GreaterThanOrEqual;
126 case LessThanOrEqual:
127 return GreaterThan;
128 default:
129 RELEASE_ASSERT_NOT_REACHED();
130 }
131 }
132
14957cd0
A
133 // Integer arithmetic operations
134
135 void add32(RegisterID src, RegisterID dest)
136 {
137 m_assembler.addlRegReg(src, dest);
138 }
139
81345200
A
140 void add32(RegisterID src1, RegisterID src2, RegisterID dest)
141 {
142 if (src1 == dest)
143 add32(src2, dest);
144 else {
145 move(src2, dest);
146 add32(src1, dest);
147 }
148 }
149
14957cd0
A
150 void add32(TrustedImm32 imm, RegisterID dest)
151 {
93a37866
A
152 if (!imm.m_value)
153 return;
154
14957cd0
A
155 if (m_assembler.isImmediate(imm.m_value)) {
156 m_assembler.addlImm8r(imm.m_value, dest);
157 return;
158 }
159
160 RegisterID scr = claimScratch();
161 m_assembler.loadConstant(imm.m_value, scr);
162 m_assembler.addlRegReg(scr, dest);
163 releaseScratch(scr);
164 }
165
166 void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
167 {
81345200 168 move(src, dest);
14957cd0
A
169 add32(imm, dest);
170 }
171
172 void add32(TrustedImm32 imm, Address address)
173 {
93a37866
A
174 if (!imm.m_value)
175 return;
176
14957cd0
A
177 RegisterID scr = claimScratch();
178 load32(address, scr);
179 add32(imm, scr);
180 store32(scr, address);
181 releaseScratch(scr);
182 }
183
184 void add32(Address src, RegisterID dest)
185 {
186 RegisterID scr = claimScratch();
187 load32(src, scr);
188 m_assembler.addlRegReg(scr, dest);
189 releaseScratch(scr);
190 }
191
93a37866
A
192 void add32(AbsoluteAddress src, RegisterID dest)
193 {
194 RegisterID scr = claimScratch();
195 load32(src.m_ptr, scr);
196 m_assembler.addlRegReg(scr, dest);
197 releaseScratch(scr);
198 }
199
14957cd0
A
200 void and32(RegisterID src, RegisterID dest)
201 {
202 m_assembler.andlRegReg(src, dest);
203 }
204
81345200
A
205 void and32(RegisterID src1, RegisterID src2, RegisterID dest)
206 {
207 if (src1 == dest)
208 and32(src2, dest);
209 else {
210 move(src2, dest);
211 and32(src1, dest);
212 }
213 }
214
215 void and32(Address src, RegisterID dest)
216 {
217 RegisterID scr = claimScratch();
218 load32(src, scr);
219 and32(scr, dest);
220 releaseScratch(scr);
221 }
222
14957cd0
A
223 void and32(TrustedImm32 imm, RegisterID dest)
224 {
81345200
A
225 if (!imm.m_value) {
226 m_assembler.movImm8(0, dest);
227 return;
228 }
229
14957cd0
A
230 if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) {
231 m_assembler.andlImm8r(imm.m_value, dest);
232 return;
233 }
234
235 RegisterID scr = claimScratch();
93a37866 236 m_assembler.loadConstant(imm.m_value, scr);
14957cd0
A
237 m_assembler.andlRegReg(scr, dest);
238 releaseScratch(scr);
239 }
240
6fe7ccc8
A
241 void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
242 {
243 if (src != dest) {
244 move(imm, dest);
245 and32(src, dest);
246 return;
247 }
248
249 and32(imm, dest);
250 }
251
14957cd0
A
252 void lshift32(RegisterID shiftamount, RegisterID dest)
253 {
93a37866
A
254 RegisterID shiftTmp = claimScratch();
255 m_assembler.loadConstant(0x1f, shiftTmp);
256 m_assembler.andlRegReg(shiftamount, shiftTmp);
257 m_assembler.shldRegReg(dest, shiftTmp);
258 releaseScratch(shiftTmp);
14957cd0
A
259 }
260
81345200
A
261 void lshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
262 {
263 move(src, dest);
264 lshift32(shiftAmount, dest);
265 }
266
14957cd0
A
267 void lshift32(TrustedImm32 imm, RegisterID dest)
268 {
93a37866
A
269 int immMasked = imm.m_value & 0x1f;
270 if (!immMasked)
6fe7ccc8
A
271 return;
272
93a37866
A
273 if ((immMasked == 1) || (immMasked == 2) || (immMasked == 8) || (immMasked == 16)) {
274 m_assembler.shllImm8r(immMasked, dest);
14957cd0
A
275 return;
276 }
277
93a37866
A
278 RegisterID shiftTmp = claimScratch();
279 m_assembler.loadConstant(immMasked, shiftTmp);
280 m_assembler.shldRegReg(dest, shiftTmp);
281 releaseScratch(shiftTmp);
14957cd0
A
282 }
283
6fe7ccc8
A
284 void lshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest)
285 {
81345200 286 move(src, dest);
6fe7ccc8
A
287 lshift32(shiftamount, dest);
288 }
289
14957cd0
A
290 void mul32(RegisterID src, RegisterID dest)
291 {
81345200
A
292 mul32(src, dest, dest);
293 }
294
295 void mul32(RegisterID src1, RegisterID src2, RegisterID dest)
296 {
297 m_assembler.imullRegReg(src1, src2);
14957cd0
A
298 m_assembler.stsmacl(dest);
299 }
300
301 void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
302 {
81345200
A
303 if (src == dest) {
304 RegisterID immval = claimScratch();
305 move(imm, immval);
306 mul32(immval, dest);
307 releaseScratch(immval);
308 } else {
309 move(imm, dest);
310 mul32(src, dest);
311 }
14957cd0
A
312 }
313
14957cd0
A
314 void or32(RegisterID src, RegisterID dest)
315 {
316 m_assembler.orlRegReg(src, dest);
317 }
318
319 void or32(TrustedImm32 imm, RegisterID dest)
320 {
321 if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) {
322 m_assembler.orlImm8r(imm.m_value, dest);
323 return;
324 }
325
326 RegisterID scr = claimScratch();
327 m_assembler.loadConstant(imm.m_value, scr);
328 m_assembler.orlRegReg(scr, dest);
329 releaseScratch(scr);
330 }
331
6fe7ccc8
A
332 void or32(RegisterID op1, RegisterID op2, RegisterID dest)
333 {
334 if (op1 == op2)
335 move(op1, dest);
336 else if (op1 == dest)
337 or32(op2, dest);
338 else {
339 move(op2, dest);
340 or32(op1, dest);
341 }
342 }
343
93a37866 344 void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
6fe7ccc8 345 {
93a37866 346 if (src != dest) {
6fe7ccc8
A
347 move(imm, dest);
348 or32(src, dest);
349 return;
350 }
351
352 or32(imm, dest);
353 }
354
81345200
A
355 void or32(RegisterID src, AbsoluteAddress address)
356 {
357 RegisterID destptr = claimScratch();
358 move(TrustedImmPtr(address.m_ptr), destptr);
359 RegisterID destval = claimScratch();
360 m_assembler.movlMemReg(destptr, destval);
361 m_assembler.orlRegReg(src, destval);
362 m_assembler.movlRegMem(destval, destptr);
363 releaseScratch(destval);
364 releaseScratch(destptr);
365 }
366
6fe7ccc8
A
367 void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
368 {
93a37866 369 if (src != dest) {
6fe7ccc8
A
370 move(imm, dest);
371 xor32(src, dest);
372 return;
373 }
374
375 xor32(imm, dest);
376 }
377
14957cd0
A
378 void rshift32(RegisterID shiftamount, RegisterID dest)
379 {
93a37866
A
380 RegisterID shiftTmp = claimScratch();
381 m_assembler.loadConstant(0x1f, shiftTmp);
382 m_assembler.andlRegReg(shiftamount, shiftTmp);
383 m_assembler.neg(shiftTmp, shiftTmp);
384 m_assembler.shadRegReg(dest, shiftTmp);
385 releaseScratch(shiftTmp);
14957cd0
A
386 }
387
81345200
A
388 void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
389 {
390 move(src, dest);
391 rshift32(shiftAmount, dest);
392 }
393
14957cd0
A
394 void rshift32(TrustedImm32 imm, RegisterID dest)
395 {
93a37866
A
396 int immMasked = imm.m_value & 0x1f;
397 if (!immMasked)
398 return;
399
400 if (immMasked == 1) {
401 m_assembler.sharImm8r(immMasked, dest);
402 return;
403 }
404
405 RegisterID shiftTmp = claimScratch();
406 m_assembler.loadConstant(-immMasked, shiftTmp);
407 m_assembler.shadRegReg(dest, shiftTmp);
408 releaseScratch(shiftTmp);
14957cd0
A
409 }
410
6fe7ccc8
A
411 void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
412 {
81345200 413 move(src, dest);
6fe7ccc8
A
414 rshift32(imm, dest);
415 }
416
14957cd0
A
417 void sub32(RegisterID src, RegisterID dest)
418 {
419 m_assembler.sublRegReg(src, dest);
420 }
421
14957cd0
A
422 void sub32(TrustedImm32 imm, AbsoluteAddress address)
423 {
93a37866
A
424 if (!imm.m_value)
425 return;
426
14957cd0
A
427 RegisterID result = claimScratch();
428 RegisterID scratchReg = claimScratch();
429
81345200 430 move(TrustedImmPtr(address.m_ptr), scratchReg);
14957cd0
A
431 m_assembler.movlMemReg(scratchReg, result);
432
433 if (m_assembler.isImmediate(-imm.m_value))
434 m_assembler.addlImm8r(-imm.m_value, result);
435 else {
436 m_assembler.loadConstant(imm.m_value, scratchReg3);
437 m_assembler.sublRegReg(scratchReg3, result);
438 }
439
440 store32(result, scratchReg);
441 releaseScratch(result);
442 releaseScratch(scratchReg);
443 }
444
81345200
A
445 void sub32(TrustedImm32 imm, Address address)
446 {
447 add32(TrustedImm32(-imm.m_value), address);
448 }
449
14957cd0
A
450 void add32(TrustedImm32 imm, AbsoluteAddress address)
451 {
93a37866
A
452 if (!imm.m_value)
453 return;
454
14957cd0
A
455 RegisterID result = claimScratch();
456 RegisterID scratchReg = claimScratch();
457
81345200 458 move(TrustedImmPtr(address.m_ptr), scratchReg);
14957cd0
A
459 m_assembler.movlMemReg(scratchReg, result);
460
461 if (m_assembler.isImmediate(imm.m_value))
462 m_assembler.addlImm8r(imm.m_value, result);
463 else {
464 m_assembler.loadConstant(imm.m_value, scratchReg3);
465 m_assembler.addlRegReg(scratchReg3, result);
466 }
467
468 store32(result, scratchReg);
469 releaseScratch(result);
470 releaseScratch(scratchReg);
471 }
472
93a37866
A
473 void add64(TrustedImm32 imm, AbsoluteAddress address)
474 {
475 RegisterID scr1 = claimScratch();
476 RegisterID scr2 = claimScratch();
477
478 // Add 32-bit LSB first.
81345200
A
479 move(TrustedImmPtr(address.m_ptr), scratchReg3);
480 m_assembler.movlMemReg(scratchReg3, scr1); // scr1 = 32-bit LSB of int64 @ address
93a37866
A
481 m_assembler.loadConstant(imm.m_value, scr2);
482 m_assembler.clrt();
483 m_assembler.addclRegReg(scr1, scr2);
81345200 484 m_assembler.movlRegMem(scr2, scratchReg3); // Update address with 32-bit LSB result.
93a37866
A
485
486 // Then add 32-bit MSB.
81345200
A
487 m_assembler.addlImm8r(4, scratchReg3);
488 m_assembler.movlMemReg(scratchReg3, scr1); // scr1 = 32-bit MSB of int64 @ address
93a37866
A
489 m_assembler.movt(scr2);
490 if (imm.m_value < 0)
491 m_assembler.addlImm8r(-1, scr2); // Sign extend imm value if needed.
492 m_assembler.addvlRegReg(scr2, scr1);
81345200 493 m_assembler.movlRegMem(scr1, scratchReg3); // Update (address + 4) with 32-bit MSB result.
93a37866
A
494
495 releaseScratch(scr2);
496 releaseScratch(scr1);
497 }
498
14957cd0
A
499 void sub32(TrustedImm32 imm, RegisterID dest)
500 {
93a37866
A
501 if (!imm.m_value)
502 return;
503
14957cd0
A
504 if (m_assembler.isImmediate(-imm.m_value)) {
505 m_assembler.addlImm8r(-imm.m_value, dest);
506 return;
507 }
508
509 RegisterID scr = claimScratch();
510 m_assembler.loadConstant(imm.m_value, scr);
511 m_assembler.sublRegReg(scr, dest);
512 releaseScratch(scr);
513 }
514
515 void sub32(Address src, RegisterID dest)
516 {
517 RegisterID scr = claimScratch();
518 load32(src, scr);
519 m_assembler.sublRegReg(scr, dest);
520 releaseScratch(scr);
521 }
522
523 void xor32(RegisterID src, RegisterID dest)
524 {
525 m_assembler.xorlRegReg(src, dest);
526 }
527
81345200
A
528 void xor32(RegisterID src1, RegisterID src2, RegisterID dest)
529 {
530 if (src1 == dest)
531 xor32(src2, dest);
532 else {
533 move(src2, dest);
534 xor32(src1, dest);
535 }
536 }
537
14957cd0
A
538 void xor32(TrustedImm32 imm, RegisterID srcDest)
539 {
6fe7ccc8
A
540 if (imm.m_value == -1) {
541 m_assembler.notlReg(srcDest, srcDest);
542 return;
543 }
544
14957cd0
A
545 if ((srcDest != SH4Registers::r0) || (imm.m_value > 255) || (imm.m_value < 0)) {
546 RegisterID scr = claimScratch();
93a37866 547 m_assembler.loadConstant(imm.m_value, scr);
14957cd0
A
548 m_assembler.xorlRegReg(scr, srcDest);
549 releaseScratch(scr);
550 return;
551 }
552
553 m_assembler.xorlImm8r(imm.m_value, srcDest);
554 }
555
556 void compare32(int imm, RegisterID dst, RelationalCondition cond)
557 {
558 if (((cond == Equal) || (cond == NotEqual)) && (dst == SH4Registers::r0) && m_assembler.isImmediate(imm)) {
559 m_assembler.cmpEqImmR0(imm, dst);
560 return;
561 }
562
81345200
A
563 if (((cond == Equal) || (cond == NotEqual)) && !imm) {
564 m_assembler.testlRegReg(dst, dst);
565 return;
566 }
567
14957cd0
A
568 RegisterID scr = claimScratch();
569 m_assembler.loadConstant(imm, scr);
570 m_assembler.cmplRegReg(scr, dst, SH4Condition(cond));
571 releaseScratch(scr);
572 }
573
574 void compare32(int offset, RegisterID base, RegisterID left, RelationalCondition cond)
575 {
576 RegisterID scr = claimScratch();
577 if (!offset) {
578 m_assembler.movlMemReg(base, scr);
579 m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
580 releaseScratch(scr);
581 return;
582 }
583
584 if ((offset < 0) || (offset >= 64)) {
585 m_assembler.loadConstant(offset, scr);
586 m_assembler.addlRegReg(base, scr);
587 m_assembler.movlMemReg(scr, scr);
588 m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
589 releaseScratch(scr);
590 return;
591 }
592
593 m_assembler.movlMemReg(offset >> 2, base, scr);
594 m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
595 releaseScratch(scr);
596 }
597
598 void testImm(int imm, int offset, RegisterID base)
599 {
600 RegisterID scr = claimScratch();
81345200 601 load32(base, offset, scr);
14957cd0 602
81345200
A
603 RegisterID scr1 = claimScratch();
604 move(TrustedImm32(imm), scr1);
14957cd0
A
605
606 m_assembler.testlRegReg(scr, scr1);
607 releaseScratch(scr);
608 releaseScratch(scr1);
609 }
610
611 void testlImm(int imm, RegisterID dst)
612 {
613 if ((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0)) {
614 m_assembler.testlImm8r(imm, dst);
615 return;
616 }
617
618 RegisterID scr = claimScratch();
619 m_assembler.loadConstant(imm, scr);
620 m_assembler.testlRegReg(scr, dst);
621 releaseScratch(scr);
622 }
623
624 void compare32(RegisterID right, int offset, RegisterID base, RelationalCondition cond)
625 {
626 if (!offset) {
627 RegisterID scr = claimScratch();
628 m_assembler.movlMemReg(base, scr);
629 m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
630 releaseScratch(scr);
631 return;
632 }
633
634 if ((offset < 0) || (offset >= 64)) {
635 RegisterID scr = claimScratch();
636 m_assembler.loadConstant(offset, scr);
637 m_assembler.addlRegReg(base, scr);
638 m_assembler.movlMemReg(scr, scr);
639 m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
640 releaseScratch(scr);
641 return;
642 }
643
644 RegisterID scr = claimScratch();
645 m_assembler.movlMemReg(offset >> 2, base, scr);
646 m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
647 releaseScratch(scr);
648 }
649
650 void compare32(int imm, int offset, RegisterID base, RelationalCondition cond)
651 {
14957cd0 652 RegisterID scr = claimScratch();
81345200
A
653 load32(base, offset, scr);
654
14957cd0 655 RegisterID scr1 = claimScratch();
81345200
A
656 move(TrustedImm32(imm), scr1);
657
14957cd0 658 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
81345200 659
14957cd0
A
660 releaseScratch(scr1);
661 releaseScratch(scr);
662 }
663
664 // Memory access operation
665
81345200
A
666 ALWAYS_INLINE void loadEffectiveAddress(BaseIndex address, RegisterID dest, int extraoffset = 0)
667 {
668 if (dest == address.base) {
669 RegisterID scaledIndex = claimScratch();
670 move(address.index, scaledIndex);
671 lshift32(TrustedImm32(address.scale), scaledIndex);
672 add32(scaledIndex, dest);
673 releaseScratch(scaledIndex);
674 } else {
675 move(address.index, dest);
676 lshift32(TrustedImm32(address.scale), dest);
677 add32(address.base, dest);
678 }
679
680 add32(TrustedImm32(address.offset + extraoffset), dest);
681 }
682
14957cd0
A
683 void load32(ImplicitAddress address, RegisterID dest)
684 {
685 load32(address.base, address.offset, dest);
686 }
687
688 void load8(ImplicitAddress address, RegisterID dest)
689 {
690 load8(address.base, address.offset, dest);
691 }
692
6fe7ccc8
A
693 void load8(BaseIndex address, RegisterID dest)
694 {
695 RegisterID scr = claimScratch();
696 move(address.index, scr);
697 lshift32(TrustedImm32(address.scale), scr);
698 add32(address.base, scr);
699 load8(scr, address.offset, dest);
700 releaseScratch(scr);
701 }
702
81345200
A
703 void load8(AbsoluteAddress address, RegisterID dest)
704 {
705 move(TrustedImmPtr(address.m_ptr), dest);
706 m_assembler.movbMemReg(dest, dest);
707 m_assembler.extub(dest, dest);
708 }
709
710 void load8(const void* address, RegisterID dest)
711 {
712 load8(AbsoluteAddress(address), dest);
713 }
714
93a37866
A
715 void load8PostInc(RegisterID base, RegisterID dest)
716 {
717 m_assembler.movbMemRegIn(base, dest);
718 m_assembler.extub(dest, dest);
719 }
720
ed1e77d3 721 void load8SignedExtendTo32(BaseIndex address, RegisterID dest)
93a37866
A
722 {
723 RegisterID scr = claimScratch();
724 move(address.index, scr);
725 lshift32(TrustedImm32(address.scale), scr);
726 add32(address.base, scr);
ed1e77d3 727 load8SignedExtendTo32(scr, address.offset, dest);
93a37866
A
728 releaseScratch(scr);
729 }
730
14957cd0
A
731 void load32(BaseIndex address, RegisterID dest)
732 {
733 RegisterID scr = claimScratch();
734 move(address.index, scr);
735 lshift32(TrustedImm32(address.scale), scr);
736 add32(address.base, scr);
737 load32(scr, address.offset, dest);
738 releaseScratch(scr);
739 }
740
6fe7ccc8 741 void load32(const void* address, RegisterID dest)
14957cd0 742 {
81345200 743 move(TrustedImmPtr(address), dest);
14957cd0
A
744 m_assembler.movlMemReg(dest, dest);
745 }
746
747 void load32(RegisterID base, int offset, RegisterID dest)
748 {
749 if (!offset) {
750 m_assembler.movlMemReg(base, dest);
751 return;
752 }
753
754 if ((offset >= 0) && (offset < 64)) {
755 m_assembler.movlMemReg(offset >> 2, base, dest);
756 return;
757 }
758
93a37866 759 RegisterID scr = (dest == base) ? claimScratch() : dest;
14957cd0 760
93a37866
A
761 m_assembler.loadConstant(offset, scr);
762 if (base == SH4Registers::r0)
763 m_assembler.movlR0mr(scr, dest);
764 else {
765 m_assembler.addlRegReg(base, scr);
766 m_assembler.movlMemReg(scr, dest);
767 }
14957cd0
A
768
769 if (dest == base)
770 releaseScratch(scr);
771 }
772
ed1e77d3 773 void load8SignedExtendTo32(RegisterID base, int offset, RegisterID dest)
14957cd0
A
774 {
775 if (!offset) {
776 m_assembler.movbMemReg(base, dest);
777 return;
778 }
779
93a37866 780 if ((offset > 0) && (offset <= 15) && (dest == SH4Registers::r0)) {
14957cd0
A
781 m_assembler.movbMemReg(offset, base, dest);
782 return;
783 }
784
93a37866
A
785 RegisterID scr = (dest == base) ? claimScratch() : dest;
786
787 m_assembler.loadConstant(offset, scr);
788 if (base == SH4Registers::r0)
789 m_assembler.movbR0mr(scr, dest);
790 else {
791 m_assembler.addlRegReg(base, scr);
792 m_assembler.movbMemReg(scr, dest);
14957cd0
A
793 }
794
93a37866
A
795 if (dest == base)
796 releaseScratch(scr);
14957cd0
A
797 }
798
93a37866 799 void load8(RegisterID base, int offset, RegisterID dest)
14957cd0 800 {
ed1e77d3 801 load8SignedExtendTo32(base, offset, dest);
93a37866 802 m_assembler.extub(dest, dest);
14957cd0
A
803 }
804
805 void load32(RegisterID src, RegisterID dst)
806 {
807 m_assembler.movlMemReg(src, dst);
808 }
809
810 void load16(ImplicitAddress address, RegisterID dest)
811 {
812 if (!address.offset) {
813 m_assembler.movwMemReg(address.base, dest);
93a37866 814 m_assembler.extuw(dest, dest);
14957cd0
A
815 return;
816 }
817
93a37866
A
818 if ((address.offset > 0) && (address.offset <= 30) && (dest == SH4Registers::r0)) {
819 m_assembler.movwMemReg(address.offset >> 1, address.base, dest);
820 m_assembler.extuw(dest, dest);
14957cd0
A
821 return;
822 }
823
93a37866
A
824 RegisterID scr = (dest == address.base) ? claimScratch() : dest;
825
826 m_assembler.loadConstant(address.offset, scr);
827 if (address.base == SH4Registers::r0)
828 m_assembler.movwR0mr(scr, dest);
829 else {
830 m_assembler.addlRegReg(address.base, scr);
831 m_assembler.movwMemReg(scr, dest);
14957cd0 832 }
93a37866 833 m_assembler.extuw(dest, dest);
14957cd0 834
93a37866
A
835 if (dest == address.base)
836 releaseScratch(scr);
14957cd0
A
837 }
838
6fe7ccc8
A
839 void load16Unaligned(BaseIndex address, RegisterID dest)
840 {
6fe7ccc8 841 RegisterID scr = claimScratch();
6fe7ccc8 842
81345200 843 loadEffectiveAddress(address, scr);
6fe7ccc8 844
81345200 845 RegisterID scr1 = claimScratch();
93a37866 846 load8PostInc(scr, scr1);
6fe7ccc8
A
847 load8(scr, dest);
848 m_assembler.shllImm8r(8, dest);
849 or32(scr1, dest);
850
851 releaseScratch(scr);
852 releaseScratch(scr1);
853 }
854
14957cd0
A
855 void load16(RegisterID src, RegisterID dest)
856 {
857 m_assembler.movwMemReg(src, dest);
93a37866 858 m_assembler.extuw(dest, dest);
14957cd0
A
859 }
860
ed1e77d3 861 void load16SignedExtendTo32(RegisterID src, RegisterID dest)
14957cd0 862 {
93a37866 863 m_assembler.movwMemReg(src, dest);
14957cd0
A
864 }
865
866 void load16(BaseIndex address, RegisterID dest)
93a37866 867 {
ed1e77d3 868 load16SignedExtendTo32(address, dest);
93a37866
A
869 m_assembler.extuw(dest, dest);
870 }
871
872 void load16PostInc(RegisterID base, RegisterID dest)
873 {
874 m_assembler.movwMemRegIn(base, dest);
875 m_assembler.extuw(dest, dest);
876 }
877
ed1e77d3 878 void load16SignedExtendTo32(BaseIndex address, RegisterID dest)
14957cd0
A
879 {
880 RegisterID scr = claimScratch();
881
882 move(address.index, scr);
883 lshift32(TrustedImm32(address.scale), scr);
81345200 884 add32(TrustedImm32(address.offset), scr);
93a37866 885
6fe7ccc8 886 if (address.base == SH4Registers::r0)
93a37866 887 m_assembler.movwR0mr(scr, dest);
14957cd0
A
888 else {
889 add32(address.base, scr);
ed1e77d3 890 load16SignedExtendTo32(scr, dest);
14957cd0
A
891 }
892
14957cd0
A
893 releaseScratch(scr);
894 }
895
93a37866 896 void store8(RegisterID src, BaseIndex address)
14957cd0
A
897 {
898 RegisterID scr = claimScratch();
93a37866
A
899
900 move(address.index, scr);
901 lshift32(TrustedImm32(address.scale), scr);
902 add32(TrustedImm32(address.offset), scr);
903
904 if (address.base == SH4Registers::r0)
905 m_assembler.movbRegMemr0(src, scr);
906 else {
907 add32(address.base, scr);
908 m_assembler.movbRegMem(src, scr);
909 }
910
14957cd0
A
911 releaseScratch(scr);
912 }
913
81345200
A
914 void store8(RegisterID src, void* address)
915 {
916 RegisterID destptr = claimScratch();
917 move(TrustedImmPtr(address), destptr);
918 m_assembler.movbRegMem(src, destptr);
919 releaseScratch(destptr);
920 }
921
922 void store8(TrustedImm32 imm, void* address)
923 {
924 ASSERT((imm.m_value >= -128) && (imm.m_value <= 127));
925 RegisterID dstptr = claimScratch();
926 move(TrustedImmPtr(address), dstptr);
927 RegisterID srcval = claimScratch();
928 move(imm, srcval);
929 m_assembler.movbRegMem(srcval, dstptr);
930 releaseScratch(dstptr);
931 releaseScratch(srcval);
932 }
933
ed1e77d3
A
934 void store8(TrustedImm32 imm, Address address)
935 {
936 ASSERT((imm.m_value >= -128) && (imm.m_value <= 127));
937 RegisterID dstptr = claimScratch();
938 move(address.base, dstptr);
939 add32(TrustedImm32(address.offset), dstptr);
940 RegisterID srcval = claimScratch();
941 move(imm, srcval);
942 m_assembler.movbRegMem(srcval, dstptr);
943 releaseScratch(dstptr);
944 releaseScratch(srcval);
945 }
946
93a37866 947 void store16(RegisterID src, BaseIndex address)
14957cd0 948 {
93a37866
A
949 RegisterID scr = claimScratch();
950
951 move(address.index, scr);
952 lshift32(TrustedImm32(address.scale), scr);
953 add32(TrustedImm32(address.offset), scr);
954
955 if (address.base == SH4Registers::r0)
956 m_assembler.movwRegMemr0(src, scr);
957 else {
958 add32(address.base, scr);
959 m_assembler.movwRegMem(src, scr);
14957cd0
A
960 }
961
93a37866
A
962 releaseScratch(scr);
963 }
964
965 void store32(RegisterID src, ImplicitAddress address)
966 {
967 if (!address.offset) {
968 m_assembler.movlRegMem(src, address.base);
14957cd0
A
969 return;
970 }
971
93a37866
A
972 if ((address.offset >= 0) && (address.offset < 64)) {
973 m_assembler.movlRegMem(src, address.offset >> 2, address.base);
14957cd0
A
974 return;
975 }
976
93a37866
A
977 RegisterID scr = claimScratch();
978 m_assembler.loadConstant(address.offset, scr);
979 if (address.base == SH4Registers::r0)
980 m_assembler.movlRegMemr0(src, scr);
981 else {
982 m_assembler.addlRegReg(address.base, scr);
983 m_assembler.movlRegMem(src, scr);
984 }
985 releaseScratch(scr);
14957cd0
A
986 }
987
988 void store32(RegisterID src, RegisterID dst)
989 {
990 m_assembler.movlRegMem(src, dst);
991 }
992
993 void store32(TrustedImm32 imm, ImplicitAddress address)
994 {
995 RegisterID scr = claimScratch();
93a37866
A
996 m_assembler.loadConstant(imm.m_value, scr);
997 store32(scr, address);
14957cd0 998 releaseScratch(scr);
14957cd0
A
999 }
1000
1001 void store32(RegisterID src, BaseIndex address)
1002 {
1003 RegisterID scr = claimScratch();
1004
1005 move(address.index, scr);
1006 lshift32(TrustedImm32(address.scale), scr);
1007 add32(address.base, scr);
1008 store32(src, Address(scr, address.offset));
1009
1010 releaseScratch(scr);
1011 }
1012
1013 void store32(TrustedImm32 imm, void* address)
1014 {
1015 RegisterID scr = claimScratch();
1016 RegisterID scr1 = claimScratch();
93a37866 1017 m_assembler.loadConstant(imm.m_value, scr);
81345200 1018 move(TrustedImmPtr(address), scr1);
6fe7ccc8 1019 m_assembler.movlRegMem(scr, scr1);
14957cd0
A
1020 releaseScratch(scr);
1021 releaseScratch(scr1);
1022 }
1023
1024 void store32(RegisterID src, void* address)
1025 {
1026 RegisterID scr = claimScratch();
81345200 1027 move(TrustedImmPtr(address), scr);
6fe7ccc8 1028 m_assembler.movlRegMem(src, scr);
14957cd0
A
1029 releaseScratch(scr);
1030 }
1031
81345200
A
1032 void store32(TrustedImm32 imm, BaseIndex address)
1033 {
1034 RegisterID destptr = claimScratch();
1035
1036 loadEffectiveAddress(address, destptr);
1037
1038 RegisterID srcval = claimScratch();
1039 move(imm, srcval);
1040 m_assembler.movlRegMem(srcval, destptr);
1041 releaseScratch(srcval);
1042 releaseScratch(destptr);
1043 }
1044
14957cd0
A
1045 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
1046 {
1047 RegisterID scr = claimScratch();
1048 DataLabel32 label(this);
1049 m_assembler.loadConstantUnReusable(address.offset, scr);
1050 m_assembler.addlRegReg(address.base, scr);
1051 m_assembler.movlMemReg(scr, dest);
1052 releaseScratch(scr);
1053 return label;
1054 }
1055
14957cd0
A
1056 DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
1057 {
1058 RegisterID scr = claimScratch();
1059 DataLabel32 label(this);
1060 m_assembler.loadConstantUnReusable(address.offset, scr);
1061 m_assembler.addlRegReg(address.base, scr);
1062 m_assembler.movlRegMem(src, scr);
1063 releaseScratch(scr);
1064 return label;
1065 }
1066
6fe7ccc8
A
1067 DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
1068 {
1069 DataLabelCompact dataLabel(this);
81345200 1070 ASSERT(isCompactPtrAlignedAddressOffset(address.offset));
6fe7ccc8
A
1071 m_assembler.movlMemRegCompact(address.offset >> 2, address.base, dest);
1072 return dataLabel;
1073 }
1074
93a37866
A
1075 ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest)
1076 {
1077 ConvertibleLoadLabel result(this);
1078
1079 RegisterID scr = claimScratch();
1080 m_assembler.movImm8(address.offset, scr);
1081 m_assembler.addlRegReg(address.base, scr);
1082 m_assembler.movlMemReg(scr, dest);
1083 releaseScratch(scr);
1084
1085 return result;
1086 }
1087
1088 // Floating-point operations
14957cd0 1089
6fe7ccc8
A
1090 static bool supportsFloatingPoint() { return true; }
1091 static bool supportsFloatingPointTruncate() { return true; }
1092 static bool supportsFloatingPointSqrt() { return true; }
93a37866
A
1093 static bool supportsFloatingPointAbs() { return true; }
1094
1095 void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2)
1096 {
1097 m_assembler.fldsfpul((FPRegisterID)(src + 1));
1098 m_assembler.stsfpulReg(dest1);
1099 m_assembler.fldsfpul(src);
1100 m_assembler.stsfpulReg(dest2);
1101 }
1102
81345200 1103 void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID)
93a37866 1104 {
93a37866
A
1105 m_assembler.ldsrmfpul(src1);
1106 m_assembler.fstsfpul((FPRegisterID)(dest + 1));
1107 m_assembler.ldsrmfpul(src2);
1108 m_assembler.fstsfpul(dest);
1109 }
1110
1111 void moveDouble(FPRegisterID src, FPRegisterID dest)
1112 {
1113 if (src != dest) {
1114 m_assembler.fmovsRegReg((FPRegisterID)(src + 1), (FPRegisterID)(dest + 1));
1115 m_assembler.fmovsRegReg(src, dest);
1116 }
1117 }
1118
81345200
A
1119 void swapDouble(FPRegisterID fr1, FPRegisterID fr2)
1120 {
1121 if (fr1 != fr2) {
1122 m_assembler.fldsfpul((FPRegisterID)(fr1 + 1));
1123 m_assembler.fmovsRegReg((FPRegisterID)(fr2 + 1), (FPRegisterID)(fr1 + 1));
1124 m_assembler.fstsfpul((FPRegisterID)(fr2 + 1));
1125 m_assembler.fldsfpul(fr1);
1126 m_assembler.fmovsRegReg(fr2, fr1);
1127 m_assembler.fstsfpul(fr2);
1128 }
1129 }
1130
93a37866
A
1131 void loadFloat(BaseIndex address, FPRegisterID dest)
1132 {
1133 RegisterID scr = claimScratch();
1134
81345200 1135 loadEffectiveAddress(address, scr);
93a37866
A
1136
1137 m_assembler.fmovsReadrm(scr, dest);
1138 releaseScratch(scr);
1139 }
1140
1141 void loadDouble(BaseIndex address, FPRegisterID dest)
1142 {
1143 RegisterID scr = claimScratch();
1144
81345200 1145 loadEffectiveAddress(address, scr);
93a37866
A
1146
1147 m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
1148 m_assembler.fmovsReadrm(scr, dest);
1149 releaseScratch(scr);
1150 }
14957cd0
A
1151
1152 void loadDouble(ImplicitAddress address, FPRegisterID dest)
1153 {
1154 RegisterID scr = claimScratch();
1155
1156 m_assembler.loadConstant(address.offset, scr);
1157 if (address.base == SH4Registers::r0) {
1158 m_assembler.fmovsReadr0r(scr, (FPRegisterID)(dest + 1));
1159 m_assembler.addlImm8r(4, scr);
1160 m_assembler.fmovsReadr0r(scr, dest);
1161 releaseScratch(scr);
1162 return;
1163 }
1164
1165 m_assembler.addlRegReg(address.base, scr);
1166 m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
1167 m_assembler.fmovsReadrm(scr, dest);
1168 releaseScratch(scr);
1169 }
1170
81345200 1171 void loadDouble(TrustedImmPtr address, FPRegisterID dest)
14957cd0
A
1172 {
1173 RegisterID scr = claimScratch();
81345200 1174 move(address, scr);
14957cd0
A
1175 m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
1176 m_assembler.fmovsReadrm(scr, dest);
1177 releaseScratch(scr);
1178 }
1179
93a37866
A
1180 void storeFloat(FPRegisterID src, BaseIndex address)
1181 {
1182 RegisterID scr = claimScratch();
81345200 1183 loadEffectiveAddress(address, scr);
93a37866 1184 m_assembler.fmovsWriterm(src, scr);
93a37866
A
1185 releaseScratch(scr);
1186 }
1187
14957cd0
A
1188 void storeDouble(FPRegisterID src, ImplicitAddress address)
1189 {
1190 RegisterID scr = claimScratch();
93a37866 1191 m_assembler.loadConstant(address.offset + 8, scr);
14957cd0 1192 m_assembler.addlRegReg(address.base, scr);
93a37866
A
1193 m_assembler.fmovsWriterndec(src, scr);
1194 m_assembler.fmovsWriterndec((FPRegisterID)(src + 1), scr);
1195 releaseScratch(scr);
1196 }
1197
1198 void storeDouble(FPRegisterID src, BaseIndex address)
1199 {
1200 RegisterID scr = claimScratch();
1201
81345200 1202 loadEffectiveAddress(address, scr, 8);
93a37866
A
1203
1204 m_assembler.fmovsWriterndec(src, scr);
1205 m_assembler.fmovsWriterndec((FPRegisterID)(src + 1), scr);
1206
14957cd0
A
1207 releaseScratch(scr);
1208 }
1209
93a37866
A
1210 void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1211 {
1212 if (op1 == dest)
1213 addDouble(op2, dest);
1214 else {
1215 moveDouble(op2, dest);
1216 addDouble(op1, dest);
1217 }
1218 }
1219
81345200
A
1220 void storeDouble(FPRegisterID src, TrustedImmPtr address)
1221 {
1222 RegisterID scr = claimScratch();
1223 m_assembler.loadConstant(reinterpret_cast<uint32_t>(const_cast<void*>(address.m_value)) + 8, scr);
1224 m_assembler.fmovsWriterndec(src, scr);
1225 m_assembler.fmovsWriterndec((FPRegisterID)(src + 1), scr);
1226 releaseScratch(scr);
1227 }
1228
14957cd0
A
1229 void addDouble(FPRegisterID src, FPRegisterID dest)
1230 {
1231 m_assembler.daddRegReg(src, dest);
1232 }
1233
93a37866
A
1234 void addDouble(AbsoluteAddress address, FPRegisterID dest)
1235 {
81345200 1236 loadDouble(TrustedImmPtr(address.m_ptr), fscratch);
93a37866
A
1237 addDouble(fscratch, dest);
1238 }
1239
14957cd0
A
1240 void addDouble(Address address, FPRegisterID dest)
1241 {
1242 loadDouble(address, fscratch);
1243 addDouble(fscratch, dest);
1244 }
1245
1246 void subDouble(FPRegisterID src, FPRegisterID dest)
1247 {
1248 m_assembler.dsubRegReg(src, dest);
1249 }
1250
81345200
A
1251 void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1252 {
1253 if (op2 == dest) {
1254 moveDouble(op1, fscratch);
1255 subDouble(op2, fscratch);
1256 moveDouble(fscratch, dest);
1257 } else {
1258 moveDouble(op1, dest);
1259 subDouble(op2, dest);
1260 }
1261 }
1262
14957cd0
A
1263 void subDouble(Address address, FPRegisterID dest)
1264 {
1265 loadDouble(address, fscratch);
1266 subDouble(fscratch, dest);
1267 }
1268
1269 void mulDouble(FPRegisterID src, FPRegisterID dest)
1270 {
1271 m_assembler.dmulRegReg(src, dest);
1272 }
1273
81345200
A
1274 void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1275 {
1276 if (op1 == dest)
1277 mulDouble(op2, dest);
1278 else {
1279 moveDouble(op2, dest);
1280 mulDouble(op1, dest);
1281 }
1282 }
1283
14957cd0
A
1284 void mulDouble(Address address, FPRegisterID dest)
1285 {
1286 loadDouble(address, fscratch);
1287 mulDouble(fscratch, dest);
1288 }
1289
1290 void divDouble(FPRegisterID src, FPRegisterID dest)
1291 {
1292 m_assembler.ddivRegReg(src, dest);
1293 }
1294
81345200
A
1295 void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1296 {
1297 if (op2 == dest) {
1298 moveDouble(op1, fscratch);
1299 divDouble(op2, fscratch);
1300 moveDouble(fscratch, dest);
1301 } else {
1302 moveDouble(op1, dest);
1303 divDouble(op2, dest);
1304 }
1305 }
1306
1307 void negateDouble(FPRegisterID src, FPRegisterID dest)
1308 {
1309 moveDouble(src, dest);
1310 m_assembler.dneg(dest);
1311 }
1312
93a37866
A
1313 void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
1314 {
1315 m_assembler.fldsfpul(src);
1316 m_assembler.dcnvsd(dst);
1317 }
1318
1319 void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst)
1320 {
1321 m_assembler.dcnvds(src);
1322 m_assembler.fstsfpul(dst);
1323 }
1324
14957cd0
A
1325 void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
1326 {
1327 m_assembler.ldsrmfpul(src);
1328 m_assembler.floatfpulDreg(dest);
1329 }
1330
1331 void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
1332 {
1333 RegisterID scr = claimScratch();
93a37866 1334 load32(src.m_ptr, scr);
14957cd0
A
1335 convertInt32ToDouble(scr, dest);
1336 releaseScratch(scr);
1337 }
1338
1339 void convertInt32ToDouble(Address src, FPRegisterID dest)
1340 {
1341 RegisterID scr = claimScratch();
1342 load32(src, scr);
1343 convertInt32ToDouble(scr, dest);
1344 releaseScratch(scr);
1345 }
1346
1347 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
1348 {
1349 RegisterID scr = claimScratch();
6fe7ccc8
A
1350 Jump m_jump;
1351 JumpList end;
1352
81345200
A
1353 loadEffectiveAddress(address, scr);
1354
1355 RegisterID scr1 = claimScratch();
6fe7ccc8
A
1356 if (dest != SH4Registers::r0)
1357 move(SH4Registers::r0, scr1);
14957cd0 1358
93a37866 1359 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 58, sizeof(uint32_t));
6fe7ccc8 1360 move(scr, SH4Registers::r0);
93a37866 1361 m_assembler.testlImm8r(0x3, SH4Registers::r0);
6fe7ccc8 1362 m_jump = Jump(m_assembler.jne(), SH4Assembler::JumpNear);
93a37866 1363
6fe7ccc8
A
1364 if (dest != SH4Registers::r0)
1365 move(scr1, SH4Registers::r0);
1366
1367 load32(scr, dest);
1368 end.append(Jump(m_assembler.bra(), SH4Assembler::JumpNear));
1369 m_assembler.nop();
1370 m_jump.link(this);
93a37866 1371 m_assembler.testlImm8r(0x1, SH4Registers::r0);
6fe7ccc8
A
1372
1373 if (dest != SH4Registers::r0)
1374 move(scr1, SH4Registers::r0);
1375
1376 m_jump = Jump(m_assembler.jne(), SH4Assembler::JumpNear);
93a37866 1377 load16PostInc(scr, scr1);
14957cd0 1378 load16(scr, dest);
6fe7ccc8 1379 m_assembler.shllImm8r(16, dest);
14957cd0 1380 or32(scr1, dest);
6fe7ccc8
A
1381 end.append(Jump(m_assembler.bra(), SH4Assembler::JumpNear));
1382 m_assembler.nop();
1383 m_jump.link(this);
93a37866
A
1384 load8PostInc(scr, scr1);
1385 load16PostInc(scr, dest);
6fe7ccc8
A
1386 m_assembler.shllImm8r(8, dest);
1387 or32(dest, scr1);
6fe7ccc8
A
1388 load8(scr, dest);
1389 m_assembler.shllImm8r(8, dest);
1390 m_assembler.shllImm8r(16, dest);
1391 or32(scr1, dest);
1392 end.link(this);
14957cd0
A
1393
1394 releaseScratch(scr);
1395 releaseScratch(scr1);
1396 }
1397
1398 Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1399 {
1400 RegisterID scr = scratchReg3;
1401 load32WithUnalignedHalfWords(left, scr);
1402 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1403 m_assembler.testlRegReg(scr, scr);
1404 else
1405 compare32(right.m_value, scr, cond);
1406
1407 if (cond == NotEqual)
1408 return branchFalse();
1409 return branchTrue();
1410 }
1411
1412 Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
1413 {
1414 m_assembler.movImm8(0, scratchReg3);
1415 convertInt32ToDouble(scratchReg3, scratch);
1416 return branchDouble(DoubleNotEqual, reg, scratch);
1417 }
1418
1419 Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
1420 {
1421 m_assembler.movImm8(0, scratchReg3);
1422 convertInt32ToDouble(scratchReg3, scratch);
1423 return branchDouble(DoubleEqualOrUnordered, reg, scratch);
1424 }
1425
1426 Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
1427 {
1428 if (cond == DoubleEqual) {
1429 m_assembler.dcmppeq(right, left);
1430 return branchTrue();
1431 }
1432
1433 if (cond == DoubleNotEqual) {
6fe7ccc8 1434 JumpList end;
93a37866 1435 m_assembler.dcmppeq(left, left);
14957cd0 1436 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
93a37866
A
1437 end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1438 m_assembler.dcmppeq(right, right);
1439 end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
14957cd0 1440 m_assembler.dcmppeq(right, left);
6fe7ccc8
A
1441 Jump m_jump = branchFalse();
1442 end.link(this);
1443 return m_jump;
14957cd0
A
1444 }
1445
1446 if (cond == DoubleGreaterThan) {
1447 m_assembler.dcmppgt(right, left);
1448 return branchTrue();
1449 }
1450
1451 if (cond == DoubleGreaterThanOrEqual) {
93a37866
A
1452 JumpList end;
1453 m_assembler.dcmppeq(left, left);
1454 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1455 end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1456 m_assembler.dcmppeq(right, right);
1457 end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
14957cd0 1458 m_assembler.dcmppgt(left, right);
93a37866
A
1459 Jump m_jump = branchFalse();
1460 end.link(this);
1461 return m_jump;
14957cd0
A
1462 }
1463
1464 if (cond == DoubleLessThan) {
1465 m_assembler.dcmppgt(left, right);
1466 return branchTrue();
1467 }
1468
1469 if (cond == DoubleLessThanOrEqual) {
93a37866
A
1470 JumpList end;
1471 m_assembler.dcmppeq(left, left);
1472 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
1473 end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1474 m_assembler.dcmppeq(right, right);
1475 end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
14957cd0 1476 m_assembler.dcmppgt(right, left);
93a37866
A
1477 Jump m_jump = branchFalse();
1478 end.link(this);
1479 return m_jump;
14957cd0
A
1480 }
1481
1482 if (cond == DoubleEqualOrUnordered) {
93a37866
A
1483 JumpList takeBranch;
1484 m_assembler.dcmppeq(left, left);
14957cd0 1485 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
93a37866
A
1486 takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1487 m_assembler.dcmppeq(right, right);
1488 takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
14957cd0 1489 m_assembler.dcmppeq(left, right);
81345200 1490 m_assembler.branch(BF_OPCODE, 2);
93a37866 1491 takeBranch.link(this);
81345200 1492 return Jump(m_assembler.extraInstrForBranch(scratchReg3));
14957cd0
A
1493 }
1494
1495 if (cond == DoubleGreaterThanOrUnordered) {
93a37866
A
1496 JumpList takeBranch;
1497 m_assembler.dcmppeq(left, left);
14957cd0 1498 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
93a37866
A
1499 takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1500 m_assembler.dcmppeq(right, right);
1501 takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
14957cd0 1502 m_assembler.dcmppgt(right, left);
81345200 1503 m_assembler.branch(BF_OPCODE, 2);
93a37866 1504 takeBranch.link(this);
81345200 1505 return Jump(m_assembler.extraInstrForBranch(scratchReg3));
14957cd0
A
1506 }
1507
1508 if (cond == DoubleGreaterThanOrEqualOrUnordered) {
14957cd0 1509 m_assembler.dcmppgt(left, right);
93a37866 1510 return branchFalse();
14957cd0
A
1511 }
1512
1513 if (cond == DoubleLessThanOrUnordered) {
93a37866
A
1514 JumpList takeBranch;
1515 m_assembler.dcmppeq(left, left);
14957cd0 1516 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
93a37866
A
1517 takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
1518 m_assembler.dcmppeq(right, right);
1519 takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear));
14957cd0 1520 m_assembler.dcmppgt(left, right);
81345200 1521 m_assembler.branch(BF_OPCODE, 2);
93a37866 1522 takeBranch.link(this);
81345200 1523 return Jump(m_assembler.extraInstrForBranch(scratchReg3));
14957cd0
A
1524 }
1525
1526 if (cond == DoubleLessThanOrEqualOrUnordered) {
14957cd0 1527 m_assembler.dcmppgt(right, left);
93a37866 1528 return branchFalse();
14957cd0
A
1529 }
1530
1531 ASSERT(cond == DoubleNotEqualOrUnordered);
14957cd0 1532 m_assembler.dcmppeq(right, left);
93a37866 1533 return branchFalse();
14957cd0
A
1534 }
1535
1536 Jump branchTrue()
1537 {
1538 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
81345200
A
1539 m_assembler.branch(BF_OPCODE, 2);
1540 return Jump(m_assembler.extraInstrForBranch(scratchReg3));
14957cd0
A
1541 }
1542
1543 Jump branchFalse()
1544 {
1545 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
81345200
A
1546 m_assembler.branch(BT_OPCODE, 2);
1547 return Jump(m_assembler.extraInstrForBranch(scratchReg3));
14957cd0
A
1548 }
1549
1550 Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1551 {
1552 RegisterID scr = claimScratch();
1553 move(left.index, scr);
1554 lshift32(TrustedImm32(left.scale), scr);
1555 add32(left.base, scr);
1556 load32(scr, left.offset, scr);
1557 compare32(right.m_value, scr, cond);
1558 releaseScratch(scr);
1559
1560 if (cond == NotEqual)
1561 return branchFalse();
1562 return branchTrue();
1563 }
1564
1565 void sqrtDouble(FPRegisterID src, FPRegisterID dest)
1566 {
93a37866 1567 moveDouble(src, dest);
14957cd0
A
1568 m_assembler.dsqrt(dest);
1569 }
6fe7ccc8 1570
93a37866 1571 void absDouble(FPRegisterID src, FPRegisterID dest)
6fe7ccc8 1572 {
93a37866
A
1573 moveDouble(src, dest);
1574 m_assembler.dabs(dest);
6fe7ccc8 1575 }
14957cd0
A
1576
1577 Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1578 {
1579 RegisterID addressTempRegister = claimScratch();
1580 load8(address, addressTempRegister);
1581 Jump jmp = branchTest32(cond, addressTempRegister, mask);
1582 releaseScratch(addressTempRegister);
1583 return jmp;
1584 }
1585
81345200
A
1586 Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
1587 {
1588 RegisterID addressTempRegister = claimScratch();
1589 load8(address, addressTempRegister);
1590 Jump jmp = branchTest32(cond, addressTempRegister, mask);
1591 releaseScratch(addressTempRegister);
1592 return jmp;
1593 }
1594
93a37866
A
1595 Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
1596 {
1597 RegisterID addressTempRegister = claimScratch();
1598 move(TrustedImmPtr(address.m_ptr), addressTempRegister);
1599 load8(Address(addressTempRegister), addressTempRegister);
1600 Jump jmp = branchTest32(cond, addressTempRegister, mask);
1601 releaseScratch(addressTempRegister);
1602 return jmp;
1603 }
1604
14957cd0
A
1605 void signExtend32ToPtr(RegisterID src, RegisterID dest)
1606 {
81345200
A
1607 move(src, dest);
1608 }
1609
1610 void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
1611 {
1612 move(src, dest);
14957cd0
A
1613 }
1614
1615 Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
1616 {
1617 RegisterID addressTempRegister = claimScratch();
1618 load8(left, addressTempRegister);
1619 Jump jmp = branch32(cond, addressTempRegister, right);
1620 releaseScratch(addressTempRegister);
1621 return jmp;
1622 }
1623
81345200
A
1624 Jump branch8(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
1625 {
1626 RegisterID addressTempRegister = claimScratch();
1627 load8(left, addressTempRegister);
1628 Jump jmp = branch32(cond, addressTempRegister, right);
1629 releaseScratch(addressTempRegister);
1630 return jmp;
1631 }
1632
6fe7ccc8
A
1633 void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
1634 {
1635 RegisterID addressTempRegister = claimScratch();
1636 load8(left, addressTempRegister);
1637 compare32(cond, addressTempRegister, right, dest);
1638 releaseScratch(addressTempRegister);
1639 }
1640
93a37866
A
1641 enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
1642 Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
81345200
A
1643 {
1644 Jump result;
1645 truncateDoubleToInt32(src, dest);
1646 RegisterID intscr = claimScratch();
1647 m_assembler.loadConstant(0x7fffffff, intscr);
1648 m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal));
1649 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 12, sizeof(uint32_t));
1650 if (branchType == BranchIfTruncateFailed) {
1651 m_assembler.branch(BT_OPCODE, 2);
1652 m_assembler.addlImm8r(1, intscr);
1653 m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal));
1654 result = branchTrue();
1655 } else {
1656 Jump out = Jump(m_assembler.je(), SH4Assembler::JumpNear);
1657 m_assembler.addlImm8r(1, intscr);
1658 m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal));
1659 result = branchFalse();
1660 out.link(this);
1661 }
1662 releaseScratch(intscr);
1663 return result;
1664 }
1665
1666 Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
1667 {
1668 Jump result;
1669 RegisterID intscr = claimScratch();
1670 m_assembler.loadConstant(0x80000000, intscr);
1671 convertInt32ToDouble(intscr, fscratch);
1672 addDouble(src, fscratch);
1673 truncateDoubleToInt32(fscratch, dest);
1674 m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal));
1675 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 16, sizeof(uint32_t));
1676 if (branchType == BranchIfTruncateFailed) {
1677 m_assembler.branch(BT_OPCODE, 4);
1678 m_assembler.addlImm8r(-1, intscr);
1679 m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal));
1680 m_assembler.addlImm8r(1, intscr);
1681 m_assembler.sublRegReg(intscr, dest);
1682 result = branchTrue();
1683 } else {
1684 Jump out = Jump(m_assembler.je(), SH4Assembler::JumpNear);
1685 m_assembler.addlImm8r(-1, intscr);
1686 m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal));
1687 m_assembler.addlImm8r(1, intscr);
1688 m_assembler.sublRegReg(intscr, dest);
1689 result = branchFalse();
1690 out.link(this);
1691 }
1692 releaseScratch(intscr);
1693 return result;
1694 }
1695
1696 void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
14957cd0
A
1697 {
1698 m_assembler.ftrcdrmfpul(src);
1699 m_assembler.stsfpulReg(dest);
81345200
A
1700 }
1701
1702 void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
1703 {
1704 RegisterID intscr = claimScratch();
1705 m_assembler.loadConstant(0x80000000, intscr);
1706 convertInt32ToDouble(intscr, fscratch);
1707 addDouble(src, fscratch);
1708 m_assembler.ftrcdrmfpul(fscratch);
1709 m_assembler.stsfpulReg(dest);
1710 m_assembler.sublRegReg(intscr, dest);
1711 releaseScratch(intscr);
14957cd0
A
1712 }
1713
1714 // Stack manipulation operations
1715
1716 void pop(RegisterID dest)
1717 {
1718 m_assembler.popReg(dest);
1719 }
1720
1721 void push(RegisterID src)
1722 {
1723 m_assembler.pushReg(src);
1724 }
1725
14957cd0
A
1726 void push(TrustedImm32 imm)
1727 {
1728 RegisterID scr = claimScratch();
1729 m_assembler.loadConstant(imm.m_value, scr);
1730 push(scr);
1731 releaseScratch(scr);
1732 }
1733
1734 // Register move operations
1735
1736 void move(TrustedImm32 imm, RegisterID dest)
1737 {
1738 m_assembler.loadConstant(imm.m_value, dest);
1739 }
1740
1741 DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
1742 {
6fe7ccc8 1743 m_assembler.ensureSpace(m_assembler.maxInstructionSize, sizeof(uint32_t));
14957cd0 1744 DataLabelPtr dataLabel(this);
6fe7ccc8 1745 m_assembler.loadConstantUnReusable(reinterpret_cast<uint32_t>(initialValue.m_value), dest);
14957cd0
A
1746 return dataLabel;
1747 }
1748
ed1e77d3
A
1749 DataLabel32 moveWithPatch(TrustedImm32 initialValue, RegisterID dest)
1750 {
1751 m_assembler.ensureSpace(m_assembler.maxInstructionSize, sizeof(uint32_t));
1752 DataLabel32 dataLabel(this);
1753 m_assembler.loadConstantUnReusable(static_cast<uint32_t>(initialValue.m_value), dest);
1754 return dataLabel;
1755 }
1756
14957cd0
A
1757 void move(RegisterID src, RegisterID dest)
1758 {
6fe7ccc8
A
1759 if (src != dest)
1760 m_assembler.movlRegReg(src, dest);
14957cd0
A
1761 }
1762
1763 void move(TrustedImmPtr imm, RegisterID dest)
1764 {
1765 m_assembler.loadConstant(imm.asIntptr(), dest);
1766 }
1767
81345200
A
1768 void swap(RegisterID reg1, RegisterID reg2)
1769 {
1770 if (reg1 != reg2) {
1771 xor32(reg1, reg2);
1772 xor32(reg2, reg1);
1773 xor32(reg1, reg2);
1774 }
1775 }
1776
14957cd0
A
1777 void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
1778 {
1779 m_assembler.cmplRegReg(right, left, SH4Condition(cond));
1780 if (cond != NotEqual) {
1781 m_assembler.movt(dest);
1782 return;
1783 }
1784
1785 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
1786 m_assembler.movImm8(0, dest);
1787 m_assembler.branch(BT_OPCODE, 0);
1788 m_assembler.movImm8(1, dest);
1789 }
1790
1791 void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
1792 {
1793 if (left != dest) {
1794 move(right, dest);
1795 compare32(cond, left, dest, dest);
1796 return;
1797 }
1798
1799 RegisterID scr = claimScratch();
1800 move(right, scr);
1801 compare32(cond, left, scr, dest);
1802 releaseScratch(scr);
1803 }
1804
1805 void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
1806 {
1807 ASSERT((cond == Zero) || (cond == NonZero));
1808
1809 load8(address, dest);
1810 if (mask.m_value == -1)
1811 compare32(0, dest, static_cast<RelationalCondition>(cond));
1812 else
1813 testlImm(mask.m_value, dest);
1814 if (cond != NonZero) {
1815 m_assembler.movt(dest);
1816 return;
1817 }
1818
1819 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
1820 m_assembler.movImm8(0, dest);
1821 m_assembler.branch(BT_OPCODE, 0);
1822 m_assembler.movImm8(1, dest);
1823 }
1824
81345200
A
1825 void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
1826 {
1827 ASSERT((cond == Zero) || (cond == NonZero));
1828
1829 load32(address, dest);
1830 if (mask.m_value == -1)
1831 compare32(0, dest, static_cast<RelationalCondition>(cond));
1832 else
1833 testlImm(mask.m_value, dest);
1834 if (cond != NonZero) {
1835 m_assembler.movt(dest);
1836 return;
1837 }
1838
1839 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
1840 m_assembler.movImm8(0, dest);
1841 m_assembler.branch(BT_OPCODE, 0);
1842 m_assembler.movImm8(1, dest);
1843 }
1844
14957cd0
A
1845 void loadPtrLinkReg(ImplicitAddress address)
1846 {
1847 RegisterID scr = claimScratch();
1848 load32(address, scr);
1849 m_assembler.ldspr(scr);
1850 releaseScratch(scr);
1851 }
1852
1853 Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
1854 {
1855 m_assembler.cmplRegReg(right, left, SH4Condition(cond));
1856 /* BT label => BF off
1857 nop LDR reg
1858 nop braf @reg
1859 nop nop
1860 */
1861 if (cond == NotEqual)
1862 return branchFalse();
1863 return branchTrue();
1864 }
1865
1866 Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
1867 {
1868 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1869 m_assembler.testlRegReg(left, left);
1870 else
1871 compare32(right.m_value, left, cond);
1872
1873 if (cond == NotEqual)
1874 return branchFalse();
1875 return branchTrue();
1876 }
1877
1878 Jump branch32(RelationalCondition cond, RegisterID left, Address right)
1879 {
1880 compare32(right.offset, right.base, left, cond);
1881 if (cond == NotEqual)
1882 return branchFalse();
1883 return branchTrue();
1884 }
1885
1886 Jump branch32(RelationalCondition cond, Address left, RegisterID right)
1887 {
1888 compare32(right, left.offset, left.base, cond);
1889 if (cond == NotEqual)
1890 return branchFalse();
1891 return branchTrue();
1892 }
1893
1894 Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
1895 {
1896 compare32(right.m_value, left.offset, left.base, cond);
1897 if (cond == NotEqual)
1898 return branchFalse();
1899 return branchTrue();
1900 }
1901
1902 Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
1903 {
1904 RegisterID scr = claimScratch();
1905
93a37866 1906 load32(left.m_ptr, scr);
14957cd0
A
1907 m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
1908 releaseScratch(scr);
1909
1910 if (cond == NotEqual)
1911 return branchFalse();
1912 return branchTrue();
1913 }
1914
1915 Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
1916 {
1917 RegisterID addressTempRegister = claimScratch();
1918
81345200 1919 move(TrustedImmPtr(left.m_ptr), addressTempRegister);
14957cd0
A
1920 m_assembler.movlMemReg(addressTempRegister, addressTempRegister);
1921 compare32(right.m_value, addressTempRegister, cond);
1922 releaseScratch(addressTempRegister);
1923
1924 if (cond == NotEqual)
1925 return branchFalse();
1926 return branchTrue();
1927 }
1928
6fe7ccc8 1929 Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
14957cd0 1930 {
6fe7ccc8 1931 ASSERT(!(right.m_value & 0xFFFFFF00));
81345200 1932 RegisterID lefttmp = claimScratch();
14957cd0 1933
81345200 1934 loadEffectiveAddress(left, lefttmp);
14957cd0 1935
81345200
A
1936 load8(lefttmp, lefttmp);
1937 RegisterID righttmp = claimScratch();
1938 m_assembler.loadConstant(right.m_value, righttmp);
14957cd0 1939
81345200
A
1940 Jump result = branch32(cond, lefttmp, righttmp);
1941 releaseScratch(lefttmp);
1942 releaseScratch(righttmp);
1943 return result;
14957cd0
A
1944 }
1945
1946 Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
1947 {
1948 ASSERT((cond == Zero) || (cond == NonZero));
1949
1950 m_assembler.testlRegReg(reg, mask);
1951
93a37866 1952 if (cond == NonZero) // NotEqual
14957cd0
A
1953 return branchFalse();
1954 return branchTrue();
1955 }
1956
1957 Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
1958 {
1959 ASSERT((cond == Zero) || (cond == NonZero));
1960
1961 if (mask.m_value == -1)
1962 m_assembler.testlRegReg(reg, reg);
1963 else
1964 testlImm(mask.m_value, reg);
1965
93a37866 1966 if (cond == NonZero) // NotEqual
14957cd0
A
1967 return branchFalse();
1968 return branchTrue();
1969 }
1970
1971 Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1972 {
1973 ASSERT((cond == Zero) || (cond == NonZero));
1974
1975 if (mask.m_value == -1)
1976 compare32(0, address.offset, address.base, static_cast<RelationalCondition>(cond));
1977 else
1978 testImm(mask.m_value, address.offset, address.base);
1979
93a37866 1980 if (cond == NonZero) // NotEqual
14957cd0
A
1981 return branchFalse();
1982 return branchTrue();
1983 }
1984
1985 Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
1986 {
81345200
A
1987 ASSERT((cond == Zero) || (cond == NonZero));
1988
14957cd0
A
1989 RegisterID scr = claimScratch();
1990
1991 move(address.index, scr);
1992 lshift32(TrustedImm32(address.scale), scr);
1993 add32(address.base, scr);
1994 load32(scr, address.offset, scr);
1995
1996 if (mask.m_value == -1)
1997 m_assembler.testlRegReg(scr, scr);
1998 else
1999 testlImm(mask.m_value, scr);
2000
2001 releaseScratch(scr);
2002
93a37866 2003 if (cond == NonZero) // NotEqual
14957cd0
A
2004 return branchFalse();
2005 return branchTrue();
2006 }
2007
2008 Jump jump()
2009 {
2010 return Jump(m_assembler.jmp());
2011 }
2012
2013 void jump(RegisterID target)
2014 {
2015 m_assembler.jmpReg(target);
2016 }
2017
2018 void jump(Address address)
2019 {
2020 RegisterID scr = claimScratch();
81345200 2021 load32(address, scr);
14957cd0 2022 m_assembler.jmpReg(scr);
81345200
A
2023 releaseScratch(scr);
2024 }
2025
2026 void jump(AbsoluteAddress address)
2027 {
2028 RegisterID scr = claimScratch();
14957cd0 2029
81345200
A
2030 move(TrustedImmPtr(address.m_ptr), scr);
2031 m_assembler.movlMemReg(scr, scr);
2032 m_assembler.jmpReg(scr);
14957cd0
A
2033 releaseScratch(scr);
2034 }
2035
2036 // Arithmetic control flow operations
2037
81345200
A
2038 Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
2039 {
2040 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2041
2042 if (cond == Overflow)
2043 return branchMul32(cond, TrustedImm32(-1), srcDest, srcDest);
2044
2045 neg32(srcDest);
2046
2047 if (cond == Signed) {
2048 m_assembler.cmppz(srcDest);
2049 return branchFalse();
2050 }
2051
2052 compare32(0, srcDest, Equal);
2053 return (cond == NonZero) ? branchFalse() : branchTrue();
2054 }
2055
14957cd0
A
2056 Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
2057 {
93a37866 2058 ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
14957cd0
A
2059
2060 if (cond == Overflow) {
2061 m_assembler.addvlRegReg(src, dest);
2062 return branchTrue();
2063 }
2064
81345200
A
2065 m_assembler.addlRegReg(src, dest);
2066
2067 if ((cond == Signed) || (cond == PositiveOrZero)) {
14957cd0 2068 m_assembler.cmppz(dest);
81345200 2069 return (cond == Signed) ? branchFalse() : branchTrue();
14957cd0
A
2070 }
2071
81345200
A
2072 compare32(0, dest, Equal);
2073 return (cond == NonZero) ? branchFalse() : branchTrue();
2074 }
2075
2076 Jump branchAdd32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
2077 {
2078 ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
2079
2080 if (cond == Overflow) {
2081 if (src1 == dest)
2082 m_assembler.addvlRegReg(src2, dest);
2083 else {
2084 move(src2, dest);
2085 m_assembler.addvlRegReg(src1, dest);
2086 }
93a37866
A
2087 return branchTrue();
2088 }
2089
81345200 2090 add32(src1, src2, dest);
14957cd0 2091
81345200
A
2092 if ((cond == Signed) || (cond == PositiveOrZero)) {
2093 m_assembler.cmppz(dest);
2094 return (cond == Signed) ? branchFalse() : branchTrue();
2095 }
2096
2097 compare32(0, dest, Equal);
2098 return (cond == NonZero) ? branchFalse() : branchTrue();
14957cd0
A
2099 }
2100
2101 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
2102 {
93a37866 2103 ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
14957cd0 2104
81345200
A
2105 RegisterID immval = claimScratch();
2106 move(imm, immval);
2107 Jump result = branchAdd32(cond, immval, dest);
2108 releaseScratch(immval);
2109 return result;
14957cd0
A
2110 }
2111
6fe7ccc8
A
2112 Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
2113 {
93a37866 2114 ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
6fe7ccc8 2115
81345200 2116 move(src, dest);
6fe7ccc8
A
2117
2118 if (cond == Overflow) {
2119 move(imm, scratchReg3);
2120 m_assembler.addvlRegReg(scratchReg3, dest);
2121 return branchTrue();
2122 }
2123
2124 add32(imm, dest);
2125
81345200 2126 if ((cond == Signed) || (cond == PositiveOrZero)) {
6fe7ccc8 2127 m_assembler.cmppz(dest);
81345200 2128 return (cond == Signed) ? branchFalse() : branchTrue();
93a37866
A
2129 }
2130
6fe7ccc8 2131 compare32(0, dest, Equal);
81345200 2132 return (cond == NonZero) ? branchFalse() : branchTrue();
6fe7ccc8
A
2133 }
2134
93a37866
A
2135 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
2136 {
2137 ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
2138 bool result;
2139
2140 move(imm, scratchReg3);
2141 RegisterID destptr = claimScratch();
2142 RegisterID destval = claimScratch();
81345200 2143 move(TrustedImmPtr(dest.m_ptr), destptr);
93a37866
A
2144 m_assembler.movlMemReg(destptr, destval);
2145 if (cond == Overflow) {
2146 m_assembler.addvlRegReg(scratchReg3, destval);
2147 result = true;
2148 } else {
2149 m_assembler.addlRegReg(scratchReg3, destval);
81345200 2150 if ((cond == Signed) || (cond == PositiveOrZero)) {
93a37866 2151 m_assembler.cmppz(destval);
81345200 2152 result = (cond == PositiveOrZero);
93a37866 2153 } else {
81345200
A
2154 m_assembler.testlRegReg(destval, destval);
2155 result = (cond != NonZero);
93a37866
A
2156 }
2157 }
2158 m_assembler.movlRegMem(destval, destptr);
2159 releaseScratch(destval);
2160 releaseScratch(destptr);
2161 return result ? branchTrue() : branchFalse();
2162 }
2163
ed1e77d3
A
2164 Jump branchAdd32(ResultCondition cond, Address src, RegisterID dest)
2165 {
2166 ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
2167
2168 if (cond == Overflow) {
2169 RegisterID srcVal = claimScratch();
2170 load32(src, srcVal);
2171 m_assembler.addvlRegReg(srcVal, dest);
2172 releaseScratch(srcVal);
2173 return branchTrue();
2174 }
2175
2176 add32(src, dest);
2177
2178 if ((cond == Signed) || (cond == PositiveOrZero)) {
2179 m_assembler.cmppz(dest);
2180 return (cond == Signed) ? branchFalse() : branchTrue();
2181 }
2182
2183 compare32(0, dest, Equal);
2184 return (cond == NonZero) ? branchFalse() : branchTrue();
2185 }
2186
14957cd0
A
2187 Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
2188 {
2189 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2190
2191 if (cond == Overflow) {
93a37866
A
2192 RegisterID scrsign = claimScratch();
2193 RegisterID msbres = claimScratch();
2194 m_assembler.dmulslRegReg(src, dest);
14957cd0 2195 m_assembler.stsmacl(dest);
93a37866
A
2196 m_assembler.cmppz(dest);
2197 m_assembler.movt(scrsign);
2198 m_assembler.addlImm8r(-1, scrsign);
2199 m_assembler.stsmach(msbres);
2200 m_assembler.cmplRegReg(msbres, scrsign, SH4Condition(Equal));
2201 releaseScratch(msbres);
2202 releaseScratch(scrsign);
14957cd0
A
2203 return branchFalse();
2204 }
2205
81345200
A
2206 mul32(src, dest);
2207
14957cd0 2208 if (cond == Signed) {
14957cd0
A
2209 m_assembler.cmppz(dest);
2210 return branchFalse();
2211 }
2212
2213 compare32(0, dest, static_cast<RelationalCondition>(cond));
81345200
A
2214 return (cond == NonZero) ? branchFalse() : branchTrue();
2215 }
14957cd0 2216
81345200
A
2217 Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
2218 {
2219 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2220
2221 if (cond == Overflow) {
2222 RegisterID scrsign = claimScratch();
2223 RegisterID msbres = claimScratch();
2224 m_assembler.dmulslRegReg(src1, src2);
2225 m_assembler.stsmacl(dest);
2226 m_assembler.cmppz(dest);
2227 m_assembler.movt(scrsign);
2228 m_assembler.addlImm8r(-1, scrsign);
2229 m_assembler.stsmach(msbres);
2230 m_assembler.cmplRegReg(msbres, scrsign, SH4Condition(Equal));
2231 releaseScratch(msbres);
2232 releaseScratch(scrsign);
14957cd0 2233 return branchFalse();
81345200
A
2234 }
2235
2236 mul32(src1, src2, dest);
2237
2238 if (cond == Signed) {
2239 m_assembler.cmppz(dest);
2240 return branchFalse();
2241 }
2242
2243 compare32(0, dest, Equal);
2244 return (cond == NonZero) ? branchFalse() : branchTrue();
14957cd0
A
2245 }
2246
2247 Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
2248 {
2249 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2250
81345200
A
2251 if (src == dest) {
2252 move(imm, scratchReg3);
2253 return branchMul32(cond, scratchReg3, dest);
2254 }
14957cd0 2255
81345200
A
2256 move(imm, dest);
2257 return branchMul32(cond, src, dest);
14957cd0
A
2258 }
2259
2260 Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
2261 {
2262 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2263
2264 if (cond == Overflow) {
2265 m_assembler.subvlRegReg(src, dest);
2266 return branchTrue();
2267 }
2268
81345200
A
2269 sub32(src, dest);
2270
14957cd0 2271 if (cond == Signed) {
81345200
A
2272 m_assembler.cmppz(dest);
2273 return branchFalse();
14957cd0
A
2274 }
2275
14957cd0 2276 compare32(0, dest, static_cast<RelationalCondition>(cond));
81345200 2277 return (cond == NonZero) ? branchFalse() : branchTrue();
14957cd0
A
2278 }
2279
2280 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
2281 {
2282 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2283
81345200
A
2284 RegisterID immval = claimScratch();
2285 move(imm, immval);
2286 Jump result = branchSub32(cond, immval, dest);
2287 releaseScratch(immval);
2288 return result;
14957cd0
A
2289 }
2290
6fe7ccc8
A
2291 Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
2292 {
81345200
A
2293 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2294
2295 move(src, dest);
2296 return branchSub32(cond, imm, dest);
6fe7ccc8
A
2297 }
2298
2299 Jump branchSub32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
2300 {
81345200
A
2301 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
2302
2303 if (src2 != dest) {
6fe7ccc8 2304 move(src1, dest);
81345200
A
2305 return branchSub32(cond, src2, dest);
2306 }
2307
2308 if (cond == Overflow) {
2309 RegisterID tmpval = claimScratch();
2310 move(src1, tmpval);
2311 m_assembler.subvlRegReg(src2, tmpval);
2312 move(tmpval, dest);
2313 releaseScratch(tmpval);
2314 return branchTrue();
2315 }
2316
2317 RegisterID tmpval = claimScratch();
2318 move(src1, tmpval);
2319 sub32(src2, tmpval);
2320 move(tmpval, dest);
2321 releaseScratch(tmpval);
2322
2323 if (cond == Signed) {
2324 m_assembler.cmppz(dest);
2325 return branchFalse();
2326 }
2327
2328 compare32(0, dest, static_cast<RelationalCondition>(cond));
2329 return (cond == NonZero) ? branchFalse() : branchTrue();
6fe7ccc8
A
2330 }
2331
14957cd0
A
2332 Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
2333 {
2334 ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
2335
81345200
A
2336 or32(src, dest);
2337
14957cd0 2338 if (cond == Signed) {
81345200
A
2339 m_assembler.cmppz(dest);
2340 return branchFalse();
14957cd0
A
2341 }
2342
14957cd0 2343 compare32(0, dest, static_cast<RelationalCondition>(cond));
81345200 2344 return (cond == NonZero) ? branchFalse() : branchTrue();
14957cd0
A
2345 }
2346
81345200 2347 void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID, bool negZeroCheck = true)
14957cd0 2348 {
81345200 2349 truncateDoubleToInt32(src, dest);
14957cd0
A
2350 convertInt32ToDouble(dest, fscratch);
2351 failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fscratch, src));
2352
81345200
A
2353 if (negZeroCheck)
2354 failureCases.append(branch32(Equal, dest, TrustedImm32(0)));
14957cd0
A
2355 }
2356
2357 void neg32(RegisterID dst)
2358 {
2359 m_assembler.neg(dst, dst);
2360 }
2361
14957cd0
A
2362 void urshift32(RegisterID shiftamount, RegisterID dest)
2363 {
93a37866
A
2364 RegisterID shiftTmp = claimScratch();
2365 m_assembler.loadConstant(0x1f, shiftTmp);
2366 m_assembler.andlRegReg(shiftamount, shiftTmp);
2367 m_assembler.neg(shiftTmp, shiftTmp);
2368 m_assembler.shldRegReg(dest, shiftTmp);
2369 releaseScratch(shiftTmp);
14957cd0
A
2370 }
2371
81345200
A
2372 void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
2373 {
2374 move(src, dest);
2375 urshift32(shiftAmount, dest);
2376 }
2377
14957cd0
A
2378 void urshift32(TrustedImm32 imm, RegisterID dest)
2379 {
93a37866
A
2380 int immMasked = imm.m_value & 0x1f;
2381 if (!immMasked)
2382 return;
2383
2384 if ((immMasked == 1) || (immMasked == 2) || (immMasked == 8) || (immMasked == 16)) {
2385 m_assembler.shlrImm8r(immMasked, dest);
2386 return;
2387 }
2388
2389 RegisterID shiftTmp = claimScratch();
2390 m_assembler.loadConstant(-immMasked, shiftTmp);
2391 m_assembler.shldRegReg(dest, shiftTmp);
2392 releaseScratch(shiftTmp);
14957cd0
A
2393 }
2394
6fe7ccc8
A
2395 void urshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest)
2396 {
81345200 2397 move(src, dest);
6fe7ccc8
A
2398 urshift32(shiftamount, dest);
2399 }
2400
14957cd0
A
2401 Call call()
2402 {
2403 return Call(m_assembler.call(), Call::Linkable);
2404 }
2405
2406 Call nearCall()
2407 {
2408 return Call(m_assembler.call(), Call::LinkableNear);
2409 }
2410
2411 Call call(RegisterID target)
2412 {
2413 return Call(m_assembler.call(target), Call::None);
2414 }
2415
81345200 2416 void call(Address address)
14957cd0 2417 {
81345200 2418 RegisterID target = claimScratch();
14957cd0
A
2419 load32(address.base, address.offset, target);
2420 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 2);
2421 m_assembler.branch(JSR_OPCODE, target);
2422 m_assembler.nop();
81345200 2423 releaseScratch(target);
14957cd0
A
2424 }
2425
2426 void breakpoint()
2427 {
81345200 2428 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 2);
14957cd0
A
2429 m_assembler.bkpt();
2430 m_assembler.nop();
2431 }
2432
2433 Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
2434 {
2435 RegisterID dataTempRegister = claimScratch();
2436
81345200 2437 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 10, 2 * sizeof(uint32_t));
14957cd0
A
2438 dataLabel = moveWithPatch(initialRightValue, dataTempRegister);
2439 m_assembler.cmplRegReg(dataTempRegister, left, SH4Condition(cond));
2440 releaseScratch(dataTempRegister);
2441
2442 if (cond == NotEqual)
2443 return branchFalse();
2444 return branchTrue();
2445 }
2446
2447 Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
2448 {
2449 RegisterID scr = claimScratch();
2450
2451 m_assembler.loadConstant(left.offset, scr);
2452 m_assembler.addlRegReg(left.base, scr);
2453 m_assembler.movlMemReg(scr, scr);
2454 RegisterID scr1 = claimScratch();
81345200 2455 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 10, 2 * sizeof(uint32_t));
14957cd0
A
2456 dataLabel = moveWithPatch(initialRightValue, scr1);
2457 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
2458 releaseScratch(scr);
2459 releaseScratch(scr1);
2460
2461 if (cond == NotEqual)
2462 return branchFalse();
2463 return branchTrue();
2464 }
2465
ed1e77d3
A
2466 Jump branch32WithPatch(RelationalCondition cond, Address left, DataLabel32& dataLabel, TrustedImm32 initialRightValue = TrustedImm32(0))
2467 {
2468 RegisterID scr = claimScratch();
2469
2470 m_assembler.loadConstant(left.offset, scr);
2471 m_assembler.addlRegReg(left.base, scr);
2472 m_assembler.movlMemReg(scr, scr);
2473 RegisterID scr1 = claimScratch();
2474 m_assembler.ensureSpace(m_assembler.maxInstructionSize + 10, 2 * sizeof(uint32_t));
2475 dataLabel = moveWithPatch(initialRightValue, scr1);
2476 m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
2477 releaseScratch(scr);
2478 releaseScratch(scr1);
2479
2480 return (cond == NotEqual) ? branchFalse() : branchTrue();
2481 }
2482
14957cd0
A
2483 void ret()
2484 {
2485 m_assembler.ret();
2486 m_assembler.nop();
2487 }
2488
2489 DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
2490 {
2491 RegisterID scr = claimScratch();
2492 DataLabelPtr label = moveWithPatch(initialValue, scr);
2493 store32(scr, address);
2494 releaseScratch(scr);
2495 return label;
2496 }
2497
2498 DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(TrustedImmPtr(0), address); }
2499
2500 int sizeOfConstantPool()
2501 {
2502 return m_assembler.sizeOfConstantPool();
2503 }
2504
2505 Call tailRecursiveCall()
2506 {
2507 RegisterID scr = claimScratch();
2508
2509 m_assembler.loadConstantUnReusable(0x0, scr, true);
2510 Jump m_jump = Jump(m_assembler.jmp(scr));
2511 releaseScratch(scr);
2512
2513 return Call::fromTailJump(m_jump);
2514 }
2515
2516 Call makeTailRecursiveCall(Jump oldJump)
2517 {
2518 oldJump.link(this);
2519 return tailRecursiveCall();
2520 }
2521
2522 void nop()
2523 {
2524 m_assembler.nop();
2525 }
2526
81345200
A
2527 void memoryFence()
2528 {
2529 m_assembler.synco();
2530 }
2531
ed1e77d3
A
2532 void abortWithReason(AbortReason reason)
2533 {
2534 move(TrustedImm32(reason), SH4Registers::r0);
2535 breakpoint();
2536 }
2537
2538 void abortWithReason(AbortReason reason, intptr_t misc)
2539 {
2540 move(TrustedImm32(misc), SH4Registers::r1);
2541 abortWithReason(reason);
2542 }
2543
6fe7ccc8
A
2544 static FunctionPtr readCallTarget(CodeLocationCall call)
2545 {
2546 return FunctionPtr(reinterpret_cast<void(*)()>(SH4Assembler::readCallTarget(call.dataLocation())));
2547 }
2548
93a37866
A
2549 static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
2550 {
2551 SH4Assembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation());
2552 }
2553
2554 static ptrdiff_t maxJumpReplacementSize()
2555 {
2556 return SH4Assembler::maxJumpReplacementSize();
2557 }
2558
2559 static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; }
2560
ed1e77d3
A
2561 static bool canJumpReplacePatchableBranch32WithPatch() { return false; }
2562
93a37866
A
2563 static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label)
2564 {
2565 return label.labelAtOffset(0);
2566 }
2567
81345200 2568 static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID rd, void* initialValue)
93a37866 2569 {
81345200 2570 SH4Assembler::revertJumpReplacementToBranchPtrWithPatch(instructionStart.dataLocation(), rd, reinterpret_cast<int>(initialValue));
93a37866
A
2571 }
2572
2573 static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr)
2574 {
2575 UNREACHABLE_FOR_PLATFORM();
2576 return CodeLocationLabel();
2577 }
2578
ed1e77d3
A
2579 static CodeLocationLabel startOfPatchableBranch32WithPatchOnAddress(CodeLocationDataLabel32)
2580 {
2581 UNREACHABLE_FOR_PLATFORM();
2582 return CodeLocationLabel();
2583 }
2584
81345200 2585 static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel, Address, void*)
93a37866
A
2586 {
2587 UNREACHABLE_FOR_PLATFORM();
2588 }
2589
ed1e77d3
A
2590 static void revertJumpReplacementToPatchableBranch32WithPatch(CodeLocationLabel, Address, int32_t)
2591 {
2592 UNREACHABLE_FOR_PLATFORM();
2593 }
2594
14957cd0
A
2595protected:
2596 SH4Assembler::Condition SH4Condition(RelationalCondition cond)
2597 {
2598 return static_cast<SH4Assembler::Condition>(cond);
2599 }
2600
2601 SH4Assembler::Condition SH4Condition(ResultCondition cond)
2602 {
2603 return static_cast<SH4Assembler::Condition>(cond);
2604 }
2605private:
2606 friend class LinkBuffer;
2607 friend class RepatchBuffer;
2608
93a37866
A
2609 static void linkCall(void* code, Call call, FunctionPtr function)
2610 {
2611 SH4Assembler::linkCall(code, call.m_label, function.value());
2612 }
2613
2614 static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
2615 {
2616 SH4Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
2617 }
2618
2619 static void repatchCall(CodeLocationCall call, FunctionPtr destination)
2620 {
2621 SH4Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
2622 }
14957cd0
A
2623};
2624
2625} // namespace JSC
2626
2627#endif // ENABLE(ASSEMBLER)
2628
2629#endif // MacroAssemblerSH4_h