1b9e55e5f5529b7091e007c7a527b54f2d6eb678
[WebKit.git] / JavaScriptCore / jit / JITArithmetic.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 "JSArray.h"
35 #include "JSFunction.h"
36 #include "Interpreter.h"
37 #include "ResultType.h"
38 #include "SamplingTool.h"
39
40 #ifndef NDEBUG
41 #include <stdio.h>
42 #endif
43
44 using namespace std;
45
46 namespace JSC {
47
48 #if USE(JSVALUE32_64)
49
50 void JIT::emit_op_negate(Instruction* currentInstruction)
51 {
52     unsigned dst = currentInstruction[1].u.operand;
53     unsigned src = currentInstruction[2].u.operand;
54
55     emitLoad(src, regT1, regT0);
56
57     Jump srcNotInt = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
58     addSlowCase(branch32(Equal, regT0, Imm32(0)));
59
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); // 0 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 PLATFORM(X86) || PLATFORM(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 // PLATFORM(X86) || PLATFORM(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     JITStubCall stubCall(this, cti_op_mod);
1190     stubCall.addArgument(op1);
1191     stubCall.addArgument(op2);
1192     stubCall.call(dst);
1193 }
1194
1195 void JIT::emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&)
1196 {
1197 }
1198
1199 #endif // PLATFORM(X86) || PLATFORM(X86_64)
1200
1201 /* ------------------------------ END: OP_MOD ------------------------------ */
1202
1203 #else // USE(JSVALUE32_64)
1204
1205 void JIT::emit_op_lshift(Instruction* currentInstruction)
1206 {
1207     unsigned result = currentInstruction[1].u.operand;
1208     unsigned op1 = currentInstruction[2].u.operand;
1209     unsigned op2 = currentInstruction[3].u.operand;
1210
1211     emitGetVirtualRegisters(op1, regT0, op2, regT2);
1212     // FIXME: would we be better using 'emitJumpSlowCaseIfNotImmediateIntegers'? - we *probably* ought to be consistent.
1213     emitJumpSlowCaseIfNotImmediateInteger(regT0);
1214     emitJumpSlowCaseIfNotImmediateInteger(regT2);
1215     emitFastArithImmToInt(regT0);
1216     emitFastArithImmToInt(regT2);
1217     lshift32(regT2, regT0);
1218 #if USE(JSVALUE32)
1219     addSlowCase(branchAdd32(Overflow, regT0, regT0));
1220     signExtend32ToPtr(regT0, regT0);
1221 #endif
1222     emitFastArithReTagImmediate(regT0, regT0);
1223     emitPutVirtualRegister(result);
1224 }
1225
1226 void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1227 {
1228     unsigned result = currentInstruction[1].u.operand;
1229     unsigned op1 = currentInstruction[2].u.operand;
1230     unsigned op2 = currentInstruction[3].u.operand;
1231
1232 #if USE(JSVALUE64)
1233     UNUSED_PARAM(op1);
1234     UNUSED_PARAM(op2);
1235     linkSlowCase(iter);
1236     linkSlowCase(iter);
1237 #else
1238     // If we are limited to 32-bit immediates there is a third slow case, which required the operands to have been reloaded.
1239     Jump notImm1 = getSlowCase(iter);
1240     Jump notImm2 = getSlowCase(iter);
1241     linkSlowCase(iter);
1242     emitGetVirtualRegisters(op1, regT0, op2, regT2);
1243     notImm1.link(this);
1244     notImm2.link(this);
1245 #endif
1246     JITStubCall stubCall(this, cti_op_lshift);
1247     stubCall.addArgument(regT0);
1248     stubCall.addArgument(regT2);
1249     stubCall.call(result);
1250 }
1251
1252 void JIT::emit_op_rshift(Instruction* currentInstruction)
1253 {
1254     unsigned result = currentInstruction[1].u.operand;
1255     unsigned op1 = currentInstruction[2].u.operand;
1256     unsigned op2 = currentInstruction[3].u.operand;
1257
1258     if (isOperandConstantImmediateInt(op2)) {
1259         // isOperandConstantImmediateInt(op2) => 1 SlowCase
1260         emitGetVirtualRegister(op1, regT0);
1261         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1262         // Mask with 0x1f as per ecma-262 11.7.2 step 7.
1263         rshift32(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), regT0);
1264     } else {
1265         emitGetVirtualRegisters(op1, regT0, op2, regT2);
1266         if (supportsFloatingPointTruncate()) {
1267             Jump lhsIsInt = emitJumpIfImmediateInteger(regT0);
1268 #if USE(JSVALUE64)
1269             // supportsFloatingPoint() && USE(JSVALUE64) => 3 SlowCases
1270             addSlowCase(emitJumpIfNotImmediateNumber(regT0));
1271             addPtr(tagTypeNumberRegister, regT0);
1272             movePtrToDouble(regT0, fpRegT0);
1273             addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0));
1274 #else
1275             // supportsFloatingPoint() && !USE(JSVALUE64) => 5 SlowCases (of which 1 IfNotJSCell)
1276             emitJumpSlowCaseIfNotJSCell(regT0, op1);
1277             addSlowCase(checkStructure(regT0, m_globalData->numberStructure.get()));
1278             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1279             addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0));
1280             addSlowCase(branchAdd32(Overflow, regT0, regT0));
1281 #endif
1282             lhsIsInt.link(this);
1283             emitJumpSlowCaseIfNotImmediateInteger(regT2);
1284         } else {
1285             // !supportsFloatingPoint() => 2 SlowCases
1286             emitJumpSlowCaseIfNotImmediateInteger(regT0);
1287             emitJumpSlowCaseIfNotImmediateInteger(regT2);
1288         }
1289         emitFastArithImmToInt(regT2);
1290         rshift32(regT2, regT0);
1291 #if USE(JSVALUE32)
1292         signExtend32ToPtr(regT0, regT0);
1293 #endif
1294     }
1295 #if USE(JSVALUE64)
1296     emitFastArithIntToImmNoCheck(regT0, regT0);
1297 #else
1298     orPtr(Imm32(JSImmediate::TagTypeNumber), regT0);
1299 #endif
1300     emitPutVirtualRegister(result);
1301 }
1302
1303 void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1304 {
1305     unsigned result = currentInstruction[1].u.operand;
1306     unsigned op1 = currentInstruction[2].u.operand;
1307     unsigned op2 = currentInstruction[3].u.operand;
1308
1309     JITStubCall stubCall(this, cti_op_rshift);
1310
1311     if (isOperandConstantImmediateInt(op2)) {
1312         linkSlowCase(iter);
1313         stubCall.addArgument(regT0);
1314         stubCall.addArgument(op2, regT2);
1315     } else {
1316         if (supportsFloatingPointTruncate()) {
1317 #if USE(JSVALUE64)
1318             linkSlowCase(iter);
1319             linkSlowCase(iter);
1320             linkSlowCase(iter);
1321 #else
1322             linkSlowCaseIfNotJSCell(iter, op1);
1323             linkSlowCase(iter);
1324             linkSlowCase(iter);
1325             linkSlowCase(iter);
1326             linkSlowCase(iter);
1327 #endif
1328             // We're reloading op1 to regT0 as we can no longer guarantee that
1329             // we have not munged the operand.  It may have already been shifted
1330             // correctly, but it still will not have been tagged.
1331             stubCall.addArgument(op1, regT0);
1332             stubCall.addArgument(regT2);
1333         } else {
1334             linkSlowCase(iter);
1335             linkSlowCase(iter);
1336             stubCall.addArgument(regT0);
1337             stubCall.addArgument(regT2);
1338         }
1339     }
1340
1341     stubCall.call(result);
1342 }
1343
1344 void JIT::emit_op_jnless(Instruction* currentInstruction)
1345 {
1346     unsigned op1 = currentInstruction[1].u.operand;
1347     unsigned op2 = currentInstruction[2].u.operand;
1348     unsigned target = currentInstruction[3].u.operand;
1349
1350     // We generate inline code for the following cases in the fast path:
1351     // - int immediate to constant int immediate
1352     // - constant int immediate to int immediate
1353     // - int immediate to int immediate
1354
1355     if (isOperandConstantImmediateInt(op2)) {
1356         emitGetVirtualRegister(op1, regT0);
1357         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1358 #if USE(JSVALUE64)
1359         int32_t op2imm = getConstantOperandImmediateInt(op2);
1360 #else
1361         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
1362 #endif
1363         addJump(branch32(GreaterThanOrEqual, regT0, Imm32(op2imm)), target);
1364     } else if (isOperandConstantImmediateInt(op1)) {
1365         emitGetVirtualRegister(op2, regT1);
1366         emitJumpSlowCaseIfNotImmediateInteger(regT1);
1367 #if USE(JSVALUE64)
1368         int32_t op1imm = getConstantOperandImmediateInt(op1);
1369 #else
1370         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
1371 #endif
1372         addJump(branch32(LessThanOrEqual, regT1, Imm32(op1imm)), target);
1373     } else {
1374         emitGetVirtualRegisters(op1, regT0, op2, regT1);
1375         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1376         emitJumpSlowCaseIfNotImmediateInteger(regT1);
1377
1378         addJump(branch32(GreaterThanOrEqual, regT0, regT1), target);
1379     }
1380 }
1381
1382 void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1383 {
1384     unsigned op1 = currentInstruction[1].u.operand;
1385     unsigned op2 = currentInstruction[2].u.operand;
1386     unsigned target = currentInstruction[3].u.operand;
1387
1388     // We generate inline code for the following cases in the slow path:
1389     // - floating-point number to constant int immediate
1390     // - constant int immediate to floating-point number
1391     // - floating-point number to floating-point number.
1392
1393     if (isOperandConstantImmediateInt(op2)) {
1394         linkSlowCase(iter);
1395
1396         if (supportsFloatingPoint()) {
1397 #if USE(JSVALUE64)
1398             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
1399             addPtr(tagTypeNumberRegister, regT0);
1400             movePtrToDouble(regT0, fpRegT0);
1401 #else
1402             Jump fail1;
1403             if (!m_codeBlock->isKnownNotImmediate(op1))
1404                 fail1 = emitJumpIfNotJSCell(regT0);
1405
1406             Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
1407             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1408 #endif
1409             
1410             int32_t op2imm = getConstantOperand(op2).asInt32();;
1411                     
1412             move(Imm32(op2imm), regT1);
1413             convertInt32ToDouble(regT1, fpRegT1);
1414
1415             emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
1416
1417             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
1418
1419 #if USE(JSVALUE64)
1420             fail1.link(this);
1421 #else
1422             if (!m_codeBlock->isKnownNotImmediate(op1))
1423                 fail1.link(this);
1424             fail2.link(this);
1425 #endif
1426         }
1427
1428         JITStubCall stubCall(this, cti_op_jless);
1429         stubCall.addArgument(regT0);
1430         stubCall.addArgument(op2, regT2);
1431         stubCall.call();
1432         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
1433
1434     } else if (isOperandConstantImmediateInt(op1)) {
1435         linkSlowCase(iter);
1436
1437         if (supportsFloatingPoint()) {
1438 #if USE(JSVALUE64)
1439             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
1440             addPtr(tagTypeNumberRegister, regT1);
1441             movePtrToDouble(regT1, fpRegT1);
1442 #else
1443             Jump fail1;
1444             if (!m_codeBlock->isKnownNotImmediate(op2))
1445                 fail1 = emitJumpIfNotJSCell(regT1);
1446             
1447             Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
1448             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
1449 #endif
1450             
1451             int32_t op1imm = getConstantOperand(op1).asInt32();;
1452                     
1453             move(Imm32(op1imm), regT0);
1454             convertInt32ToDouble(regT0, fpRegT0);
1455
1456             emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
1457
1458             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
1459
1460 #if USE(JSVALUE64)
1461             fail1.link(this);
1462 #else
1463             if (!m_codeBlock->isKnownNotImmediate(op2))
1464                 fail1.link(this);
1465             fail2.link(this);
1466 #endif
1467         }
1468
1469         JITStubCall stubCall(this, cti_op_jless);
1470         stubCall.addArgument(op1, regT2);
1471         stubCall.addArgument(regT1);
1472         stubCall.call();
1473         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
1474
1475     } else {
1476         linkSlowCase(iter);
1477
1478         if (supportsFloatingPoint()) {
1479 #if USE(JSVALUE64)
1480             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
1481             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
1482             Jump fail3 = emitJumpIfImmediateInteger(regT1);
1483             addPtr(tagTypeNumberRegister, regT0);
1484             addPtr(tagTypeNumberRegister, regT1);
1485             movePtrToDouble(regT0, fpRegT0);
1486             movePtrToDouble(regT1, fpRegT1);
1487 #else
1488             Jump fail1;
1489             if (!m_codeBlock->isKnownNotImmediate(op1))
1490                 fail1 = emitJumpIfNotJSCell(regT0);
1491
1492             Jump fail2;
1493             if (!m_codeBlock->isKnownNotImmediate(op2))
1494                 fail2 = emitJumpIfNotJSCell(regT1);
1495
1496             Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
1497             Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
1498             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1499             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
1500 #endif
1501
1502             emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
1503
1504             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
1505
1506 #if USE(JSVALUE64)
1507             fail1.link(this);
1508             fail2.link(this);
1509             fail3.link(this);
1510 #else
1511             if (!m_codeBlock->isKnownNotImmediate(op1))
1512                 fail1.link(this);
1513             if (!m_codeBlock->isKnownNotImmediate(op2))
1514                 fail2.link(this);
1515             fail3.link(this);
1516             fail4.link(this);
1517 #endif
1518         }
1519
1520         linkSlowCase(iter);
1521         JITStubCall stubCall(this, cti_op_jless);
1522         stubCall.addArgument(regT0);
1523         stubCall.addArgument(regT1);
1524         stubCall.call();
1525         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
1526     }
1527 }
1528
1529 void JIT::emit_op_jless(Instruction* currentInstruction)
1530 {
1531     unsigned op1 = currentInstruction[1].u.operand;
1532     unsigned op2 = currentInstruction[2].u.operand;
1533     unsigned target = currentInstruction[3].u.operand;
1534
1535     // We generate inline code for the following cases in the fast path:
1536     // - int immediate to constant int immediate
1537     // - constant int immediate to int immediate
1538     // - int immediate to int immediate
1539
1540     if (isOperandConstantImmediateInt(op2)) {
1541         emitGetVirtualRegister(op1, regT0);
1542         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1543 #if USE(JSVALUE64)
1544         int32_t op2imm = getConstantOperandImmediateInt(op2);
1545 #else
1546         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
1547 #endif
1548         addJump(branch32(LessThan, regT0, Imm32(op2imm)), target);
1549     } else if (isOperandConstantImmediateInt(op1)) {
1550         emitGetVirtualRegister(op2, regT1);
1551         emitJumpSlowCaseIfNotImmediateInteger(regT1);
1552 #if USE(JSVALUE64)
1553         int32_t op1imm = getConstantOperandImmediateInt(op1);
1554 #else
1555         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
1556 #endif
1557         addJump(branch32(GreaterThan, regT1, Imm32(op1imm)), target);
1558     } else {
1559         emitGetVirtualRegisters(op1, regT0, op2, regT1);
1560         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1561         emitJumpSlowCaseIfNotImmediateInteger(regT1);
1562
1563         addJump(branch32(LessThan, regT0, regT1), target);
1564     }
1565 }
1566
1567 void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1568 {
1569     unsigned op1 = currentInstruction[1].u.operand;
1570     unsigned op2 = currentInstruction[2].u.operand;
1571     unsigned target = currentInstruction[3].u.operand;
1572
1573     // We generate inline code for the following cases in the slow path:
1574     // - floating-point number to constant int immediate
1575     // - constant int immediate to floating-point number
1576     // - floating-point number to floating-point number.
1577
1578     if (isOperandConstantImmediateInt(op2)) {
1579         linkSlowCase(iter);
1580
1581         if (supportsFloatingPoint()) {
1582 #if USE(JSVALUE64)
1583             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
1584             addPtr(tagTypeNumberRegister, regT0);
1585             movePtrToDouble(regT0, fpRegT0);
1586 #else
1587             Jump fail1;
1588             if (!m_codeBlock->isKnownNotImmediate(op1))
1589                 fail1 = emitJumpIfNotJSCell(regT0);
1590
1591             Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
1592             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1593 #endif
1594             
1595             int32_t op2imm = getConstantOperand(op2).asInt32();
1596                     
1597             move(Imm32(op2imm), regT1);
1598             convertInt32ToDouble(regT1, fpRegT1);
1599
1600             emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
1601
1602             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
1603
1604 #if USE(JSVALUE64)
1605             fail1.link(this);
1606 #else
1607             if (!m_codeBlock->isKnownNotImmediate(op1))
1608                 fail1.link(this);
1609             fail2.link(this);
1610 #endif
1611         }
1612
1613         JITStubCall stubCall(this, cti_op_jless);
1614         stubCall.addArgument(regT0);
1615         stubCall.addArgument(op2, regT2);
1616         stubCall.call();
1617         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
1618
1619     } else if (isOperandConstantImmediateInt(op1)) {
1620         linkSlowCase(iter);
1621
1622         if (supportsFloatingPoint()) {
1623 #if USE(JSVALUE64)
1624             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
1625             addPtr(tagTypeNumberRegister, regT1);
1626             movePtrToDouble(regT1, fpRegT1);
1627 #else
1628             Jump fail1;
1629             if (!m_codeBlock->isKnownNotImmediate(op2))
1630                 fail1 = emitJumpIfNotJSCell(regT1);
1631             
1632             Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
1633             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
1634 #endif
1635             
1636             int32_t op1imm = getConstantOperand(op1).asInt32();
1637                     
1638             move(Imm32(op1imm), regT0);
1639             convertInt32ToDouble(regT0, fpRegT0);
1640
1641             emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
1642
1643             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
1644
1645 #if USE(JSVALUE64)
1646             fail1.link(this);
1647 #else
1648             if (!m_codeBlock->isKnownNotImmediate(op2))
1649                 fail1.link(this);
1650             fail2.link(this);
1651 #endif
1652         }
1653
1654         JITStubCall stubCall(this, cti_op_jless);
1655         stubCall.addArgument(op1, regT2);
1656         stubCall.addArgument(regT1);
1657         stubCall.call();
1658         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
1659
1660     } else {
1661         linkSlowCase(iter);
1662
1663         if (supportsFloatingPoint()) {
1664 #if USE(JSVALUE64)
1665             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
1666             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
1667             Jump fail3 = emitJumpIfImmediateInteger(regT1);
1668             addPtr(tagTypeNumberRegister, regT0);
1669             addPtr(tagTypeNumberRegister, regT1);
1670             movePtrToDouble(regT0, fpRegT0);
1671             movePtrToDouble(regT1, fpRegT1);
1672 #else
1673             Jump fail1;
1674             if (!m_codeBlock->isKnownNotImmediate(op1))
1675                 fail1 = emitJumpIfNotJSCell(regT0);
1676
1677             Jump fail2;
1678             if (!m_codeBlock->isKnownNotImmediate(op2))
1679                 fail2 = emitJumpIfNotJSCell(regT1);
1680
1681             Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
1682             Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
1683             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1684             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
1685 #endif
1686
1687             emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
1688
1689             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
1690
1691 #if USE(JSVALUE64)
1692             fail1.link(this);
1693             fail2.link(this);
1694             fail3.link(this);
1695 #else
1696             if (!m_codeBlock->isKnownNotImmediate(op1))
1697                 fail1.link(this);
1698             if (!m_codeBlock->isKnownNotImmediate(op2))
1699                 fail2.link(this);
1700             fail3.link(this);
1701             fail4.link(this);
1702 #endif
1703         }
1704
1705         linkSlowCase(iter);
1706         JITStubCall stubCall(this, cti_op_jless);
1707         stubCall.addArgument(regT0);
1708         stubCall.addArgument(regT1);
1709         stubCall.call();
1710         emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
1711     }
1712 }
1713
1714 void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
1715 {
1716     unsigned op1 = currentInstruction[1].u.operand;
1717     unsigned op2 = currentInstruction[2].u.operand;
1718     unsigned target = currentInstruction[3].u.operand;
1719
1720     // We generate inline code for the following cases in the fast path:
1721     // - int immediate to constant int immediate
1722     // - constant int immediate to int immediate
1723     // - int immediate to int immediate
1724
1725     if (isOperandConstantImmediateInt(op2)) {
1726         emitGetVirtualRegister(op1, regT0);
1727         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1728 #if USE(JSVALUE64)
1729         int32_t op2imm = getConstantOperandImmediateInt(op2);
1730 #else
1731         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
1732 #endif
1733         addJump(branch32(GreaterThan, regT0, Imm32(op2imm)), target);
1734     } else if (isOperandConstantImmediateInt(op1)) {
1735         emitGetVirtualRegister(op2, regT1);
1736         emitJumpSlowCaseIfNotImmediateInteger(regT1);
1737 #if USE(JSVALUE64)
1738         int32_t op1imm = getConstantOperandImmediateInt(op1);
1739 #else
1740         int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
1741 #endif
1742         addJump(branch32(LessThan, regT1, Imm32(op1imm)), target);
1743     } else {
1744         emitGetVirtualRegisters(op1, regT0, op2, regT1);
1745         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1746         emitJumpSlowCaseIfNotImmediateInteger(regT1);
1747
1748         addJump(branch32(GreaterThan, regT0, regT1), target);
1749     }
1750 }
1751
1752 void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1753 {
1754     unsigned op1 = currentInstruction[1].u.operand;
1755     unsigned op2 = currentInstruction[2].u.operand;
1756     unsigned target = currentInstruction[3].u.operand;
1757
1758     // We generate inline code for the following cases in the slow path:
1759     // - floating-point number to constant int immediate
1760     // - constant int immediate to floating-point number
1761     // - floating-point number to floating-point number.
1762
1763     if (isOperandConstantImmediateInt(op2)) {
1764         linkSlowCase(iter);
1765
1766         if (supportsFloatingPoint()) {
1767 #if USE(JSVALUE64)
1768             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
1769             addPtr(tagTypeNumberRegister, regT0);
1770             movePtrToDouble(regT0, fpRegT0);
1771 #else
1772             Jump fail1;
1773             if (!m_codeBlock->isKnownNotImmediate(op1))
1774                 fail1 = emitJumpIfNotJSCell(regT0);
1775
1776             Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
1777             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1778 #endif
1779             
1780             int32_t op2imm = getConstantOperand(op2).asInt32();;
1781                     
1782             move(Imm32(op2imm), regT1);
1783             convertInt32ToDouble(regT1, fpRegT1);
1784
1785             emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);
1786
1787             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
1788
1789 #if USE(JSVALUE64)
1790             fail1.link(this);
1791 #else
1792             if (!m_codeBlock->isKnownNotImmediate(op1))
1793                 fail1.link(this);
1794             fail2.link(this);
1795 #endif
1796         }
1797
1798         JITStubCall stubCall(this, cti_op_jlesseq);
1799         stubCall.addArgument(regT0);
1800         stubCall.addArgument(op2, regT2);
1801         stubCall.call();
1802         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
1803
1804     } else if (isOperandConstantImmediateInt(op1)) {
1805         linkSlowCase(iter);
1806
1807         if (supportsFloatingPoint()) {
1808 #if USE(JSVALUE64)
1809             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
1810             addPtr(tagTypeNumberRegister, regT1);
1811             movePtrToDouble(regT1, fpRegT1);
1812 #else
1813             Jump fail1;
1814             if (!m_codeBlock->isKnownNotImmediate(op2))
1815                 fail1 = emitJumpIfNotJSCell(regT1);
1816             
1817             Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
1818             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
1819 #endif
1820             
1821             int32_t op1imm = getConstantOperand(op1).asInt32();;
1822                     
1823             move(Imm32(op1imm), regT0);
1824             convertInt32ToDouble(regT0, fpRegT0);
1825
1826             emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);
1827
1828             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
1829
1830 #if USE(JSVALUE64)
1831             fail1.link(this);
1832 #else
1833             if (!m_codeBlock->isKnownNotImmediate(op2))
1834                 fail1.link(this);
1835             fail2.link(this);
1836 #endif
1837         }
1838
1839         JITStubCall stubCall(this, cti_op_jlesseq);
1840         stubCall.addArgument(op1, regT2);
1841         stubCall.addArgument(regT1);
1842         stubCall.call();
1843         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
1844
1845     } else {
1846         linkSlowCase(iter);
1847
1848         if (supportsFloatingPoint()) {
1849 #if USE(JSVALUE64)
1850             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
1851             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
1852             Jump fail3 = emitJumpIfImmediateInteger(regT1);
1853             addPtr(tagTypeNumberRegister, regT0);
1854             addPtr(tagTypeNumberRegister, regT1);
1855             movePtrToDouble(regT0, fpRegT0);
1856             movePtrToDouble(regT1, fpRegT1);
1857 #else
1858             Jump fail1;
1859             if (!m_codeBlock->isKnownNotImmediate(op1))
1860                 fail1 = emitJumpIfNotJSCell(regT0);
1861
1862             Jump fail2;
1863             if (!m_codeBlock->isKnownNotImmediate(op2))
1864                 fail2 = emitJumpIfNotJSCell(regT1);
1865
1866             Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
1867             Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
1868             loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
1869             loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
1870 #endif
1871
1872             emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);
1873
1874             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
1875
1876 #if USE(JSVALUE64)
1877             fail1.link(this);
1878             fail2.link(this);
1879             fail3.link(this);
1880 #else
1881             if (!m_codeBlock->isKnownNotImmediate(op1))
1882                 fail1.link(this);
1883             if (!m_codeBlock->isKnownNotImmediate(op2))
1884                 fail2.link(this);
1885             fail3.link(this);
1886             fail4.link(this);
1887 #endif
1888         }
1889
1890         linkSlowCase(iter);
1891         JITStubCall stubCall(this, cti_op_jlesseq);
1892         stubCall.addArgument(regT0);
1893         stubCall.addArgument(regT1);
1894         stubCall.call();
1895         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
1896     }
1897 }
1898
1899 void JIT::emit_op_bitand(Instruction* currentInstruction)
1900 {
1901     unsigned result = currentInstruction[1].u.operand;
1902     unsigned op1 = currentInstruction[2].u.operand;
1903     unsigned op2 = currentInstruction[3].u.operand;
1904
1905     if (isOperandConstantImmediateInt(op1)) {
1906         emitGetVirtualRegister(op2, regT0);
1907         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1908 #if USE(JSVALUE64)
1909         int32_t imm = getConstantOperandImmediateInt(op1);
1910         andPtr(Imm32(imm), regT0);
1911         if (imm >= 0)
1912             emitFastArithIntToImmNoCheck(regT0, regT0);
1913 #else
1914         andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)))), regT0);
1915 #endif
1916     } else if (isOperandConstantImmediateInt(op2)) {
1917         emitGetVirtualRegister(op1, regT0);
1918         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1919 #if USE(JSVALUE64)
1920         int32_t imm = getConstantOperandImmediateInt(op2);
1921         andPtr(Imm32(imm), regT0);
1922         if (imm >= 0)
1923             emitFastArithIntToImmNoCheck(regT0, regT0);
1924 #else
1925         andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)))), regT0);
1926 #endif
1927     } else {
1928         emitGetVirtualRegisters(op1, regT0, op2, regT1);
1929         andPtr(regT1, regT0);
1930         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1931     }
1932     emitPutVirtualRegister(result);
1933 }
1934
1935 void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1936 {
1937     unsigned result = currentInstruction[1].u.operand;
1938     unsigned op1 = currentInstruction[2].u.operand;
1939     unsigned op2 = currentInstruction[3].u.operand;
1940
1941     linkSlowCase(iter);
1942     if (isOperandConstantImmediateInt(op1)) {
1943         JITStubCall stubCall(this, cti_op_bitand);
1944         stubCall.addArgument(op1, regT2);
1945         stubCall.addArgument(regT0);
1946         stubCall.call(result);
1947     } else if (isOperandConstantImmediateInt(op2)) {
1948         JITStubCall stubCall(this, cti_op_bitand);
1949         stubCall.addArgument(regT0);
1950         stubCall.addArgument(op2, regT2);
1951         stubCall.call(result);
1952     } else {
1953         JITStubCall stubCall(this, cti_op_bitand);
1954         stubCall.addArgument(op1, regT2);
1955         stubCall.addArgument(regT1);
1956         stubCall.call(result);
1957     }
1958 }
1959
1960 void JIT::emit_op_post_inc(Instruction* currentInstruction)
1961 {
1962     unsigned result = currentInstruction[1].u.operand;
1963     unsigned srcDst = currentInstruction[2].u.operand;
1964
1965     emitGetVirtualRegister(srcDst, regT0);
1966     move(regT0, regT1);
1967     emitJumpSlowCaseIfNotImmediateInteger(regT0);
1968 #if USE(JSVALUE64)
1969     addSlowCase(branchAdd32(Overflow, Imm32(1), regT1));
1970     emitFastArithIntToImmNoCheck(regT1, regT1);
1971 #else
1972     addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1));
1973     signExtend32ToPtr(regT1, regT1);
1974 #endif
1975     emitPutVirtualRegister(srcDst, regT1);
1976     emitPutVirtualRegister(result);
1977 }
1978
1979 void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1980 {
1981     unsigned result = currentInstruction[1].u.operand;
1982     unsigned srcDst = currentInstruction[2].u.operand;
1983
1984     linkSlowCase(iter);
1985     linkSlowCase(iter);
1986     JITStubCall stubCall(this, cti_op_post_inc);
1987     stubCall.addArgument(regT0);
1988     stubCall.addArgument(Imm32(srcDst));
1989     stubCall.call(result);
1990 }
1991
1992 void JIT::emit_op_post_dec(Instruction* currentInstruction)
1993 {
1994     unsigned result = currentInstruction[1].u.operand;
1995     unsigned srcDst = currentInstruction[2].u.operand;
1996
1997     emitGetVirtualRegister(srcDst, regT0);
1998     move(regT0, regT1);
1999     emitJumpSlowCaseIfNotImmediateInteger(regT0);
2000 #if USE(JSVALUE64)
2001     addSlowCase(branchSub32(Zero, Imm32(1), regT1));
2002     emitFastArithIntToImmNoCheck(regT1, regT1);
2003 #else
2004     addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1));
2005     signExtend32ToPtr(regT1, regT1);
2006 #endif
2007     emitPutVirtualRegister(srcDst, regT1);
2008     emitPutVirtualRegister(result);
2009 }
2010
2011 void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2012 {
2013     unsigned result = currentInstruction[1].u.operand;
2014     unsigned srcDst = currentInstruction[2].u.operand;
2015
2016     linkSlowCase(iter);
2017     linkSlowCase(iter);
2018     JITStubCall stubCall(this, cti_op_post_dec);
2019     stubCall.addArgument(regT0);
2020     stubCall.addArgument(Imm32(srcDst));
2021     stubCall.call(result);
2022 }
2023
2024 void JIT::emit_op_pre_inc(Instruction* currentInstruction)
2025 {
2026     unsigned srcDst = currentInstruction[1].u.operand;
2027
2028     emitGetVirtualRegister(srcDst, regT0);
2029     emitJumpSlowCaseIfNotImmediateInteger(regT0);
2030 #if USE(JSVALUE64)
2031     addSlowCase(branchAdd32(Overflow, Imm32(1), regT0));
2032     emitFastArithIntToImmNoCheck(regT0, regT0);
2033 #else
2034     addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0));
2035     signExtend32ToPtr(regT0, regT0);
2036 #endif
2037     emitPutVirtualRegister(srcDst);
2038 }
2039
2040 void JIT::emitSlow_op_pre_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2041 {
2042     unsigned srcDst = currentInstruction[1].u.operand;
2043
2044     Jump notImm = getSlowCase(iter);
2045     linkSlowCase(iter);
2046     emitGetVirtualRegister(srcDst, regT0);
2047     notImm.link(this);
2048     JITStubCall stubCall(this, cti_op_pre_inc);
2049     stubCall.addArgument(regT0);
2050     stubCall.call(srcDst);
2051 }
2052
2053 void JIT::emit_op_pre_dec(Instruction* currentInstruction)
2054 {
2055     unsigned srcDst = currentInstruction[1].u.operand;
2056
2057     emitGetVirtualRegister(srcDst, regT0);
2058     emitJumpSlowCaseIfNotImmediateInteger(regT0);
2059 #if USE(JSVALUE64)
2060     addSlowCase(branchSub32(Zero, Imm32(1), regT0));
2061     emitFastArithIntToImmNoCheck(regT0, regT0);
2062 #else
2063     addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0));
2064     signExtend32ToPtr(regT0, regT0);
2065 #endif
2066     emitPutVirtualRegister(srcDst);
2067 }
2068
2069 void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2070 {
2071     unsigned srcDst = currentInstruction[1].u.operand;
2072
2073     Jump notImm = getSlowCase(iter);
2074     linkSlowCase(iter);
2075     emitGetVirtualRegister(srcDst, regT0);
2076     notImm.link(this);
2077     JITStubCall stubCall(this, cti_op_pre_dec);
2078     stubCall.addArgument(regT0);
2079     stubCall.call(srcDst);
2080 }
2081
2082 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
2083
2084 #if PLATFORM(X86) || PLATFORM(X86_64)
2085
2086 void JIT::emit_op_mod(Instruction* currentInstruction)
2087 {
2088     unsigned result = currentInstruction[1].u.operand;
2089     unsigned op1 = currentInstruction[2].u.operand;
2090     unsigned op2 = currentInstruction[3].u.operand;
2091
2092     emitGetVirtualRegisters(op1, X86Registers::eax, op2, X86Registers::ecx);
2093     emitJumpSlowCaseIfNotImmediateInteger(X86Registers::eax);
2094     emitJumpSlowCaseIfNotImmediateInteger(X86Registers::ecx);
2095 #if USE(JSVALUE64)
2096     addSlowCase(branchPtr(Equal, X86Registers::ecx, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))));
2097     m_assembler.cdq();
2098     m_assembler.idivl_r(X86Registers::ecx);
2099 #else
2100     emitFastArithDeTagImmediate(X86Registers::eax);
2101     addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86Registers::ecx));
2102     m_assembler.cdq();
2103     m_assembler.idivl_r(X86Registers::ecx);
2104     signExtend32ToPtr(X86Registers::edx, X86Registers::edx);
2105 #endif
2106     emitFastArithReTagImmediate(X86Registers::edx, X86Registers::eax);
2107     emitPutVirtualRegister(result);
2108 }
2109
2110 void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2111 {
2112     unsigned result = currentInstruction[1].u.operand;
2113
2114 #if USE(JSVALUE64)
2115     linkSlowCase(iter);
2116     linkSlowCase(iter);
2117     linkSlowCase(iter);
2118 #else
2119     Jump notImm1 = getSlowCase(iter);
2120     Jump notImm2 = getSlowCase(iter);
2121     linkSlowCase(iter);
2122     emitFastArithReTagImmediate(X86Registers::eax, X86Registers::eax);
2123     emitFastArithReTagImmediate(X86Registers::ecx, X86Registers::ecx);
2124     notImm1.link(this);
2125     notImm2.link(this);
2126 #endif
2127     JITStubCall stubCall(this, cti_op_mod);
2128     stubCall.addArgument(X86Registers::eax);
2129     stubCall.addArgument(X86Registers::ecx);
2130     stubCall.call(result);
2131 }
2132
2133 #else // PLATFORM(X86) || PLATFORM(X86_64)
2134
2135 void JIT::emit_op_mod(Instruction* currentInstruction)
2136 {
2137     unsigned result = currentInstruction[1].u.operand;
2138     unsigned op1 = currentInstruction[2].u.operand;
2139     unsigned op2 = currentInstruction[3].u.operand;
2140
2141     JITStubCall stubCall(this, cti_op_mod);
2142     stubCall.addArgument(op1, regT2);
2143     stubCall.addArgument(op2, regT2);
2144     stubCall.call(result);
2145 }
2146
2147 void JIT::emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&)
2148 {
2149     ASSERT_NOT_REACHED();
2150 }
2151
2152 #endif // PLATFORM(X86) || PLATFORM(X86_64)
2153
2154 /* ------------------------------ END: OP_MOD ------------------------------ */
2155
2156 #if USE(JSVALUE64)
2157
2158 /* ------------------------------ BEGIN: USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
2159
2160 void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsigned op2, OperandTypes)
2161 {
2162     emitGetVirtualRegisters(op1, regT0, op2, regT1);
2163     emitJumpSlowCaseIfNotImmediateInteger(regT0);
2164     emitJumpSlowCaseIfNotImmediateInteger(regT1);
2165     if (opcodeID == op_add)
2166         addSlowCase(branchAdd32(Overflow, regT1, regT0));
2167     else if (opcodeID == op_sub)
2168         addSlowCase(branchSub32(Overflow, regT1, regT0));
2169     else {
2170         ASSERT(opcodeID == op_mul);
2171         addSlowCase(branchMul32(Overflow, regT1, regT0));
2172         addSlowCase(branchTest32(Zero, regT0));
2173     }
2174     emitFastArithIntToImmNoCheck(regT0, regT0);
2175 }
2176
2177 void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned result, unsigned op1, unsigned op2, OperandTypes types, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase)
2178 {
2179     // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset.
2180     COMPILE_ASSERT(((JSImmediate::TagTypeNumber + JSImmediate::DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0);
2181     
2182     Jump notImm1;
2183     Jump notImm2;
2184     if (op1HasImmediateIntFastCase) {
2185         notImm2 = getSlowCase(iter);
2186     } else if (op2HasImmediateIntFastCase) {
2187         notImm1 = getSlowCase(iter);
2188     } else {
2189         notImm1 = getSlowCase(iter);
2190         notImm2 = getSlowCase(iter);
2191     }
2192
2193     linkSlowCase(iter); // Integer overflow case - we could handle this in JIT code, but this is likely rare.
2194     if (opcodeID == op_mul && !op1HasImmediateIntFastCase && !op2HasImmediateIntFastCase) // op_mul has an extra slow case to handle 0 * negative number.
2195         linkSlowCase(iter);
2196     emitGetVirtualRegister(op1, regT0);
2197
2198     Label stubFunctionCall(this);
2199     JITStubCall stubCall(this, opcodeID == op_add ? cti_op_add : opcodeID == op_sub ? cti_op_sub : cti_op_mul);
2200     if (op1HasImmediateIntFastCase || op2HasImmediateIntFastCase) {
2201         emitGetVirtualRegister(op1, regT0);
2202         emitGetVirtualRegister(op2, regT1);
2203     }
2204     stubCall.addArgument(regT0);
2205     stubCall.addArgument(regT1);
2206     stubCall.call(result);
2207     Jump end = jump();
2208
2209     if (op1HasImmediateIntFastCase) {
2210         notImm2.link(this);
2211         if (!types.second().definitelyIsNumber())
2212             emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
2213         emitGetVirtualRegister(op1, regT1);
2214         convertInt32ToDouble(regT1, fpRegT1);
2215         addPtr(tagTypeNumberRegister, regT0);
2216         movePtrToDouble(regT0, fpRegT2);
2217     } else if (op2HasImmediateIntFastCase) {
2218         notImm1.link(this);
2219         if (!types.first().definitelyIsNumber())
2220             emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
2221         emitGetVirtualRegister(op2, regT1);
2222         convertInt32ToDouble(regT1, fpRegT1);
2223         addPtr(tagTypeNumberRegister, regT0);
2224         movePtrToDouble(regT0, fpRegT2);
2225     } else {
2226         // if we get here, eax is not an int32, edx not yet checked.
2227         notImm1.link(this);
2228         if (!types.first().definitelyIsNumber())
2229             emitJumpIfNotImmediateNumber(regT0).linkTo(stubFunctionCall, this);
2230         if (!types.second().definitelyIsNumber())
2231             emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
2232         addPtr(tagTypeNumberRegister, regT0);
2233         movePtrToDouble(regT0, fpRegT1);
2234         Jump op2isDouble = emitJumpIfNotImmediateInteger(regT1);
2235         convertInt32ToDouble(regT1, fpRegT2);
2236         Jump op2wasInteger = jump();
2237
2238         // if we get here, eax IS an int32, edx is not.
2239         notImm2.link(this);
2240         if (!types.second().definitelyIsNumber())
2241             emitJumpIfNotImmediateNumber(regT1).linkTo(stubFunctionCall, this);
2242         convertInt32ToDouble(regT0, fpRegT1);
2243         op2isDouble.link(this);
2244         addPtr(tagTypeNumberRegister, regT1);
2245         movePtrToDouble(regT1, fpRegT2);
2246         op2wasInteger.link(this);
2247     }
2248
2249     if (opcodeID == op_add)
2250         addDouble(fpRegT2, fpRegT1);
2251     else if (opcodeID == op_sub)
2252         subDouble(fpRegT2, fpRegT1);
2253     else if (opcodeID == op_mul)
2254         mulDouble(fpRegT2, fpRegT1);
2255     else {
2256         ASSERT(opcodeID == op_div);
2257         divDouble(fpRegT2, fpRegT1);
2258     }
2259     moveDoubleToPtr(fpRegT1, regT0);
2260     subPtr(tagTypeNumberRegister, regT0);
2261     emitPutVirtualRegister(result, regT0);
2262
2263     end.link(this);
2264 }
2265
2266 void JIT::emit_op_add(Instruction* currentInstruction)
2267 {
2268     unsigned result = currentInstruction[1].u.operand;
2269     unsigned op1 = currentInstruction[2].u.operand;
2270     unsigned op2 = currentInstruction[3].u.operand;
2271     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2272
2273     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
2274         JITStubCall stubCall(this, cti_op_add);
2275         stubCall.addArgument(op1, regT2);
2276         stubCall.addArgument(op2, regT2);
2277         stubCall.call(result);
2278         return;
2279     }
2280
2281     if (isOperandConstantImmediateInt(op1)) {
2282         emitGetVirtualRegister(op2, regT0);
2283         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2284         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1)), regT0));
2285         emitFastArithIntToImmNoCheck(regT0, regT0);
2286     } else if (isOperandConstantImmediateInt(op2)) {
2287         emitGetVirtualRegister(op1, regT0);
2288         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2289         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2)), regT0));
2290         emitFastArithIntToImmNoCheck(regT0, regT0);
2291     } else
2292         compileBinaryArithOp(op_add, result, op1, op2, types);
2293
2294     emitPutVirtualRegister(result);
2295 }
2296
2297 void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2298 {
2299     unsigned result = currentInstruction[1].u.operand;
2300     unsigned op1 = currentInstruction[2].u.operand;
2301     unsigned op2 = currentInstruction[3].u.operand;
2302     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2303
2304     if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
2305         return;
2306
2307     bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1);
2308     bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2);
2309     compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand), op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
2310 }
2311
2312 void JIT::emit_op_mul(Instruction* currentInstruction)
2313 {
2314     unsigned result = currentInstruction[1].u.operand;
2315     unsigned op1 = currentInstruction[2].u.operand;
2316     unsigned op2 = currentInstruction[3].u.operand;
2317     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2318
2319     // For now, only plant a fast int case if the constant operand is greater than zero.
2320     int32_t value;
2321     if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {
2322         emitGetVirtualRegister(op2, regT0);
2323         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2324         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
2325         emitFastArithReTagImmediate(regT0, regT0);
2326     } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
2327         emitGetVirtualRegister(op1, regT0);
2328         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2329         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
2330         emitFastArithReTagImmediate(regT0, regT0);
2331     } else
2332         compileBinaryArithOp(op_mul, result, op1, op2, types);
2333
2334     emitPutVirtualRegister(result);
2335 }
2336
2337 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2338 {
2339     unsigned result = currentInstruction[1].u.operand;
2340     unsigned op1 = currentInstruction[2].u.operand;
2341     unsigned op2 = currentInstruction[3].u.operand;
2342     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2343
2344     bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1) && getConstantOperandImmediateInt(op1) > 0;
2345     bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2) && getConstantOperandImmediateInt(op2) > 0;
2346     compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand), op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
2347 }
2348
2349 void JIT::emit_op_div(Instruction* currentInstruction)
2350 {
2351     unsigned dst = currentInstruction[1].u.operand;
2352     unsigned op1 = currentInstruction[2].u.operand;
2353     unsigned op2 = currentInstruction[3].u.operand;
2354     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2355
2356     if (isOperandConstantImmediateDouble(op1)) {
2357         emitGetVirtualRegister(op1, regT0);
2358         addPtr(tagTypeNumberRegister, regT0);
2359         movePtrToDouble(regT0, fpRegT0);
2360     } else if (isOperandConstantImmediateInt(op1)) {
2361         emitLoadInt32ToDouble(op1, fpRegT0);
2362     } else {
2363         emitGetVirtualRegister(op1, regT0);
2364         if (!types.first().definitelyIsNumber())
2365             emitJumpSlowCaseIfNotImmediateNumber(regT0);
2366         Jump notInt = emitJumpIfNotImmediateInteger(regT0);
2367         convertInt32ToDouble(regT0, fpRegT0);
2368         Jump skipDoubleLoad = jump();
2369         notInt.link(this);
2370         addPtr(tagTypeNumberRegister, regT0);
2371         movePtrToDouble(regT0, fpRegT0);
2372         skipDoubleLoad.link(this);
2373     }
2374     
2375     if (isOperandConstantImmediateDouble(op2)) {
2376         emitGetVirtualRegister(op2, regT1);
2377         addPtr(tagTypeNumberRegister, regT1);
2378         movePtrToDouble(regT1, fpRegT1);
2379     } else if (isOperandConstantImmediateInt(op2)) {
2380         emitLoadInt32ToDouble(op2, fpRegT1);
2381     } else {
2382         emitGetVirtualRegister(op2, regT1);
2383         if (!types.second().definitelyIsNumber())
2384             emitJumpSlowCaseIfNotImmediateNumber(regT1);
2385         Jump notInt = emitJumpIfNotImmediateInteger(regT1);
2386         convertInt32ToDouble(regT1, fpRegT1);
2387         Jump skipDoubleLoad = jump();
2388         notInt.link(this);
2389         addPtr(tagTypeNumberRegister, regT1);
2390         movePtrToDouble(regT1, fpRegT1);
2391         skipDoubleLoad.link(this);
2392     }
2393     divDouble(fpRegT1, fpRegT0);
2394
2395     // Double result.
2396     moveDoubleToPtr(fpRegT0, regT0);
2397     subPtr(tagTypeNumberRegister, regT0);
2398
2399     emitPutVirtualRegister(dst, regT0);
2400 }
2401
2402 void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2403 {
2404     unsigned result = currentInstruction[1].u.operand;
2405     unsigned op1 = currentInstruction[2].u.operand;
2406     unsigned op2 = currentInstruction[3].u.operand;
2407     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2408     if (types.first().definitelyIsNumber() && types.second().definitelyIsNumber()) {
2409 #ifndef NDEBUG
2410         breakpoint();
2411 #endif
2412         return;
2413     }
2414     if (!isOperandConstantImmediateDouble(op1) && !isOperandConstantImmediateInt(op1)) {
2415         if (!types.first().definitelyIsNumber())
2416             linkSlowCase(iter);
2417     }
2418     if (!isOperandConstantImmediateDouble(op2) && !isOperandConstantImmediateInt(op2)) {
2419         if (!types.second().definitelyIsNumber())
2420             linkSlowCase(iter);
2421     }
2422     // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
2423     JITStubCall stubCall(this, cti_op_div);
2424     stubCall.addArgument(op1, regT2);
2425     stubCall.addArgument(op2, regT2);
2426     stubCall.call(result);
2427 }
2428
2429 void JIT::emit_op_sub(Instruction* currentInstruction)
2430 {
2431     unsigned result = currentInstruction[1].u.operand;
2432     unsigned op1 = currentInstruction[2].u.operand;
2433     unsigned op2 = currentInstruction[3].u.operand;
2434     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2435
2436     compileBinaryArithOp(op_sub, result, op1, op2, types);
2437     emitPutVirtualRegister(result);
2438 }
2439
2440 void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2441 {
2442     unsigned result = currentInstruction[1].u.operand;
2443     unsigned op1 = currentInstruction[2].u.operand;
2444     unsigned op2 = currentInstruction[3].u.operand;
2445     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2446
2447     compileBinaryArithOpSlowCase(op_sub, iter, result, op1, op2, types, false, false);
2448 }
2449
2450 #else // USE(JSVALUE64)
2451
2452 /* ------------------------------ BEGIN: !USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
2453
2454 void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes types)
2455 {
2456     Structure* numberStructure = m_globalData->numberStructure.get();
2457     Jump wasJSNumberCell1;
2458     Jump wasJSNumberCell2;
2459
2460     emitGetVirtualRegisters(src1, regT0, src2, regT1);
2461
2462     if (types.second().isReusable() && supportsFloatingPoint()) {
2463         ASSERT(types.second().mightBeNumber());
2464
2465         // Check op2 is a number
2466         Jump op2imm = emitJumpIfImmediateInteger(regT1);
2467         if (!types.second().definitelyIsNumber()) {
2468             emitJumpSlowCaseIfNotJSCell(regT1, src2);
2469             addSlowCase(checkStructure(regT1, numberStructure));
2470         }
2471
2472         // (1) In this case src2 is a reusable number cell.
2473         //     Slow case if src1 is not a number type.
2474         Jump op1imm = emitJumpIfImmediateInteger(regT0);
2475         if (!types.first().definitelyIsNumber()) {
2476             emitJumpSlowCaseIfNotJSCell(regT0, src1);
2477             addSlowCase(checkStructure(regT0, numberStructure));
2478         }
2479
2480         // (1a) if we get here, src1 is also a number cell
2481         loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
2482         Jump loadedDouble = jump();
2483         // (1b) if we get here, src1 is an immediate
2484         op1imm.link(this);
2485         emitFastArithImmToInt(regT0);
2486         convertInt32ToDouble(regT0, fpRegT0);
2487         // (1c) 
2488         loadedDouble.link(this);
2489         if (opcodeID == op_add)
2490             addDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
2491         else if (opcodeID == op_sub)
2492             subDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
2493         else {
2494             ASSERT(opcodeID == op_mul);
2495             mulDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
2496         }
2497
2498         // Store the result to the JSNumberCell and jump.
2499         storeDouble(fpRegT0, Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)));
2500         move(regT1, regT0);
2501         emitPutVirtualRegister(dst);
2502         wasJSNumberCell2 = jump();
2503
2504         // (2) This handles cases where src2 is an immediate number.
2505         //     Two slow cases - either src1 isn't an immediate, or the subtract overflows.
2506         op2imm.link(this);
2507         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2508     } else if (types.first().isReusable() && supportsFloatingPoint()) {
2509         ASSERT(types.first().mightBeNumber());
2510
2511         // Check op1 is a number
2512         Jump op1imm = emitJumpIfImmediateInteger(regT0);
2513         if (!types.first().definitelyIsNumber()) {
2514             emitJumpSlowCaseIfNotJSCell(regT0, src1);
2515             addSlowCase(checkStructure(regT0, numberStructure));
2516         }
2517
2518         // (1) In this case src1 is a reusable number cell.
2519         //     Slow case if src2 is not a number type.
2520         Jump op2imm = emitJumpIfImmediateInteger(regT1);
2521         if (!types.second().definitelyIsNumber()) {
2522             emitJumpSlowCaseIfNotJSCell(regT1, src2);
2523             addSlowCase(checkStructure(regT1, numberStructure));
2524         }
2525
2526         // (1a) if we get here, src2 is also a number cell
2527         loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
2528         Jump loadedDouble = jump();
2529         // (1b) if we get here, src2 is an immediate
2530         op2imm.link(this);
2531         emitFastArithImmToInt(regT1);
2532         convertInt32ToDouble(regT1, fpRegT1);
2533         // (1c) 
2534         loadedDouble.link(this);
2535         loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
2536         if (opcodeID == op_add)
2537             addDouble(fpRegT1, fpRegT0);
2538         else if (opcodeID == op_sub)
2539             subDouble(fpRegT1, fpRegT0);
2540         else {
2541             ASSERT(opcodeID == op_mul);
2542             mulDouble(fpRegT1, fpRegT0);
2543         }
2544         storeDouble(fpRegT0, Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)));
2545         emitPutVirtualRegister(dst);
2546
2547         // Store the result to the JSNumberCell and jump.
2548         storeDouble(fpRegT0, Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)));
2549         emitPutVirtualRegister(dst);
2550         wasJSNumberCell1 = jump();
2551
2552         // (2) This handles cases where src1 is an immediate number.
2553         //     Two slow cases - either src2 isn't an immediate, or the subtract overflows.
2554         op1imm.link(this);
2555         emitJumpSlowCaseIfNotImmediateInteger(regT1);
2556     } else
2557         emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);
2558
2559     if (opcodeID == op_add) {
2560         emitFastArithDeTagImmediate(regT0);
2561         addSlowCase(branchAdd32(Overflow, regT1, regT0));
2562     } else  if (opcodeID == op_sub) {
2563         addSlowCase(branchSub32(Overflow, regT1, regT0));
2564         signExtend32ToPtr(regT0, regT0);
2565         emitFastArithReTagImmediate(regT0, regT0);
2566     } else {
2567         ASSERT(opcodeID == op_mul);
2568         // convert eax & edx from JSImmediates to ints, and check if either are zero
2569         emitFastArithImmToInt(regT1);
2570         Jump op1Zero = emitFastArithDeTagImmediateJumpIfZero(regT0);
2571         Jump op2NonZero = branchTest32(NonZero, regT1);
2572         op1Zero.link(this);
2573         // if either input is zero, add the two together, and check if the result is < 0.
2574         // If it is, we have a problem (N < 0), (N * 0) == -0, not representatble as a JSImmediate. 
2575         move(regT0, regT2);
2576         addSlowCase(branchAdd32(Signed, regT1, regT2));
2577         // Skip the above check if neither input is zero
2578         op2NonZero.link(this);
2579         addSlowCase(branchMul32(Overflow, regT1, regT0));
2580         signExtend32ToPtr(regT0, regT0);
2581         emitFastArithReTagImmediate(regT0, regT0);
2582     }
2583     emitPutVirtualRegister(dst);
2584
2585     if (types.second().isReusable() && supportsFloatingPoint())
2586         wasJSNumberCell2.link(this);
2587     else if (types.first().isReusable() && supportsFloatingPoint())
2588         wasJSNumberCell1.link(this);
2589 }
2590
2591 void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes types)
2592 {
2593     linkSlowCase(iter);
2594     if (types.second().isReusable() && supportsFloatingPoint()) {
2595         if (!types.first().definitelyIsNumber()) {
2596             linkSlowCaseIfNotJSCell(iter, src1);
2597             linkSlowCase(iter);
2598         }
2599         if (!types.second().definitelyIsNumber()) {
2600             linkSlowCaseIfNotJSCell(iter, src2);
2601             linkSlowCase(iter);
2602         }
2603     } else if (types.first().isReusable() && supportsFloatingPoint()) {
2604         if (!types.first().definitelyIsNumber()) {
2605             linkSlowCaseIfNotJSCell(iter, src1);
2606             linkSlowCase(iter);
2607         }
2608         if (!types.second().definitelyIsNumber()) {
2609             linkSlowCaseIfNotJSCell(iter, src2);
2610             linkSlowCase(iter);
2611         }
2612     }
2613     linkSlowCase(iter);
2614
2615     // additional entry point to handle -0 cases.
2616     if (opcodeID == op_mul)
2617         linkSlowCase(iter);
2618
2619     JITStubCall stubCall(this, opcodeID == op_add ? cti_op_add : opcodeID == op_sub ? cti_op_sub : cti_op_mul);
2620     stubCall.addArgument(src1, regT2);
2621     stubCall.addArgument(src2, regT2);
2622     stubCall.call(dst);
2623 }
2624
2625 void JIT::emit_op_add(Instruction* currentInstruction)
2626 {
2627     unsigned result = currentInstruction[1].u.operand;
2628     unsigned op1 = currentInstruction[2].u.operand;
2629     unsigned op2 = currentInstruction[3].u.operand;
2630     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2631
2632     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
2633         JITStubCall stubCall(this, cti_op_add);
2634         stubCall.addArgument(op1, regT2);
2635         stubCall.addArgument(op2, regT2);
2636         stubCall.call(result);
2637         return;
2638     }
2639
2640     if (isOperandConstantImmediateInt(op1)) {
2641         emitGetVirtualRegister(op2, regT0);
2642         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2643         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), regT0));
2644         signExtend32ToPtr(regT0, regT0);
2645         emitPutVirtualRegister(result);
2646     } else if (isOperandConstantImmediateInt(op2)) {
2647         emitGetVirtualRegister(op1, regT0);
2648         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2649         addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), regT0));
2650         signExtend32ToPtr(regT0, regT0);
2651         emitPutVirtualRegister(result);
2652     } else {
2653         compileBinaryArithOp(op_add, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
2654     }
2655 }
2656
2657 void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2658 {
2659     unsigned result = currentInstruction[1].u.operand;
2660     unsigned op1 = currentInstruction[2].u.operand;
2661     unsigned op2 = currentInstruction[3].u.operand;
2662
2663     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2664     if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
2665         return;
2666
2667     if (isOperandConstantImmediateInt(op1)) {
2668         Jump notImm = getSlowCase(iter);
2669         linkSlowCase(iter);
2670         sub32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), regT0);
2671         notImm.link(this);
2672         JITStubCall stubCall(this, cti_op_add);
2673         stubCall.addArgument(op1, regT2);
2674         stubCall.addArgument(regT0);
2675         stubCall.call(result);
2676     } else if (isOperandConstantImmediateInt(op2)) {
2677         Jump notImm = getSlowCase(iter);
2678         linkSlowCase(iter);
2679         sub32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), regT0);
2680         notImm.link(this);
2681         JITStubCall stubCall(this, cti_op_add);
2682         stubCall.addArgument(regT0);
2683         stubCall.addArgument(op2, regT2);
2684         stubCall.call(result);
2685     } else {
2686         OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
2687         ASSERT(types.first().mightBeNumber() && types.second().mightBeNumber());
2688         compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types);
2689     }
2690 }
2691
2692 void JIT::emit_op_mul(Instruction* currentInstruction)
2693 {
2694     unsigned result = currentInstruction[1].u.operand;
2695     unsigned op1 = currentInstruction[2].u.operand;
2696     unsigned op2 = currentInstruction[3].u.operand;
2697
2698     // For now, only plant a fast int case if the constant operand is greater than zero.
2699     int32_t value;
2700     if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {
2701         emitGetVirtualRegister(op2, regT0);
2702         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2703         emitFastArithDeTagImmediate(regT0);
2704         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
2705         signExtend32ToPtr(regT0, regT0);
2706         emitFastArithReTagImmediate(regT0, regT0);
2707         emitPutVirtualRegister(result);
2708     } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
2709         emitGetVirtualRegister(op1, regT0);
2710         emitJumpSlowCaseIfNotImmediateInteger(regT0);
2711         emitFastArithDeTagImmediate(regT0);
2712         addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
2713         signExtend32ToPtr(regT0, regT0);
2714         emitFastArithReTagImmediate(regT0, regT0);
2715         emitPutVirtualRegister(result);
2716     } else
2717         compileBinaryArithOp(op_mul, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
2718 }
2719
2720 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2721 {
2722     unsigned result = currentInstruction[1].u.operand;
2723     unsigned op1 = currentInstruction[2].u.operand;
2724     unsigned op2 = currentInstruction[3].u.operand;
2725
2726     if ((isOperandConstantImmediateInt(op1) && (getConstantOperandImmediateInt(op1) > 0))
2727         || (isOperandConstantImmediateInt(op2) && (getConstantOperandImmediateInt(op2) > 0))) {
2728         linkSlowCase(iter);
2729         linkSlowCase(iter);
2730         // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
2731         JITStubCall stubCall(this, cti_op_mul);
2732         stubCall.addArgument(op1, regT2);
2733         stubCall.addArgument(op2, regT2);
2734         stubCall.call(result);
2735     } else
2736         compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
2737 }
2738
2739 void JIT::emit_op_sub(Instruction* currentInstruction)
2740 {
2741     compileBinaryArithOp(op_sub, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
2742 }
2743
2744 void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2745 {
2746     compileBinaryArithOpSlowCase(op_sub, iter, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
2747 }
2748
2749 #endif // USE(JSVALUE64)
2750
2751 /* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */
2752
2753 #endif // USE(JSVALUE32_64)
2754
2755 } // namespace JSC
2756
2757 #endif // ENABLE(JIT)