Hoist JSVALUE32_64 arithmetic implementations into a separate file.
[WebKit-https.git] / JavaScriptCore / jit / JITArithmetic32_64.cpp
1 /*
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "JIT.h"
28
29 #if ENABLE(JIT)
30
31 #include "CodeBlock.h"
32 #include "JITInlineMethods.h"
33 #include "JITStubCall.h"
34 #include "JITStubs.h"
35 #include "JSArray.h"
36 #include "JSFunction.h"
37 #include "Interpreter.h"
38 #include "ResultType.h"
39 #include "SamplingTool.h"
40
41 #ifndef NDEBUG
42 #include <stdio.h>
43 #endif
44
45 using namespace std;
46
47 namespace JSC {
48
49 #if USE(JSVALUE32_64)
50
51 void JIT::emit_op_negate(Instruction* currentInstruction)
52 {
53     unsigned dst = currentInstruction[1].u.operand;
54     unsigned src = currentInstruction[2].u.operand;
55
56     emitLoad(src, regT1, regT0);
57
58     Jump srcNotInt = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
59     addSlowCase(branchTest32(Zero, regT0, Imm32(0x7fffffff)));
60     neg32(regT0);
61     emitStoreInt32(dst, regT0, (dst == src));
62
63     Jump end = jump();
64
65     srcNotInt.link(this);
66     addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
67
68     xor32(Imm32(1 << 31), regT1);
69     store32(regT1, tagFor(dst));
70     if (dst != src)
71         store32(regT0, payloadFor(dst));
72
73     end.link(this);
74 }
75
76 void JIT::emitSlow_op_negate(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
77 {
78     unsigned dst = currentInstruction[1].u.operand;
79
80     linkSlowCase(iter); // 0x7fffffff check
81     linkSlowCase(iter); // double check
82
83     JITStubCall stubCall(this, cti_op_negate);
84     stubCall.addArgument(regT1, regT0);
85     stubCall.call(dst);
86 }
87
88 void JIT::emit_op_jnless(Instruction* currentInstruction)
89 {
90     unsigned op1 = currentInstruction[1].u.operand;
91     unsigned op2 = currentInstruction[2].u.operand;
92     unsigned target = currentInstruction[3].u.operand;
93
94     JumpList notInt32Op1;
95     JumpList notInt32Op2;
96
97     // Int32 less.
98     if (isOperandConstantImmediateInt(op1)) {
99         emitLoad(op2, regT3, regT2);
100         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
101         addJump(branch32(LessThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
102     } else if (isOperandConstantImmediateInt(op2)) {
103         emitLoad(op1, regT1, regT0);
104         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
105         addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
106     } else {
107         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
108         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
109         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
110         addJump(branch32(GreaterThanOrEqual, regT0, regT2), target);
111     }
112
113     if (!supportsFloatingPoint()) {
114         addSlowCase(notInt32Op1);
115         addSlowCase(notInt32Op2);
116         return;
117     }
118     Jump end = jump();
119
120     // Double less.
121     emitBinaryDoubleOp(op_jnless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
122     end.link(this);
123 }
124
125 void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
126 {
127     unsigned op1 = currentInstruction[1].u.operand;
128     unsigned op2 = currentInstruction[2].u.operand;
129     unsigned target = currentInstruction[3].u.operand;
130
131     if (!supportsFloatingPoint()) {
132         if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
133             linkSlowCase(iter); // int32 check
134         linkSlowCase(iter); // int32 check
135     } else {
136         if (!isOperandConstantImmediateInt(op1)) {
137             linkSlowCase(iter); // double check
138             linkSlowCase(iter); // int32 check
139         }
140         if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))
141             linkSlowCase(iter); // double check
142     }
143
144     JITStubCall stubCall(this, cti_op_jless);
145     stubCall.addArgument(op1);
146     stubCall.addArgument(op2);
147     stubCall.call();
148     emitJumpSlowToHot(branchTest32(Zero, regT0), target);
149 }
150
151 void JIT::emit_op_jless(Instruction* currentInstruction)
152 {
153     unsigned op1 = currentInstruction[1].u.operand;
154     unsigned op2 = currentInstruction[2].u.operand;
155     unsigned target = currentInstruction[3].u.operand;
156
157     JumpList notInt32Op1;
158     JumpList notInt32Op2;
159
160     // Int32 less.
161     if (isOperandConstantImmediateInt(op1)) {
162         emitLoad(op2, regT3, regT2);
163         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
164         addJump(branch32(GreaterThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
165     } else if (isOperandConstantImmediateInt(op2)) {
166         emitLoad(op1, regT1, regT0);
167         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
168         addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
169     } else {
170         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
171         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
172         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
173         addJump(branch32(LessThan, regT0, regT2), target);
174     }
175
176     if (!supportsFloatingPoint()) {
177         addSlowCase(notInt32Op1);
178         addSlowCase(notInt32Op2);
179         return;
180     }
181     Jump end = jump();
182
183     // Double less.
184     emitBinaryDoubleOp(op_jless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
185     end.link(this);
186 }
187
188 void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
189 {
190     unsigned op1 = currentInstruction[1].u.operand;
191     unsigned op2 = currentInstruction[2].u.operand;
192     unsigned target = currentInstruction[3].u.operand;
193
194     if (!supportsFloatingPoint()) {
195         if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
196             linkSlowCase(iter); // int32 check
197         linkSlowCase(iter); // int32 check
198     } else {
199         if (!isOperandConstantImmediateInt(op1)) {
200             linkSlowCase(iter); // double check
201             linkSlowCase(iter); // int32 check
202         }
203         if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))
204             linkSlowCase(iter); // double check
205     }
206
207     JITStubCall stubCall(this, cti_op_jless);
208     stubCall.addArgument(op1);
209     stubCall.addArgument(op2);
210     stubCall.call();
211     emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
212 }
213
214 void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
215 {
216     unsigned op1 = currentInstruction[1].u.operand;
217     unsigned op2 = currentInstruction[2].u.operand;
218     unsigned target = currentInstruction[3].u.operand;
219
220     JumpList notInt32Op1;
221     JumpList notInt32Op2;
222
223     // Int32 less.
224     if (isOperandConstantImmediateInt(op1)) {
225         emitLoad(op2, regT3, regT2);
226         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
227         addJump(branch32(LessThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
228     } else if (isOperandConstantImmediateInt(op2)) {
229         emitLoad(op1, regT1, regT0);
230         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
231         addJump(branch32(GreaterThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
232     } else {
233         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
234         notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
235         notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
236         addJump(branch32(GreaterThan, regT0, regT2), target);
237     }
238
239     if (!supportsFloatingPoint()) {
240         addSlowCase(notInt32Op1);
241         addSlowCase(notInt32Op2);
242         return;
243     }
244     Jump end = jump();
245
246     // Double less.
247     emitBinaryDoubleOp(op_jnlesseq, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
248     end.link(this);
249 }
250
251 void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
252 {
253     unsigned op1 = currentInstruction[1].u.operand;
254     unsigned op2 = currentInstruction[2].u.operand;
255     unsigned target = currentInstruction[3].u.operand;
256
257     if (!supportsFloatingPoint()) {
258         if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
259             linkSlowCase(iter); // int32 check
260         linkSlowCase(iter); // int32 check
261     } else {
262         if (!isOperandConstantImmediateInt(op1)) {
263             linkSlowCase(iter); // double check
264             linkSlowCase(iter); // int32 check
265         }
266         if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))
267             linkSlowCase(iter); // double check
268     }
269
270     JITStubCall stubCall(this, cti_op_jlesseq);
271     stubCall.addArgument(op1);
272     stubCall.addArgument(op2);
273     stubCall.call();
274     emitJumpSlowToHot(branchTest32(Zero, regT0), target);
275 }
276
277 // LeftShift (<<)
278
279 void JIT::emit_op_lshift(Instruction* currentInstruction)
280 {
281     unsigned dst = currentInstruction[1].u.operand;
282     unsigned op1 = currentInstruction[2].u.operand;
283     unsigned op2 = currentInstruction[3].u.operand;
284
285     if (isOperandConstantImmediateInt(op2)) {
286         emitLoad(op1, regT1, regT0);
287         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
288         lshift32(Imm32(getConstantOperand(op2).asInt32()), regT0);
289         emitStoreInt32(dst, regT0, dst == op1);
290         return;
291     }
292
293     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
294     if (!isOperandConstantImmediateInt(op1))
295         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
296     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
297     lshift32(regT2, regT0);
298     emitStoreInt32(dst, regT0, dst == op1 || dst == op2);
299 }
300
301 void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
302 {
303     unsigned dst = currentInstruction[1].u.operand;
304     unsigned op1 = currentInstruction[2].u.operand;
305     unsigned op2 = currentInstruction[3].u.operand;
306
307     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
308         linkSlowCase(iter); // int32 check
309     linkSlowCase(iter); // int32 check
310
311     JITStubCall stubCall(this, cti_op_lshift);
312     stubCall.addArgument(op1);
313     stubCall.addArgument(op2);
314     stubCall.call(dst);
315 }
316
317 // RightShift (>>)
318
319 void JIT::emit_op_rshift(Instruction* currentInstruction)
320 {
321     unsigned dst = currentInstruction[1].u.operand;
322     unsigned op1 = currentInstruction[2].u.operand;
323     unsigned op2 = currentInstruction[3].u.operand;
324
325     if (isOperandConstantImmediateInt(op2)) {
326         emitLoad(op1, regT1, regT0);
327         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
328         rshift32(Imm32(getConstantOperand(op2).asInt32()), regT0);
329         emitStoreInt32(dst, regT0, dst == op1);
330         return;
331     }
332
333     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
334     if (!isOperandConstantImmediateInt(op1))
335         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
336     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
337     rshift32(regT2, regT0);
338     emitStoreInt32(dst, regT0, dst == op1 || dst == op2);
339 }
340
341 void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
342 {
343     unsigned dst = currentInstruction[1].u.operand;
344     unsigned op1 = currentInstruction[2].u.operand;
345     unsigned op2 = currentInstruction[3].u.operand;
346
347     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
348         linkSlowCase(iter); // int32 check
349     linkSlowCase(iter); // int32 check
350
351     JITStubCall stubCall(this, cti_op_rshift);
352     stubCall.addArgument(op1);
353     stubCall.addArgument(op2);
354     stubCall.call(dst);
355 }
356
357 // BitAnd (&)
358
359 void JIT::emit_op_bitand(Instruction* currentInstruction)
360 {
361     unsigned dst = currentInstruction[1].u.operand;
362     unsigned op1 = currentInstruction[2].u.operand;
363     unsigned op2 = currentInstruction[3].u.operand;
364
365     unsigned op;
366     int32_t constant;
367     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
368         emitLoad(op, regT1, regT0);
369         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
370         and32(Imm32(constant), regT0);
371         emitStoreInt32(dst, regT0, (op == dst));
372         return;
373     }
374
375     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
376     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
377     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
378     and32(regT2, regT0);
379     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
380 }
381
382 void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
383 {
384     unsigned dst = currentInstruction[1].u.operand;
385     unsigned op1 = currentInstruction[2].u.operand;
386     unsigned op2 = currentInstruction[3].u.operand;
387
388     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
389         linkSlowCase(iter); // int32 check
390     linkSlowCase(iter); // int32 check
391
392     JITStubCall stubCall(this, cti_op_bitand);
393     stubCall.addArgument(op1);
394     stubCall.addArgument(op2);
395     stubCall.call(dst);
396 }
397
398 // BitOr (|)
399
400 void JIT::emit_op_bitor(Instruction* currentInstruction)
401 {
402     unsigned dst = currentInstruction[1].u.operand;
403     unsigned op1 = currentInstruction[2].u.operand;
404     unsigned op2 = currentInstruction[3].u.operand;
405
406     unsigned op;
407     int32_t constant;
408     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
409         emitLoad(op, regT1, regT0);
410         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
411         or32(Imm32(constant), regT0);
412         emitStoreInt32(dst, regT0, (op == dst));
413         return;
414     }
415
416     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
417     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
418     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
419     or32(regT2, regT0);
420     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
421 }
422
423 void JIT::emitSlow_op_bitor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
424 {
425     unsigned dst = currentInstruction[1].u.operand;
426     unsigned op1 = currentInstruction[2].u.operand;
427     unsigned op2 = currentInstruction[3].u.operand;
428
429     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
430         linkSlowCase(iter); // int32 check
431     linkSlowCase(iter); // int32 check
432
433     JITStubCall stubCall(this, cti_op_bitor);
434     stubCall.addArgument(op1);
435     stubCall.addArgument(op2);
436     stubCall.call(dst);
437 }
438
439 // BitXor (^)
440
441 void JIT::emit_op_bitxor(Instruction* currentInstruction)
442 {
443     unsigned dst = currentInstruction[1].u.operand;
444     unsigned op1 = currentInstruction[2].u.operand;
445     unsigned op2 = currentInstruction[3].u.operand;
446
447     unsigned op;
448     int32_t constant;
449     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
450         emitLoad(op, regT1, regT0);
451         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
452         xor32(Imm32(constant), regT0);
453         emitStoreInt32(dst, regT0, (op == dst));
454         return;
455     }
456
457     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
458     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
459     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
460     xor32(regT2, regT0);
461     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
462 }
463
464 void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
465 {
466     unsigned dst = currentInstruction[1].u.operand;
467     unsigned op1 = currentInstruction[2].u.operand;
468     unsigned op2 = currentInstruction[3].u.operand;
469
470     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
471         linkSlowCase(iter); // int32 check
472     linkSlowCase(iter); // int32 check
473
474     JITStubCall stubCall(this, cti_op_bitxor);
475     stubCall.addArgument(op1);
476     stubCall.addArgument(op2);
477     stubCall.call(dst);
478 }
479
480 // BitNot (~)
481
482 void JIT::emit_op_bitnot(Instruction* currentInstruction)
483 {
484     unsigned dst = currentInstruction[1].u.operand;
485     unsigned src = currentInstruction[2].u.operand;
486
487     emitLoad(src, regT1, regT0);
488     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
489
490     not32(regT0);
491     emitStoreInt32(dst, regT0, (dst == src));
492 }
493
494 void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
495 {
496     unsigned dst = currentInstruction[1].u.operand;
497
498     linkSlowCase(iter); // int32 check
499
500     JITStubCall stubCall(this, cti_op_bitnot);
501     stubCall.addArgument(regT1, regT0);
502     stubCall.call(dst);
503 }
504
505 // PostInc (i++)
506
507 void JIT::emit_op_post_inc(Instruction* currentInstruction)
508 {
509     unsigned dst = currentInstruction[1].u.operand;
510     unsigned srcDst = currentInstruction[2].u.operand;
511
512     emitLoad(srcDst, regT1, regT0);
513     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
514
515     if (dst == srcDst) // x = x++ is a noop for ints.
516         return;
517
518     emitStoreInt32(dst, regT0);
519
520     addSlowCase(branchAdd32(Overflow, Imm32(1), regT0));
521     emitStoreInt32(srcDst, regT0, true);
522 }
523
524 void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
525 {
526     unsigned dst = currentInstruction[1].u.operand;
527     unsigned srcDst = currentInstruction[2].u.operand;
528
529     linkSlowCase(iter); // int32 check
530     if (dst != srcDst)
531         linkSlowCase(iter); // overflow check
532
533     JITStubCall stubCall(this, cti_op_post_inc);
534     stubCall.addArgument(srcDst);
535     stubCall.addArgument(Imm32(srcDst));
536     stubCall.call(dst);
537 }
538
539 // PostDec (i--)
540
541 void JIT::emit_op_post_dec(Instruction* currentInstruction)
542 {
543     unsigned dst = currentInstruction[1].u.operand;
544     unsigned srcDst = currentInstruction[2].u.operand;
545
546     emitLoad(srcDst, regT1, regT0);
547     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
548
549     if (dst == srcDst) // x = x-- is a noop for ints.
550         return;
551
552     emitStoreInt32(dst, regT0);
553
554     addSlowCase(branchSub32(Overflow, Imm32(1), regT0));
555     emitStoreInt32(srcDst, regT0, true);
556 }
557
558 void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
559 {
560     unsigned dst = currentInstruction[1].u.operand;
561     unsigned srcDst = currentInstruction[2].u.operand;
562
563     linkSlowCase(iter); // int32 check
564     if (dst != srcDst)
565         linkSlowCase(iter); // overflow check
566
567     JITStubCall stubCall(this, cti_op_post_dec);
568     stubCall.addArgument(srcDst);
569     stubCall.addArgument(Imm32(srcDst));
570     stubCall.call(dst);
571 }
572
573 // PreInc (++i)
574
575 void JIT::emit_op_pre_inc(Instruction* currentInstruction)
576 {
577     unsigned srcDst = currentInstruction[1].u.operand;
578
579     emitLoad(srcDst, regT1, regT0);
580
581     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
582     addSlowCase(branchAdd32(Overflow, Imm32(1), regT0));
583     emitStoreInt32(srcDst, regT0, true);
584 }
585
586 void JIT::emitSlow_op_pre_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
587 {
588     unsigned srcDst = currentInstruction[1].u.operand;
589
590     linkSlowCase(iter); // int32 check
591     linkSlowCase(iter); // overflow check
592
593     JITStubCall stubCall(this, cti_op_pre_inc);
594     stubCall.addArgument(srcDst);
595     stubCall.call(srcDst);
596 }
597
598 // PreDec (--i)
599
600 void JIT::emit_op_pre_dec(Instruction* currentInstruction)
601 {
602     unsigned srcDst = currentInstruction[1].u.operand;
603
604     emitLoad(srcDst, regT1, regT0);
605
606     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
607     addSlowCase(branchSub32(Overflow, Imm32(1), regT0));
608     emitStoreInt32(srcDst, regT0, true);
609 }
610
611 void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
612 {
613     unsigned srcDst = currentInstruction[1].u.operand;
614
615     linkSlowCase(iter); // int32 check
616     linkSlowCase(iter); // overflow check
617
618     JITStubCall stubCall(this, cti_op_pre_dec);
619     stubCall.addArgument(srcDst);
620     stubCall.call(srcDst);
621 }
622
623 // Addition (+)
624
625 void JIT::emit_op_add(Instruction* currentInstruction)
626 {
627     unsigned dst = currentInstruction[1].u.operand;
628     unsigned op1 = currentInstruction[2].u.operand;
629     unsigned op2 = currentInstruction[3].u.operand;
630     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
631
632     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
633         JITStubCall stubCall(this, cti_op_add);
634         stubCall.addArgument(op1);
635         stubCall.addArgument(op2);
636         stubCall.call(dst);
637         return;
638     }
639
640     JumpList notInt32Op1;
641     JumpList notInt32Op2;
642
643     unsigned op;
644     int32_t constant;
645     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
646         emitAdd32Constant(dst, op, constant, op == op1 ? types.first() : types.second());
647         return;
648     }
649
650     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
651     notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
652     notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
653
654     // Int32 case.
655     addSlowCase(branchAdd32(Overflow, regT2, regT0));
656     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
657
658     if (!supportsFloatingPoint()) {
659         addSlowCase(notInt32Op1);
660         addSlowCase(notInt32Op2);
661         return;
662     }
663     Jump end = jump();
664
665     // Double case.
666     emitBinaryDoubleOp(op_add, dst, op1, op2, types, notInt32Op1, notInt32Op2);
667     end.link(this);
668 }
669
670 void JIT::emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType)
671 {
672     // Int32 case.
673     emitLoad(op, regT1, regT0);
674     Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
675     addSlowCase(branchAdd32(Overflow, Imm32(constant), regT0));
676     emitStoreInt32(dst, regT0, (op == dst));
677
678     // Double case.
679     if (!supportsFloatingPoint()) {
680         addSlowCase(notInt32);
681         return;
682     }
683     Jump end = jump();
684
685     notInt32.link(this);
686     if (!opType.definitelyIsNumber())
687         addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
688     move(Imm32(constant), regT2);
689     convertInt32ToDouble(regT2, fpRegT0);
690     emitLoadDouble(op, fpRegT1);
691     addDouble(fpRegT1, fpRegT0);
692     emitStoreDouble(dst, fpRegT0);
693
694     end.link(this);
695 }
696
697 void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
698 {
699     unsigned dst = currentInstruction[1].u.operand;
700     unsigned op1 = currentInstruction[2].u.operand;
701     unsigned op2 = currentInstruction[3].u.operand;
702     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
703
704     if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
705         return;
706
707     unsigned op;
708     int32_t constant;
709     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
710         linkSlowCase(iter); // overflow check
711
712         if (!supportsFloatingPoint())
713             linkSlowCase(iter); // non-sse case
714         else {
715             ResultType opType = op == op1 ? types.first() : types.second();
716             if (!opType.definitelyIsNumber())
717                 linkSlowCase(iter); // double check
718         }
719     } else {
720         linkSlowCase(iter); // overflow check
721
722         if (!supportsFloatingPoint()) {
723             linkSlowCase(iter); // int32 check
724             linkSlowCase(iter); // int32 check
725         } else {
726             if (!types.first().definitelyIsNumber())
727                 linkSlowCase(iter); // double check
728
729             if (!types.second().definitelyIsNumber()) {
730                 linkSlowCase(iter); // int32 check
731                 linkSlowCase(iter); // double check
732             }
733         }
734     }
735
736     JITStubCall stubCall(this, cti_op_add);
737     stubCall.addArgument(op1);
738     stubCall.addArgument(op2);
739     stubCall.call(dst);
740 }
741
742 // Subtraction (-)
743
744 void JIT::emit_op_sub(Instruction* currentInstruction)
745 {
746     unsigned dst = currentInstruction[1].u.operand;
747     unsigned op1 = currentInstruction[2].u.operand;
748     unsigned op2 = currentInstruction[3].u.operand;
749     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
750
751     JumpList notInt32Op1;
752     JumpList notInt32Op2;
753
754     if (isOperandConstantImmediateInt(op2)) {
755         emitSub32Constant(dst, op1, getConstantOperand(op2).asInt32(), types.first());
756         return;
757     }
758
759     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
760     notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
761     notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
762
763     // Int32 case.
764     addSlowCase(branchSub32(Overflow, regT2, regT0));
765     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
766
767     if (!supportsFloatingPoint()) {
768         addSlowCase(notInt32Op1);
769         addSlowCase(notInt32Op2);
770         return;
771     }
772     Jump end = jump();
773
774     // Double case.
775     emitBinaryDoubleOp(op_sub, dst, op1, op2, types, notInt32Op1, notInt32Op2);
776     end.link(this);
777 }
778
779 void JIT::emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType)
780 {
781     // Int32 case.
782     emitLoad(op, regT1, regT0);
783     Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
784     addSlowCase(branchSub32(Overflow, Imm32(constant), regT0));
785     emitStoreInt32(dst, regT0, (op == dst));
786
787     // Double case.
788     if (!supportsFloatingPoint()) {
789         addSlowCase(notInt32);
790         return;
791     }
792     Jump end = jump();
793
794     notInt32.link(this);
795     if (!opType.definitelyIsNumber())
796         addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
797     move(Imm32(constant), regT2);
798     convertInt32ToDouble(regT2, fpRegT0);
799     emitLoadDouble(op, fpRegT1);
800     subDouble(fpRegT0, fpRegT1);
801     emitStoreDouble(dst, fpRegT1);
802
803     end.link(this);
804 }
805
806 void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
807 {
808     unsigned dst = currentInstruction[1].u.operand;
809     unsigned op1 = currentInstruction[2].u.operand;
810     unsigned op2 = currentInstruction[3].u.operand;
811     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
812
813     if (isOperandConstantImmediateInt(op2)) {
814         linkSlowCase(iter); // overflow check
815
816         if (!supportsFloatingPoint() || !types.first().definitelyIsNumber())
817             linkSlowCase(iter); // int32 or double check
818     } else {
819         linkSlowCase(iter); // overflow check
820
821         if (!supportsFloatingPoint()) {
822             linkSlowCase(iter); // int32 check
823             linkSlowCase(iter); // int32 check
824         } else {
825             if (!types.first().definitelyIsNumber())
826                 linkSlowCase(iter); // double check
827
828             if (!types.second().definitelyIsNumber()) {
829                 linkSlowCase(iter); // int32 check
830                 linkSlowCase(iter); // double check
831             }
832         }
833     }
834
835     JITStubCall stubCall(this, cti_op_sub);
836     stubCall.addArgument(op1);
837     stubCall.addArgument(op2);
838     stubCall.call(dst);
839 }
840
841 void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsigned op2, OperandTypes types, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters, bool op2IsInRegisters)
842 {
843     JumpList end;
844
845     if (!notInt32Op1.empty()) {
846         // Double case 1: Op1 is not int32; Op2 is unknown.
847         notInt32Op1.link(this);
848
849         ASSERT(op1IsInRegisters);
850
851         // Verify Op1 is double.
852         if (!types.first().definitelyIsNumber())
853             addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
854
855         if (!op2IsInRegisters)
856             emitLoad(op2, regT3, regT2);
857
858         Jump doubleOp2 = branch32(Below, regT3, Imm32(JSValue::LowestTag));
859
860         if (!types.second().definitelyIsNumber())
861             addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
862
863         convertInt32ToDouble(regT2, fpRegT0);
864         Jump doTheMath = jump();
865
866         // Load Op2 as double into double register.
867         doubleOp2.link(this);
868         emitLoadDouble(op2, fpRegT0);
869
870         // Do the math.
871         doTheMath.link(this);
872         switch (opcodeID) {
873             case op_mul:
874                 emitLoadDouble(op1, fpRegT2);
875                 mulDouble(fpRegT2, fpRegT0);
876                 emitStoreDouble(dst, fpRegT0);
877                 break;
878             case op_add:
879                 emitLoadDouble(op1, fpRegT2);
880                 addDouble(fpRegT2, fpRegT0);
881                 emitStoreDouble(dst, fpRegT0);
882                 break;
883             case op_sub:
884                 emitLoadDouble(op1, fpRegT1);
885                 subDouble(fpRegT0, fpRegT1);
886                 emitStoreDouble(dst, fpRegT1);
887                 break;
888             case op_div:
889                 emitLoadDouble(op1, fpRegT1);
890                 divDouble(fpRegT0, fpRegT1);
891                 emitStoreDouble(dst, fpRegT1);
892                 break;
893             case op_jnless:
894                 emitLoadDouble(op1, fpRegT2);
895                 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT0, fpRegT2), dst);
896                 break;
897             case op_jless:
898                 emitLoadDouble(op1, fpRegT2);
899                 addJump(branchDouble(DoubleLessThan, fpRegT2, fpRegT0), dst);
900                 break;
901             case op_jnlesseq:
902                 emitLoadDouble(op1, fpRegT2);
903                 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT0, fpRegT2), dst);
904                 break;
905             default:
906                 ASSERT_NOT_REACHED();
907         }
908
909         if (!notInt32Op2.empty())
910             end.append(jump());
911     }
912
913     if (!notInt32Op2.empty()) {
914         // Double case 2: Op1 is int32; Op2 is not int32.
915         notInt32Op2.link(this);
916
917         ASSERT(op2IsInRegisters);
918
919         if (!op1IsInRegisters)
920             emitLoadPayload(op1, regT0);
921
922         convertInt32ToDouble(regT0, fpRegT0);
923
924         // Verify op2 is double.
925         if (!types.second().definitelyIsNumber())
926             addSlowCase(branch32(Above, regT3, Imm32(JSValue::LowestTag)));
927
928         // Do the math.
929         switch (opcodeID) {
930             case op_mul:
931                 emitLoadDouble(op2, fpRegT2);
932                 mulDouble(fpRegT2, fpRegT0);
933                 emitStoreDouble(dst, fpRegT0);
934                 break;
935             case op_add:
936                 emitLoadDouble(op2, fpRegT2);
937                 addDouble(fpRegT2, fpRegT0);
938                 emitStoreDouble(dst, fpRegT0);
939                 break;
940             case op_sub:
941                 emitLoadDouble(op2, fpRegT2);
942                 subDouble(fpRegT2, fpRegT0);
943                 emitStoreDouble(dst, fpRegT0);
944                 break;
945             case op_div:
946                 emitLoadDouble(op2, fpRegT2);
947                 divDouble(fpRegT2, fpRegT0);
948                 emitStoreDouble(dst, fpRegT0);
949                 break;
950             case op_jnless:
951                 emitLoadDouble(op2, fpRegT1);
952                 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), dst);
953                 break;
954             case op_jless:
955                 emitLoadDouble(op2, fpRegT1);
956                 addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), dst);
957                 break;
958             case op_jnlesseq:
959                 emitLoadDouble(op2, fpRegT1);
960                 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), dst);
961                 break;
962             default:
963                 ASSERT_NOT_REACHED();
964         }
965     }
966
967     end.link(this);
968 }
969
970 // Multiplication (*)
971
972 void JIT::emit_op_mul(Instruction* currentInstruction)
973 {
974     unsigned dst = currentInstruction[1].u.operand;
975     unsigned op1 = currentInstruction[2].u.operand;
976     unsigned op2 = currentInstruction[3].u.operand;
977     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
978
979     JumpList notInt32Op1;
980     JumpList notInt32Op2;
981
982     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
983     notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
984     notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
985
986     // Int32 case.
987     move(regT0, regT3);
988     addSlowCase(branchMul32(Overflow, regT2, regT0));
989     addSlowCase(branchTest32(Zero, regT0));
990     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
991
992     if (!supportsFloatingPoint()) {
993         addSlowCase(notInt32Op1);
994         addSlowCase(notInt32Op2);
995         return;
996     }
997     Jump end = jump();
998
999     // Double case.
1000     emitBinaryDoubleOp(op_mul, dst, op1, op2, types, notInt32Op1, notInt32Op2);
1001     end.link(this);
1002 }
1003
1004 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1005 {
1006     unsigned dst = currentInstruction[1].u.operand;
1007     unsigned op1 = currentInstruction[2].u.operand;
1008     unsigned op2 = currentInstruction[3].u.operand;
1009     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1010
1011     Jump overflow = getSlowCase(iter); // overflow check
1012     linkSlowCase(iter); // zero result check
1013
1014     Jump negZero = branchOr32(Signed, regT2, regT3);
1015     emitStoreInt32(dst, Imm32(0), (op1 == dst || op2 == dst));
1016
1017     emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_mul));
1018
1019     negZero.link(this);
1020     overflow.link(this);
1021
1022     if (!supportsFloatingPoint()) {
1023         linkSlowCase(iter); // int32 check
1024         linkSlowCase(iter); // int32 check
1025     }
1026
1027     if (supportsFloatingPoint()) {
1028         if (!types.first().definitelyIsNumber())
1029             linkSlowCase(iter); // double check
1030
1031         if (!types.second().definitelyIsNumber()) {
1032             linkSlowCase(iter); // int32 check
1033             linkSlowCase(iter); // double check
1034         }
1035     }
1036
1037     Label jitStubCall(this);
1038     JITStubCall stubCall(this, cti_op_mul);
1039     stubCall.addArgument(op1);
1040     stubCall.addArgument(op2);
1041     stubCall.call(dst);
1042 }
1043
1044 // Division (/)
1045
1046 void JIT::emit_op_div(Instruction* currentInstruction)
1047 {
1048     unsigned dst = currentInstruction[1].u.operand;
1049     unsigned op1 = currentInstruction[2].u.operand;
1050     unsigned op2 = currentInstruction[3].u.operand;
1051     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1052
1053     if (!supportsFloatingPoint()) {
1054         addSlowCase(jump());
1055         return;
1056     }
1057
1058     // Int32 divide.
1059     JumpList notInt32Op1;
1060     JumpList notInt32Op2;
1061
1062     JumpList end;
1063
1064     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
1065
1066     notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
1067     notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
1068
1069     convertInt32ToDouble(regT0, fpRegT0);
1070     convertInt32ToDouble(regT2, fpRegT1);
1071     divDouble(fpRegT1, fpRegT0);
1072
1073     JumpList doubleResult;
1074     branchConvertDoubleToInt32(fpRegT0, regT0, doubleResult, fpRegT1);
1075
1076     // Int32 result.
1077     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
1078     end.append(jump());
1079
1080     // Double result.
1081     doubleResult.link(this);
1082     emitStoreDouble(dst, fpRegT0);
1083     end.append(jump());
1084
1085     // Double divide.
1086     emitBinaryDoubleOp(op_div, dst, op1, op2, types, notInt32Op1, notInt32Op2);
1087     end.link(this);
1088 }
1089
1090 void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1091 {
1092     unsigned dst = currentInstruction[1].u.operand;
1093     unsigned op1 = currentInstruction[2].u.operand;
1094     unsigned op2 = currentInstruction[3].u.operand;
1095     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1096
1097     if (!supportsFloatingPoint())
1098         linkSlowCase(iter);
1099     else {
1100         if (!types.first().definitelyIsNumber())
1101             linkSlowCase(iter); // double check
1102
1103         if (!types.second().definitelyIsNumber()) {
1104             linkSlowCase(iter); // int32 check
1105             linkSlowCase(iter); // double check
1106         }
1107     }
1108
1109     JITStubCall stubCall(this, cti_op_div);
1110     stubCall.addArgument(op1);
1111     stubCall.addArgument(op2);
1112     stubCall.call(dst);
1113 }
1114
1115 // Mod (%)
1116
1117 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
1118
1119 #if CPU(X86) || CPU(X86_64)
1120
1121 void JIT::emit_op_mod(Instruction* currentInstruction)
1122 {
1123     unsigned dst = currentInstruction[1].u.operand;
1124     unsigned op1 = currentInstruction[2].u.operand;
1125     unsigned op2 = currentInstruction[3].u.operand;
1126
1127     if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) {
1128         emitLoad(op1, X86Registers::edx, X86Registers::eax);
1129         move(Imm32(getConstantOperand(op2).asInt32()), X86Registers::ecx);
1130         addSlowCase(branch32(NotEqual, X86Registers::edx, Imm32(JSValue::Int32Tag)));
1131         if (getConstantOperand(op2).asInt32() == -1)
1132             addSlowCase(branch32(Equal, X86Registers::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
1133     } else {
1134         emitLoad2(op1, X86Registers::edx, X86Registers::eax, op2, X86Registers::ebx, X86Registers::ecx);
1135         addSlowCase(branch32(NotEqual, X86Registers::edx, Imm32(JSValue::Int32Tag)));
1136         addSlowCase(branch32(NotEqual, X86Registers::ebx, Imm32(JSValue::Int32Tag)));
1137
1138         addSlowCase(branch32(Equal, X86Registers::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
1139         addSlowCase(branch32(Equal, X86Registers::ecx, Imm32(0))); // divide by 0
1140     }
1141
1142     move(X86Registers::eax, X86Registers::ebx); // Save dividend payload, in case of 0.
1143     m_assembler.cdq();
1144     m_assembler.idivl_r(X86Registers::ecx);
1145
1146     // If the remainder is zero and the dividend is negative, the result is -0.
1147     Jump storeResult1 = branchTest32(NonZero, X86Registers::edx);
1148     Jump storeResult2 = branchTest32(Zero, X86Registers::ebx, Imm32(0x80000000)); // not negative
1149     emitStore(dst, jsNumber(m_globalData, -0.0));
1150     Jump end = jump();
1151
1152     storeResult1.link(this);
1153     storeResult2.link(this);
1154     emitStoreInt32(dst, X86Registers::edx, (op1 == dst || op2 == dst));
1155     end.link(this);
1156 }
1157
1158 void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1159 {
1160     unsigned dst = currentInstruction[1].u.operand;
1161     unsigned op1 = currentInstruction[2].u.operand;
1162     unsigned op2 = currentInstruction[3].u.operand;
1163
1164     if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) {
1165         linkSlowCase(iter); // int32 check
1166         if (getConstantOperand(op2).asInt32() == -1)
1167             linkSlowCase(iter); // 0x80000000 check
1168     } else {
1169         linkSlowCase(iter); // int32 check
1170         linkSlowCase(iter); // int32 check
1171         linkSlowCase(iter); // 0 check
1172         linkSlowCase(iter); // 0x80000000 check
1173     }
1174
1175     JITStubCall stubCall(this, cti_op_mod);
1176     stubCall.addArgument(op1);
1177     stubCall.addArgument(op2);
1178     stubCall.call(dst);
1179 }
1180
1181 #else // CPU(X86) || CPU(X86_64)
1182
1183 void JIT::emit_op_mod(Instruction* currentInstruction)
1184 {
1185     unsigned dst = currentInstruction[1].u.operand;
1186     unsigned op1 = currentInstruction[2].u.operand;
1187     unsigned op2 = currentInstruction[3].u.operand;
1188
1189 #if ENABLE(JIT_OPTIMIZE_MOD)
1190     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
1191     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
1192     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
1193
1194     addSlowCase(branch32(Equal, regT2, Imm32(0)));
1195
1196     emitNakedCall(m_globalData->jitStubs.ctiSoftModulo());
1197
1198     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
1199 #else
1200     JITStubCall stubCall(this, cti_op_mod);
1201     stubCall.addArgument(op1);
1202     stubCall.addArgument(op2);
1203     stubCall.call(dst);
1204 #endif
1205 }
1206
1207 void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1208 {
1209 #if ENABLE(JIT_OPTIMIZE_MOD)
1210     unsigned result = currentInstruction[1].u.operand;
1211     unsigned op1 = currentInstruction[2].u.operand;
1212     unsigned op2 = currentInstruction[3].u.operand;
1213     linkSlowCase(iter);
1214     linkSlowCase(iter);
1215     linkSlowCase(iter);
1216     JITStubCall stubCall(this, cti_op_mod);
1217     stubCall.addArgument(op1);
1218     stubCall.addArgument(op2);
1219     stubCall.call(result);
1220 #else
1221     ASSERT_NOT_REACHED();
1222 #endif
1223 }
1224
1225 #endif // CPU(X86) || CPU(X86_64)
1226
1227 /* ------------------------------ END: OP_MOD ------------------------------ */
1228
1229 #endif // USE(JSVALUE32_64)
1230
1231 }
1232
1233 #endif // ENABLE(JIT)