[ARMv6][DFG] ARM MacroAssembler is always emitting cmn when immediate is 0
[WebKit-https.git] / Source / JavaScriptCore / assembler / MacroAssemblerARM.h
1 /*
2  * Copyright (C) 2008-2017 Apple Inc.
3  * Copyright (C) 2009, 2010 University of Szeged
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #pragma once
29
30 #if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
31
32 #include "ARMAssembler.h"
33 #include "AbstractMacroAssembler.h"
34
35 namespace JSC {
36
37 class MacroAssemblerARM : public AbstractMacroAssembler<ARMAssembler, MacroAssemblerARM> {
38     static const int DoubleConditionMask = 0x0f;
39     static const int DoubleConditionBitSpecial = 0x10;
40     COMPILE_ASSERT(!(DoubleConditionBitSpecial & DoubleConditionMask), DoubleConditionBitSpecial_should_not_interfere_with_ARMAssembler_Condition_codes);
41 public:
42     static const unsigned numGPRs = 16;
43     static const unsigned numFPRs = 16;
44     
45     typedef ARMRegisters::FPRegisterID FPRegisterID;
46
47     enum RelationalCondition {
48         Equal = ARMAssembler::EQ,
49         NotEqual = ARMAssembler::NE,
50         Above = ARMAssembler::HI,
51         AboveOrEqual = ARMAssembler::CS,
52         Below = ARMAssembler::CC,
53         BelowOrEqual = ARMAssembler::LS,
54         GreaterThan = ARMAssembler::GT,
55         GreaterThanOrEqual = ARMAssembler::GE,
56         LessThan = ARMAssembler::LT,
57         LessThanOrEqual = ARMAssembler::LE
58     };
59
60     enum ResultCondition {
61         Overflow = ARMAssembler::VS,
62         Signed = ARMAssembler::MI,
63         PositiveOrZero = ARMAssembler::PL,
64         Zero = ARMAssembler::EQ,
65         NonZero = ARMAssembler::NE
66     };
67
68     enum DoubleCondition {
69         // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
70         DoubleEqual = ARMAssembler::EQ,
71         DoubleNotEqual = ARMAssembler::NE | DoubleConditionBitSpecial,
72         DoubleGreaterThan = ARMAssembler::GT,
73         DoubleGreaterThanOrEqual = ARMAssembler::GE,
74         DoubleLessThan = ARMAssembler::CC,
75         DoubleLessThanOrEqual = ARMAssembler::LS,
76         // If either operand is NaN, these conditions always evaluate to true.
77         DoubleEqualOrUnordered = ARMAssembler::EQ | DoubleConditionBitSpecial,
78         DoubleNotEqualOrUnordered = ARMAssembler::NE,
79         DoubleGreaterThanOrUnordered = ARMAssembler::HI,
80         DoubleGreaterThanOrEqualOrUnordered = ARMAssembler::CS,
81         DoubleLessThanOrUnordered = ARMAssembler::LT,
82         DoubleLessThanOrEqualOrUnordered = ARMAssembler::LE,
83     };
84
85     static const RegisterID stackPointerRegister = ARMRegisters::sp;
86     static const RegisterID framePointerRegister = ARMRegisters::fp;
87     static const RegisterID linkRegister = ARMRegisters::lr;
88
89     static const Scale ScalePtr = TimesFour;
90
91     void add32(RegisterID src, RegisterID dest)
92     {
93         m_assembler.adds(dest, dest, src);
94     }
95
96     void add32(RegisterID op1, RegisterID op2, RegisterID dest)
97     {
98         m_assembler.adds(dest, op1, op2);
99     }
100
101     void add32(TrustedImm32 imm, Address address)
102     {
103         load32(address, ARMRegisters::S1);
104         add32(imm, ARMRegisters::S1);
105         store32(ARMRegisters::S1, address);
106     }
107
108     void add32(TrustedImm32 imm, RegisterID dest)
109     {
110         m_assembler.adds(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
111     }
112
113     void add32(AbsoluteAddress src, RegisterID dest)
114     {
115         move(TrustedImmPtr(src.m_ptr), ARMRegisters::S1);
116         m_assembler.dtrUp(ARMAssembler::LoadUint32, ARMRegisters::S1, ARMRegisters::S1, 0);
117         add32(ARMRegisters::S1, dest);
118     }
119
120     void add32(Address src, RegisterID dest)
121     {
122         load32(src, ARMRegisters::S1);
123         add32(ARMRegisters::S1, dest);
124     }
125
126     void add32(RegisterID src, TrustedImm32 imm, RegisterID dest)
127     {
128         m_assembler.adds(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
129     }
130
131     void and32(RegisterID src, RegisterID dest)
132     {
133         m_assembler.bitAnds(dest, dest, src);
134     }
135
136     void and32(RegisterID op1, RegisterID op2, RegisterID dest)
137     {
138         m_assembler.bitAnds(dest, op1, op2);
139     }
140
141     void and32(TrustedImm32 imm, RegisterID dest)
142     {
143         ARMWord w = m_assembler.getImm(imm.m_value, ARMRegisters::S0, true);
144         if (w & ARMAssembler::Op2InvertedImmediate)
145             m_assembler.bics(dest, dest, w & ~ARMAssembler::Op2InvertedImmediate);
146         else
147             m_assembler.bitAnds(dest, dest, w);
148     }
149
150     void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
151     {
152         ARMWord w = m_assembler.getImm(imm.m_value, ARMRegisters::S0, true);
153         if (w & ARMAssembler::Op2InvertedImmediate)
154             m_assembler.bics(dest, src, w & ~ARMAssembler::Op2InvertedImmediate);
155         else
156             m_assembler.bitAnds(dest, src, w);
157     }
158
159     void and32(Address src, RegisterID dest)
160     {
161         load32(src, ARMRegisters::S1);
162         and32(ARMRegisters::S1, dest);
163     }
164
165     void lshift32(RegisterID shiftAmount, RegisterID dest)
166     {
167         lshift32(dest, shiftAmount, dest);
168     }
169
170     void lshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
171     {
172         ARMWord w = ARMAssembler::getOp2Byte(0x1f);
173         m_assembler.bitAnd(ARMRegisters::S0, shiftAmount, w);
174
175         m_assembler.movs(dest, m_assembler.lslRegister(src, ARMRegisters::S0));
176     }
177
178     void lshift32(TrustedImm32 imm, RegisterID dest)
179     {
180         m_assembler.movs(dest, m_assembler.lsl(dest, imm.m_value & 0x1f));
181     }
182
183     void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
184     {
185         m_assembler.movs(dest, m_assembler.lsl(src, imm.m_value & 0x1f));
186     }
187
188     void mul32(RegisterID op1, RegisterID op2, RegisterID dest)
189     {
190         if (op2 == dest) {
191             if (op1 == dest) {
192                 move(op2, ARMRegisters::S0);
193                 op2 = ARMRegisters::S0;
194             } else {
195                 // Swap the operands.
196                 RegisterID tmp = op1;
197                 op1 = op2;
198                 op2 = tmp;
199             }
200         }
201         m_assembler.muls(dest, op1, op2);
202     }
203
204     void mul32(RegisterID src, RegisterID dest)
205     {
206         mul32(src, dest, dest);
207     }
208
209     void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
210     {
211         move(imm, ARMRegisters::S0);
212         m_assembler.muls(dest, src, ARMRegisters::S0);
213     }
214
215     void neg32(RegisterID srcDest)
216     {
217         m_assembler.rsbs(srcDest, srcDest, ARMAssembler::getOp2Byte(0));
218     }
219
220     void or32(RegisterID src, RegisterID dest)
221     {
222         m_assembler.orrs(dest, dest, src);
223     }
224
225     void or32(RegisterID src, AbsoluteAddress dest)
226     {
227         move(TrustedImmPtr(dest.m_ptr), ARMRegisters::S0);
228         load32(Address(ARMRegisters::S0), ARMRegisters::S1);
229         or32(src, ARMRegisters::S1);
230         store32(ARMRegisters::S1, ARMRegisters::S0);
231     }
232
233     void or32(TrustedImm32 imm, AbsoluteAddress dest)
234     {
235         move(TrustedImmPtr(dest.m_ptr), ARMRegisters::S0);
236         load32(Address(ARMRegisters::S0), ARMRegisters::S1);
237         or32(imm, ARMRegisters::S1); // It uses S0 as temporary register, we need to reload the address.
238         move(TrustedImmPtr(dest.m_ptr), ARMRegisters::S0);
239         store32(ARMRegisters::S1, ARMRegisters::S0);
240     }
241
242     void or32(TrustedImm32 imm, Address address)
243     {
244         load32(address, ARMRegisters::S0);
245         or32(imm, ARMRegisters::S0, ARMRegisters::S0);
246         store32(ARMRegisters::S0, address);
247     }
248
249     void or32(TrustedImm32 imm, RegisterID dest)
250     {
251         ASSERT(dest != ARMRegisters::S0);
252         m_assembler.orrs(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
253     }
254
255     void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
256     {
257         ASSERT(src != ARMRegisters::S0);
258         m_assembler.orrs(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
259     }
260
261     void or32(RegisterID op1, RegisterID op2, RegisterID dest)
262     {
263         m_assembler.orrs(dest, op1, op2);
264     }
265
266     void rshift32(RegisterID shiftAmount, RegisterID dest)
267     {
268         rshift32(dest, shiftAmount, dest);
269     }
270
271     void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
272     {
273         ARMWord w = ARMAssembler::getOp2Byte(0x1f);
274         m_assembler.bitAnd(ARMRegisters::S0, shiftAmount, w);
275
276         m_assembler.movs(dest, m_assembler.asrRegister(src, ARMRegisters::S0));
277     }
278
279     void rshift32(TrustedImm32 imm, RegisterID dest)
280     {
281         rshift32(dest, imm, dest);
282     }
283
284     void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
285     {
286         if (!imm.m_value)
287             move(src, dest);
288         else
289             m_assembler.movs(dest, m_assembler.asr(src, imm.m_value & 0x1f));
290     }
291
292     void urshift32(RegisterID shiftAmount, RegisterID dest)
293     {
294         urshift32(dest, shiftAmount, dest);
295     }
296
297     void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
298     {
299         ARMWord w = ARMAssembler::getOp2Byte(0x1f);
300         m_assembler.bitAnd(ARMRegisters::S0, shiftAmount, w);
301
302         m_assembler.movs(dest, m_assembler.lsrRegister(src, ARMRegisters::S0));
303     }
304
305     void urshift32(TrustedImm32 imm, RegisterID dest)
306     {
307         m_assembler.movs(dest, m_assembler.lsr(dest, imm.m_value & 0x1f));
308     }
309     
310     void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
311     {
312         if (!imm.m_value)
313             move(src, dest);
314         else
315             m_assembler.movs(dest, m_assembler.lsr(src, imm.m_value & 0x1f));
316     }
317
318     void sub32(RegisterID src, RegisterID dest)
319     {
320         m_assembler.subs(dest, dest, src);
321     }
322
323     void sub32(RegisterID left, RegisterID right, RegisterID dest)
324     {
325         m_assembler.subs(dest, left, right);
326     }
327
328     void sub32(TrustedImm32 imm, RegisterID dest)
329     {
330         m_assembler.subs(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
331     }
332
333     void sub32(TrustedImm32 imm, Address address)
334     {
335         load32(address, ARMRegisters::S1);
336         sub32(imm, ARMRegisters::S1);
337         store32(ARMRegisters::S1, address);
338     }
339
340     void sub32(Address src, RegisterID dest)
341     {
342         load32(src, ARMRegisters::S1);
343         sub32(ARMRegisters::S1, dest);
344     }
345
346     void sub32(RegisterID src, TrustedImm32 imm, RegisterID dest)
347     {
348         m_assembler.subs(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
349     }
350
351     void xor32(RegisterID src, RegisterID dest)
352     {
353         m_assembler.eors(dest, dest, src);
354     }
355
356     void xor32(RegisterID op1, RegisterID op2, RegisterID dest)
357     {
358         m_assembler.eors(dest, op1, op2);
359     }
360
361     void xor32(Address src, RegisterID dest)
362     {
363         load32(src, ARMRegisters::S1);
364         xor32(ARMRegisters::S1, dest);
365     }
366
367     void xor32(TrustedImm32 imm, RegisterID dest)
368     {
369         if (imm.m_value == -1)
370             m_assembler.mvns(dest, dest);
371         else
372             m_assembler.eors(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
373     }
374
375     void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
376     {
377         if (imm.m_value == -1)
378             m_assembler.mvns(dest, src);
379         else    
380             m_assembler.eors(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
381     }
382
383     void countLeadingZeros32(RegisterID src, RegisterID dest)
384     {
385 #if WTF_ARM_ARCH_AT_LEAST(5)
386         m_assembler.clz(dest, src);
387 #else
388         UNUSED_PARAM(src);
389         UNUSED_PARAM(dest);
390         RELEASE_ASSERT_NOT_REACHED();
391 #endif
392     }
393
394     void load8(ImplicitAddress address, RegisterID dest)
395     {
396         m_assembler.dataTransfer32(ARMAssembler::LoadUint8, dest, address.base, address.offset);
397     }
398
399     void load8(BaseIndex address, RegisterID dest)
400     {
401         m_assembler.baseIndexTransfer32(ARMAssembler::LoadUint8, dest, address.base, address.index, static_cast<int>(address.scale), address.offset);
402     }
403
404     void load8(const void* address, RegisterID dest)
405     {
406         move(TrustedImmPtr(address), ARMRegisters::S0);
407         m_assembler.dataTransfer32(ARMAssembler::LoadUint8, dest, ARMRegisters::S0, 0);
408     }
409
410     void load8SignedExtendTo32(Address address, RegisterID dest)
411     {
412         m_assembler.dataTransfer16(ARMAssembler::LoadInt8, dest, address.base, address.offset);
413     }
414
415     void load8SignedExtendTo32(BaseIndex address, RegisterID dest)
416     {
417         m_assembler.baseIndexTransfer16(ARMAssembler::LoadInt8, dest, address.base, address.index, static_cast<int>(address.scale), address.offset);
418     }
419
420     void load16(ImplicitAddress address, RegisterID dest)
421     {
422         m_assembler.dataTransfer16(ARMAssembler::LoadUint16, dest, address.base, address.offset);
423     }
424
425     void load16(BaseIndex address, RegisterID dest)
426     {
427         m_assembler.baseIndexTransfer16(ARMAssembler::LoadUint16, dest, address.base, address.index, static_cast<int>(address.scale), address.offset);
428     }
429
430     void load16SignedExtendTo32(BaseIndex address, RegisterID dest)
431     {
432         m_assembler.baseIndexTransfer16(ARMAssembler::LoadInt16, dest, address.base, address.index, static_cast<int>(address.scale), address.offset);
433     }
434
435     void load32(ImplicitAddress address, RegisterID dest)
436     {
437         m_assembler.dataTransfer32(ARMAssembler::LoadUint32, dest, address.base, address.offset);
438     }
439
440     void load32(BaseIndex address, RegisterID dest)
441     {
442         m_assembler.baseIndexTransfer32(ARMAssembler::LoadUint32, dest, address.base, address.index, static_cast<int>(address.scale), address.offset);
443     }
444
445 #if CPU(ARMV5_OR_LOWER)
446     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest);
447 #else
448     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
449     {
450         load32(address, dest);
451     }
452 #endif
453
454     void load16Unaligned(BaseIndex address, RegisterID dest)
455     {
456         load16(address, dest);
457     }
458
459     void abortWithReason(AbortReason reason)
460     {
461         move(TrustedImm32(reason), ARMRegisters::S0);
462         breakpoint();
463     }
464
465     void abortWithReason(AbortReason reason, intptr_t misc)
466     {
467         move(TrustedImm32(misc), ARMRegisters::S1);
468         abortWithReason(reason);
469     }
470
471     ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest)
472     {
473         ConvertibleLoadLabel result(this);
474         ASSERT(address.offset >= 0 && address.offset <= 255);
475         m_assembler.dtrUp(ARMAssembler::LoadUint32, dest, address.base, address.offset);
476         return result;
477     }
478
479     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
480     {
481         DataLabel32 dataLabel(this);
482         m_assembler.ldrUniqueImmediate(ARMRegisters::S0, 0);
483         m_assembler.dtrUpRegister(ARMAssembler::LoadUint32, dest, address.base, ARMRegisters::S0);
484         return dataLabel;
485     }
486
487     static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value)
488     {
489         return value >= -4095 && value <= 4095;
490     }
491
492     DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
493     {
494         DataLabelCompact dataLabel(this);
495         ASSERT(isCompactPtrAlignedAddressOffset(address.offset));
496         if (address.offset >= 0)
497             m_assembler.dtrUp(ARMAssembler::LoadUint32, dest, address.base, address.offset);
498         else
499             m_assembler.dtrDown(ARMAssembler::LoadUint32, dest, address.base, address.offset);
500         return dataLabel;
501     }
502
503     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
504     {
505         DataLabel32 dataLabel(this);
506         m_assembler.ldrUniqueImmediate(ARMRegisters::S0, 0);
507         m_assembler.dtrUpRegister(ARMAssembler::StoreUint32, src, address.base, ARMRegisters::S0);
508         return dataLabel;
509     }
510
511     void store8(RegisterID src, BaseIndex address)
512     {
513         m_assembler.baseIndexTransfer32(ARMAssembler::StoreUint8, src, address.base, address.index, static_cast<int>(address.scale), address.offset);
514     }
515
516     void store8(RegisterID src, ImplicitAddress address)
517     {
518         m_assembler.dtrUp(ARMAssembler::StoreUint8, src, address.base, address.offset);
519     }
520
521     void store8(RegisterID src, const void* address)
522     {
523         move(TrustedImmPtr(address), ARMRegisters::S0);
524         m_assembler.dtrUp(ARMAssembler::StoreUint8, src, ARMRegisters::S0, 0);
525     }
526
527     void store8(TrustedImm32 imm, ImplicitAddress address)
528     {
529         TrustedImm32 imm8(static_cast<int8_t>(imm.m_value));
530         move(imm8, ARMRegisters::S1);
531         store8(ARMRegisters::S1, address);
532     }
533
534     void store8(TrustedImm32 imm, const void* address)
535     {
536         TrustedImm32 imm8(static_cast<int8_t>(imm.m_value));
537         move(TrustedImm32(reinterpret_cast<ARMWord>(address)), ARMRegisters::S0);
538         move(imm8, ARMRegisters::S1);
539         m_assembler.dtrUp(ARMAssembler::StoreUint8, ARMRegisters::S1, ARMRegisters::S0, 0);
540     }
541
542     void store16(RegisterID src, BaseIndex address)
543     {
544         m_assembler.baseIndexTransfer16(ARMAssembler::StoreUint16, src, address.base, address.index, static_cast<int>(address.scale), address.offset);
545     }
546
547     void store32(RegisterID src, ImplicitAddress address)
548     {
549         m_assembler.dataTransfer32(ARMAssembler::StoreUint32, src, address.base, address.offset);
550     }
551
552     void store32(RegisterID src, BaseIndex address)
553     {
554         m_assembler.baseIndexTransfer32(ARMAssembler::StoreUint32, src, address.base, address.index, static_cast<int>(address.scale), address.offset);
555     }
556
557     void store32(TrustedImm32 imm, ImplicitAddress address)
558     {
559         move(imm, ARMRegisters::S1);
560         store32(ARMRegisters::S1, address);
561     }
562
563     void store32(TrustedImm32 imm, BaseIndex address)
564     {
565         move(imm, ARMRegisters::S1);
566         m_assembler.baseIndexTransfer32(ARMAssembler::StoreUint32, ARMRegisters::S1, address.base, address.index, static_cast<int>(address.scale), address.offset);
567     }
568
569     void store32(RegisterID src, const void* address)
570     {
571         m_assembler.ldrUniqueImmediate(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
572         m_assembler.dtrUp(ARMAssembler::StoreUint32, src, ARMRegisters::S0, 0);
573     }
574
575     void store32(TrustedImm32 imm, const void* address)
576     {
577         m_assembler.ldrUniqueImmediate(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
578         m_assembler.moveImm(imm.m_value, ARMRegisters::S1);
579         m_assembler.dtrUp(ARMAssembler::StoreUint32, ARMRegisters::S1, ARMRegisters::S0, 0);
580     }
581
582     void pop(RegisterID dest)
583     {
584         m_assembler.pop(dest);
585     }
586
587     void popPair(RegisterID dest1, RegisterID dest2)
588     {
589         m_assembler.pop(dest1);
590         m_assembler.pop(dest2);
591     }
592
593     void push(RegisterID src)
594     {
595         m_assembler.push(src);
596     }
597
598     void push(Address address)
599     {
600         load32(address, ARMRegisters::S1);
601         push(ARMRegisters::S1);
602     }
603
604     void push(TrustedImm32 imm)
605     {
606         move(imm, ARMRegisters::S0);
607         push(ARMRegisters::S0);
608     }
609
610     void pushPair(RegisterID src1, RegisterID src2)
611     {
612         m_assembler.push(src2);
613         m_assembler.push(src1);
614     }
615
616     void move(TrustedImm32 imm, RegisterID dest)
617     {
618         m_assembler.moveImm(imm.m_value, dest);
619     }
620
621     void move(RegisterID src, RegisterID dest)
622     {
623         if (src != dest)
624             m_assembler.mov(dest, src);
625     }
626
627     void move(TrustedImmPtr imm, RegisterID dest)
628     {
629         move(TrustedImm32(imm), dest);
630     }
631
632     void swap(RegisterID reg1, RegisterID reg2)
633     {
634         xor32(reg1, reg2);
635         xor32(reg2, reg1);
636         xor32(reg1, reg2);
637     }
638
639     void signExtend32ToPtr(RegisterID src, RegisterID dest)
640     {
641         if (src != dest)
642             move(src, dest);
643     }
644
645     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
646     {
647         if (src != dest)
648             move(src, dest);
649     }
650
651     Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
652     {
653         TrustedImm32 right8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, right);
654         MacroAssemblerHelpers::load8OnCondition(*this, cond, left, ARMRegisters::S1);
655         return branch32(cond, ARMRegisters::S1, right8);
656     }
657
658     Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
659     {
660         TrustedImm32 right8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, right);
661         MacroAssemblerHelpers::load8OnCondition(*this, cond, left, ARMRegisters::S1);
662         return branch32(cond, ARMRegisters::S1, right8);
663     }
664
665     Jump branch8(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
666     {
667         TrustedImm32 right8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, right);
668         move(TrustedImmPtr(left.m_ptr), ARMRegisters::S1);
669         MacroAssemblerHelpers::load8OnCondition(*this, cond, Address(ARMRegisters::S1), ARMRegisters::S1);
670         return branch32(cond, ARMRegisters::S1, right8);
671     }
672
673     Jump branchPtr(RelationalCondition cond, BaseIndex left, RegisterID right)
674     {
675         load32(left, ARMRegisters::S1);
676         return branch32(cond, ARMRegisters::S1, right);
677     }
678
679     Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right, int useConstantPool = 0)
680     {
681         m_assembler.cmp(left, right);
682         return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
683     }
684
685     Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right, int useConstantPool = 0)
686     {
687         internalCompare32(left, right);
688         return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
689     }
690
691     Jump branch32(RelationalCondition cond, RegisterID left, Address right)
692     {
693         load32(right, ARMRegisters::S1);
694         return branch32(cond, left, ARMRegisters::S1);
695     }
696
697     Jump branch32(RelationalCondition cond, Address left, RegisterID right)
698     {
699         load32(left, ARMRegisters::S1);
700         return branch32(cond, ARMRegisters::S1, right);
701     }
702
703     Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
704     {
705         load32(left, ARMRegisters::S1);
706         return branch32(cond, ARMRegisters::S1, right);
707     }
708
709     Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
710     {
711         load32(left, ARMRegisters::S1);
712         return branch32(cond, ARMRegisters::S1, right);
713     }
714
715     Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
716     {
717         load32WithUnalignedHalfWords(left, ARMRegisters::S1);
718         return branch32(cond, ARMRegisters::S1, right);
719     }
720
721     Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
722     {
723         TrustedImm32 mask8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, mask);
724         MacroAssemblerHelpers::load8OnCondition(*this, cond, address, ARMRegisters::S1);
725         return branchTest32(cond, ARMRegisters::S1, mask8);
726     }
727
728     Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
729     {
730         TrustedImm32 mask8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, mask);
731         MacroAssemblerHelpers::load8OnCondition(*this, cond, address, ARMRegisters::S1);
732         return branchTest32(cond, ARMRegisters::S1, mask8);
733     }
734
735     Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
736     {
737         TrustedImm32 mask8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, mask);
738         move(TrustedImmPtr(address.m_ptr), ARMRegisters::S1);
739         MacroAssemblerHelpers::load8OnCondition(*this, cond, Address(ARMRegisters::S1), ARMRegisters::S1);
740         return branchTest32(cond, ARMRegisters::S1, mask8);
741     }
742
743     Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
744     {
745         ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == PositiveOrZero);
746         m_assembler.tst(reg, mask);
747         return Jump(m_assembler.jmp(ARMCondition(cond)));
748     }
749
750     Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
751     {
752         ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == PositiveOrZero);
753         ARMWord w = m_assembler.getImm(mask.m_value, ARMRegisters::S0, true);
754         if (w & ARMAssembler::Op2InvertedImmediate)
755             m_assembler.bics(ARMRegisters::S0, reg, w & ~ARMAssembler::Op2InvertedImmediate);
756         else
757             m_assembler.tst(reg, w);
758         return Jump(m_assembler.jmp(ARMCondition(cond)));
759     }
760
761     Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
762     {
763         load32(address, ARMRegisters::S1);
764         return branchTest32(cond, ARMRegisters::S1, mask);
765     }
766
767     Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
768     {
769         load32(address, ARMRegisters::S1);
770         return branchTest32(cond, ARMRegisters::S1, mask);
771     }
772
773     Jump jump()
774     {
775         return Jump(m_assembler.jmp());
776     }
777
778     void jump(RegisterID target)
779     {
780         m_assembler.bx(target);
781     }
782
783     void jump(Address address)
784     {
785         load32(address, ARMRegisters::pc);
786     }
787
788     void jump(AbsoluteAddress address)
789     {
790         move(TrustedImmPtr(address.m_ptr), ARMRegisters::S0);
791         load32(Address(ARMRegisters::S0, 0), ARMRegisters::pc);
792     }
793
794     void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2)
795     {
796         m_assembler.vmov(dest1, dest2, src);
797     }
798
799     void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID)
800     {
801         m_assembler.vmov(dest, src1, src2);
802     }
803
804     Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
805     {
806         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero)
807             || (cond == NonZero) || (cond == PositiveOrZero));
808         add32(src, dest);
809         return Jump(m_assembler.jmp(ARMCondition(cond)));
810     }
811
812     Jump branchAdd32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest)
813     {
814         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero)
815             || (cond == NonZero) || (cond == PositiveOrZero));
816         add32(op1, op2, dest);
817         return Jump(m_assembler.jmp(ARMCondition(cond)));
818     }
819
820     Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
821     {
822         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero)
823             || (cond == NonZero) || (cond == PositiveOrZero));
824         add32(imm, dest);
825         return Jump(m_assembler.jmp(ARMCondition(cond)));
826     }
827
828     Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
829     {
830         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero)
831             || (cond == NonZero) || (cond == PositiveOrZero));
832         add32(src, imm, dest);
833         return Jump(m_assembler.jmp(ARMCondition(cond)));
834     }
835
836     Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
837     {
838         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero)
839             || (cond == NonZero) || (cond == PositiveOrZero));
840         add32(imm, dest);
841         return Jump(m_assembler.jmp(ARMCondition(cond)));
842     }
843
844     Jump branchAdd32(ResultCondition cond, Address src, RegisterID dest)
845     {
846         load32(src, ARMRegisters::S0);
847         return branchAdd32(cond, dest, ARMRegisters::S0, dest);
848     }
849     void mull32(RegisterID op1, RegisterID op2, RegisterID dest)
850     {
851         if (op2 == dest) {
852             if (op1 == dest) {
853                 move(op2, ARMRegisters::S0);
854                 op2 = ARMRegisters::S0;
855             } else {
856                 // Swap the operands.
857                 RegisterID tmp = op1;
858                 op1 = op2;
859                 op2 = tmp;
860             }
861         }
862         m_assembler.mull(ARMRegisters::S1, dest, op1, op2);
863         m_assembler.cmp(ARMRegisters::S1, m_assembler.asr(dest, 31));
864     }
865
866     Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
867     {
868         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
869         if (cond == Overflow) {
870             mull32(src1, src2, dest);
871             cond = NonZero;
872         }
873         else
874             mul32(src1, src2, dest);
875         return Jump(m_assembler.jmp(ARMCondition(cond)));
876     }
877
878     Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
879     {
880         return branchMul32(cond, src, dest, dest);
881     }
882
883     Jump branchMul32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
884     {
885         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
886         if (cond == Overflow) {
887             move(imm, ARMRegisters::S0);
888             mull32(ARMRegisters::S0, src, dest);
889             cond = NonZero;
890         }
891         else
892             mul32(imm, src, dest);
893         return Jump(m_assembler.jmp(ARMCondition(cond)));
894     }
895
896     Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
897     {
898         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
899         sub32(src, dest);
900         return Jump(m_assembler.jmp(ARMCondition(cond)));
901     }
902
903     Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
904     {
905         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
906         sub32(imm, dest);
907         return Jump(m_assembler.jmp(ARMCondition(cond)));
908     }
909
910     Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
911     {
912         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
913         sub32(src, imm, dest);
914         return Jump(m_assembler.jmp(ARMCondition(cond)));
915     }
916
917     Jump branchSub32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest)
918     {
919         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
920         m_assembler.subs(dest, op1, op2);
921         return Jump(m_assembler.jmp(ARMCondition(cond)));
922     }
923
924     Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
925     {
926         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
927         neg32(srcDest);
928         return Jump(m_assembler.jmp(ARMCondition(cond)));
929     }
930
931     Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
932     {
933         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
934         or32(src, dest);
935         return Jump(m_assembler.jmp(ARMCondition(cond)));
936     }
937
938     PatchableJump patchableJump()
939     {
940         return PatchableJump(m_assembler.jmp(ARMAssembler::AL, 1));
941     }
942
943     PatchableJump patchableBranch32(RelationalCondition cond, RegisterID reg, TrustedImm32 imm)
944     {
945         internalCompare32(reg, imm);
946         Jump jump(m_assembler.loadBranchTarget(ARMRegisters::S1, ARMCondition(cond), true));
947         m_assembler.bx(ARMRegisters::S1, ARMCondition(cond));
948         return PatchableJump(jump);
949     }
950
951     PatchableJump patchableBranch32(RelationalCondition cond, Address address, TrustedImm32 imm)
952     {
953         internalCompare32(address, imm);
954         Jump jump(m_assembler.loadBranchTarget(ARMRegisters::S1, ARMCondition(cond), false));
955         m_assembler.bx(ARMRegisters::S1, ARMCondition(cond));
956         return PatchableJump(jump);
957     }
958
959     void breakpoint()
960     {
961         m_assembler.bkpt(0);
962     }
963
964     static bool isBreakpoint(void* address) { return ARMAssembler::isBkpt(address); }
965
966     Call nearCall()
967     {
968         m_assembler.loadBranchTarget(ARMRegisters::S1, ARMAssembler::AL, true);
969         return Call(m_assembler.blx(ARMRegisters::S1), Call::LinkableNear);
970     }
971
972     Call nearTailCall()
973     {
974         return Call(m_assembler.jmp(), Call::LinkableNearTail);
975     }
976
977     Call call(RegisterID target)
978     {
979         return Call(m_assembler.blx(target), Call::None);
980     }
981
982     void call(Address address)
983     {
984         call32(address.base, address.offset);
985     }
986
987     void ret()
988     {
989         m_assembler.bx(linkRegister);
990     }
991
992     void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
993     {
994         m_assembler.cmp(left, right);
995         m_assembler.mov(dest, ARMAssembler::getOp2Byte(0));
996         m_assembler.mov(dest, ARMAssembler::getOp2Byte(1), ARMCondition(cond));
997     }
998
999     void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
1000     {
1001         m_assembler.cmp(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
1002         m_assembler.mov(dest, ARMAssembler::getOp2Byte(0));
1003         m_assembler.mov(dest, ARMAssembler::getOp2Byte(1), ARMCondition(cond));
1004     }
1005
1006     void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
1007     {
1008         TrustedImm32 right8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, right);
1009         MacroAssemblerHelpers::load8OnCondition(*this, cond, left, ARMRegisters::S1);
1010         compare32(cond, ARMRegisters::S1, right8, dest);
1011     }
1012
1013     void test32(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest)
1014     {
1015         if (mask.m_value == -1)
1016             m_assembler.tst(reg, reg);
1017         else
1018             m_assembler.tst(reg, m_assembler.getImm(mask.m_value, ARMRegisters::S0));
1019         m_assembler.mov(dest, ARMAssembler::getOp2Byte(0));
1020         m_assembler.mov(dest, ARMAssembler::getOp2Byte(1), ARMCondition(cond));
1021     }
1022
1023     void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
1024     {
1025         load32(address, ARMRegisters::S1);
1026         test32(cond, ARMRegisters::S1, mask, dest);
1027     }
1028
1029     void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
1030     {
1031         TrustedImm32 mask8 = MacroAssemblerHelpers::mask8OnCondition(*this, cond, mask);
1032         MacroAssemblerHelpers::load8OnCondition(*this, cond, address, ARMRegisters::S1);
1033         test32(cond, ARMRegisters::S1, mask8, dest);
1034     }
1035
1036     void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
1037     {
1038         m_assembler.add(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
1039     }
1040
1041     void add32(TrustedImm32 imm, AbsoluteAddress address)
1042     {
1043         load32(address.m_ptr, ARMRegisters::S1);
1044         add32(imm, ARMRegisters::S1);
1045         store32(ARMRegisters::S1, address.m_ptr);
1046     }
1047
1048     void add64(TrustedImm32 imm, AbsoluteAddress address)
1049     {
1050         ARMWord tmp;
1051
1052         move(TrustedImmPtr(address.m_ptr), ARMRegisters::S1);
1053         m_assembler.dtrUp(ARMAssembler::LoadUint32, ARMRegisters::S0, ARMRegisters::S1, 0);
1054
1055         if ((tmp = ARMAssembler::getOp2(imm.m_value)) != ARMAssembler::InvalidImmediate)
1056             m_assembler.adds(ARMRegisters::S0, ARMRegisters::S0, tmp);
1057         else if ((tmp = ARMAssembler::getOp2(-imm.m_value)) != ARMAssembler::InvalidImmediate)
1058             m_assembler.subs(ARMRegisters::S0, ARMRegisters::S0, tmp);
1059         else {
1060             m_assembler.adds(ARMRegisters::S0, ARMRegisters::S0, m_assembler.getImm(imm.m_value, ARMRegisters::S1));
1061             move(TrustedImmPtr(address.m_ptr), ARMRegisters::S1);
1062         }
1063         m_assembler.dtrUp(ARMAssembler::StoreUint32, ARMRegisters::S0, ARMRegisters::S1, 0);
1064
1065         m_assembler.dtrUp(ARMAssembler::LoadUint32, ARMRegisters::S0, ARMRegisters::S1, sizeof(ARMWord));
1066         if (imm.m_value >= 0)
1067             m_assembler.adc(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Byte(0));
1068         else
1069             m_assembler.sbc(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Byte(0));
1070         m_assembler.dtrUp(ARMAssembler::StoreUint32, ARMRegisters::S0, ARMRegisters::S1, sizeof(ARMWord));
1071     }
1072
1073     void sub32(TrustedImm32 imm, AbsoluteAddress address)
1074     {
1075         load32(address.m_ptr, ARMRegisters::S1);
1076         sub32(imm, ARMRegisters::S1);
1077         store32(ARMRegisters::S1, address.m_ptr);
1078     }
1079
1080     void load32(const void* address, RegisterID dest)
1081     {
1082         m_assembler.ldrUniqueImmediate(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
1083         m_assembler.dtrUp(ARMAssembler::LoadUint32, dest, ARMRegisters::S0, 0);
1084     }
1085
1086     Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
1087     {
1088         load32(left.m_ptr, ARMRegisters::S1);
1089         return branch32(cond, ARMRegisters::S1, right);
1090     }
1091
1092     Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
1093     {
1094         load32(left.m_ptr, ARMRegisters::S1);
1095         return branch32(cond, ARMRegisters::S1, right);
1096     }
1097
1098     void relativeTableJump(RegisterID index, int scale)
1099     {
1100         ASSERT(scale >= 0 && scale <= 31);
1101         m_assembler.add(ARMRegisters::pc, ARMRegisters::pc, m_assembler.lsl(index, scale));
1102
1103         // NOP the default prefetching
1104         m_assembler.mov(ARMRegisters::r0, ARMRegisters::r0);
1105     }
1106
1107     Call call()
1108     {
1109         ensureSpace(2 * sizeof(ARMWord), sizeof(ARMWord));
1110         m_assembler.loadBranchTarget(ARMRegisters::S1, ARMAssembler::AL, true);
1111         return Call(m_assembler.blx(ARMRegisters::S1), Call::Linkable);
1112     }
1113
1114     Call tailRecursiveCall()
1115     {
1116         return Call::fromTailJump(jump());
1117     }
1118
1119     Call makeTailRecursiveCall(Jump oldJump)
1120     {
1121         return Call::fromTailJump(oldJump);
1122     }
1123
1124     DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
1125     {
1126         DataLabelPtr dataLabel(this);
1127         m_assembler.ldrUniqueImmediate(dest, reinterpret_cast<ARMWord>(initialValue.m_value));
1128         return dataLabel;
1129     }
1130
1131     DataLabel32 moveWithPatch(TrustedImm32 initialValue, RegisterID dest)
1132     {
1133         DataLabel32 dataLabel(this);
1134         m_assembler.ldrUniqueImmediate(dest, static_cast<ARMWord>(initialValue.m_value));
1135         return dataLabel;
1136     }
1137
1138     Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
1139     {
1140         ensureSpace(3 * sizeof(ARMWord), 2 * sizeof(ARMWord));
1141         dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S1);
1142         Jump jump = branch32(cond, left, ARMRegisters::S1, true);
1143         return jump;
1144     }
1145
1146     Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
1147     {
1148         load32(left, ARMRegisters::S1);
1149         ensureSpace(3 * sizeof(ARMWord), 2 * sizeof(ARMWord));
1150         dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S0);
1151         Jump jump = branch32(cond, ARMRegisters::S0, ARMRegisters::S1, true);
1152         return jump;
1153     }
1154
1155     Jump branch32WithPatch(RelationalCondition cond, Address left, DataLabel32& dataLabel, TrustedImm32 initialRightValue = TrustedImm32(0))
1156     {
1157         load32(left, ARMRegisters::S1);
1158         ensureSpace(3 * sizeof(ARMWord), 2 * sizeof(ARMWord));
1159         dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S0);
1160         Jump jump = branch32(cond, ARMRegisters::S0, ARMRegisters::S1, true);
1161         return jump;
1162     }
1163
1164     DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
1165     {
1166         DataLabelPtr dataLabel = moveWithPatch(initialValue, ARMRegisters::S1);
1167         store32(ARMRegisters::S1, address);
1168         return dataLabel;
1169     }
1170
1171     DataLabelPtr storePtrWithPatch(ImplicitAddress address)
1172     {
1173         return storePtrWithPatch(TrustedImmPtr(0), address);
1174     }
1175
1176     // Floating point operators
1177     static bool supportsFloatingPoint()
1178     {
1179         return s_isVFPPresent;
1180     }
1181
1182     static bool supportsFloatingPointTruncate()
1183     {
1184         return false;
1185     }
1186
1187     static bool supportsFloatingPointSqrt()
1188     {
1189         return s_isVFPPresent;
1190     }
1191     static bool supportsFloatingPointAbs() { return false; }
1192     static bool supportsFloatingPointRounding() { return false; }
1193
1194
1195     void loadFloat(ImplicitAddress address, FPRegisterID dest)
1196     {
1197         m_assembler.dataTransferFloat(ARMAssembler::LoadFloat, dest, address.base, address.offset);
1198     }
1199
1200     void loadFloat(BaseIndex address, FPRegisterID dest)
1201     {
1202         m_assembler.baseIndexTransferFloat(ARMAssembler::LoadFloat, dest, address.base, address.index, static_cast<int>(address.scale), address.offset);
1203     }
1204
1205     void loadDouble(ImplicitAddress address, FPRegisterID dest)
1206     {
1207         m_assembler.dataTransferFloat(ARMAssembler::LoadDouble, dest, address.base, address.offset);
1208     }
1209
1210     void loadDouble(BaseIndex address, FPRegisterID dest)
1211     {
1212         m_assembler.baseIndexTransferFloat(ARMAssembler::LoadDouble, dest, address.base, address.index, static_cast<int>(address.scale), address.offset);
1213     }
1214
1215     void loadDouble(TrustedImmPtr address, FPRegisterID dest)
1216     {
1217         move(TrustedImm32(reinterpret_cast<ARMWord>(address.m_value)), ARMRegisters::S0);
1218         m_assembler.doubleDtrUp(ARMAssembler::LoadDouble, dest, ARMRegisters::S0, 0);
1219     }
1220
1221     NO_RETURN_DUE_TO_CRASH void ceilDouble(FPRegisterID, FPRegisterID)
1222     {
1223         ASSERT(!supportsFloatingPointRounding());
1224         CRASH();
1225     }
1226
1227     NO_RETURN_DUE_TO_CRASH void floorDouble(FPRegisterID, FPRegisterID)
1228     {
1229         ASSERT(!supportsFloatingPointRounding());
1230         CRASH();
1231     }
1232
1233     NO_RETURN_DUE_TO_CRASH void roundTowardZeroDouble(FPRegisterID, FPRegisterID)
1234     {
1235         ASSERT(!supportsFloatingPointRounding());
1236         CRASH();
1237     }
1238
1239     void storeFloat(FPRegisterID src, ImplicitAddress address)
1240     {
1241         m_assembler.dataTransferFloat(ARMAssembler::StoreFloat, src, address.base, address.offset);
1242     }
1243
1244     void storeFloat(FPRegisterID src, BaseIndex address)
1245     {
1246         m_assembler.baseIndexTransferFloat(ARMAssembler::StoreFloat, src, address.base, address.index, static_cast<int>(address.scale), address.offset);
1247     }
1248
1249     void storeDouble(FPRegisterID src, ImplicitAddress address)
1250     {
1251         m_assembler.dataTransferFloat(ARMAssembler::StoreDouble, src, address.base, address.offset);
1252     }
1253
1254     void storeDouble(FPRegisterID src, BaseIndex address)
1255     {
1256         m_assembler.baseIndexTransferFloat(ARMAssembler::StoreDouble, src, address.base, address.index, static_cast<int>(address.scale), address.offset);
1257     }
1258
1259     void storeDouble(FPRegisterID src, TrustedImmPtr address)
1260     {
1261         move(TrustedImm32(reinterpret_cast<ARMWord>(address.m_value)), ARMRegisters::S0);
1262         m_assembler.dataTransferFloat(ARMAssembler::StoreDouble, src, ARMRegisters::S0, 0);
1263     }
1264
1265     void moveDouble(FPRegisterID src, FPRegisterID dest)
1266     {
1267         if (src != dest)
1268             m_assembler.vmov_f64(dest, src);
1269     }
1270
1271     void moveZeroToDouble(FPRegisterID reg)
1272     {
1273         static double zeroConstant = 0.;
1274         loadDouble(TrustedImmPtr(&zeroConstant), reg);
1275     }
1276
1277     void addDouble(FPRegisterID src, FPRegisterID dest)
1278     {
1279         m_assembler.vadd_f64(dest, dest, src);
1280     }
1281
1282     void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1283     {
1284         m_assembler.vadd_f64(dest, op1, op2);
1285     }
1286
1287     void addDouble(Address src, FPRegisterID dest)
1288     {
1289         loadDouble(src, ARMRegisters::SD0);
1290         addDouble(ARMRegisters::SD0, dest);
1291     }
1292
1293     void addDouble(AbsoluteAddress address, FPRegisterID dest)
1294     {
1295         loadDouble(TrustedImmPtr(address.m_ptr), ARMRegisters::SD0);
1296         addDouble(ARMRegisters::SD0, dest);
1297     }
1298
1299     void divDouble(FPRegisterID src, FPRegisterID dest)
1300     {
1301         m_assembler.vdiv_f64(dest, dest, src);
1302     }
1303
1304     void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1305     {
1306         m_assembler.vdiv_f64(dest, op1, op2);
1307     }
1308
1309     void divDouble(Address src, FPRegisterID dest)
1310     {
1311         RELEASE_ASSERT_NOT_REACHED(); // Untested
1312         loadDouble(src, ARMRegisters::SD0);
1313         divDouble(ARMRegisters::SD0, dest);
1314     }
1315
1316     void subDouble(FPRegisterID src, FPRegisterID dest)
1317     {
1318         m_assembler.vsub_f64(dest, dest, src);
1319     }
1320
1321     void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1322     {
1323         m_assembler.vsub_f64(dest, op1, op2);
1324     }
1325
1326     void subDouble(Address src, FPRegisterID dest)
1327     {
1328         loadDouble(src, ARMRegisters::SD0);
1329         subDouble(ARMRegisters::SD0, dest);
1330     }
1331
1332     void mulDouble(FPRegisterID src, FPRegisterID dest)
1333     {
1334         m_assembler.vmul_f64(dest, dest, src);
1335     }
1336
1337     void mulDouble(Address src, FPRegisterID dest)
1338     {
1339         loadDouble(src, ARMRegisters::SD0);
1340         mulDouble(ARMRegisters::SD0, dest);
1341     }
1342
1343     void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1344     {
1345         m_assembler.vmul_f64(dest, op1, op2);
1346     }
1347
1348     void sqrtDouble(FPRegisterID src, FPRegisterID dest)
1349     {
1350         m_assembler.vsqrt_f64(dest, src);
1351     }
1352     
1353     void absDouble(FPRegisterID src, FPRegisterID dest)
1354     {
1355         m_assembler.vabs_f64(dest, src);
1356     }
1357
1358     void negateDouble(FPRegisterID src, FPRegisterID dest)
1359     {
1360         m_assembler.vneg_f64(dest, src);
1361     }
1362
1363     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
1364     {
1365         m_assembler.vmov_vfp32(dest << 1, src);
1366         m_assembler.vcvt_f64_s32(dest, dest << 1);
1367     }
1368
1369     void convertInt32ToDouble(Address src, FPRegisterID dest)
1370     {
1371         load32(src, ARMRegisters::S1);
1372         convertInt32ToDouble(ARMRegisters::S1, dest);
1373     }
1374
1375     void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
1376     {
1377         move(TrustedImmPtr(src.m_ptr), ARMRegisters::S1);
1378         load32(Address(ARMRegisters::S1), ARMRegisters::S1);
1379         convertInt32ToDouble(ARMRegisters::S1, dest);
1380     }
1381
1382     void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
1383     {
1384         m_assembler.vcvt_f64_f32(dst, src);
1385     }
1386
1387     void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst)
1388     {
1389         m_assembler.vcvt_f32_f64(dst, src);
1390     }
1391
1392     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
1393     {
1394         m_assembler.vcmp_f64(left, right);
1395         m_assembler.vmrs_apsr();
1396         if (cond & DoubleConditionBitSpecial)
1397             m_assembler.cmp(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::VS);
1398         return Jump(m_assembler.jmp(static_cast<ARMAssembler::Condition>(cond & ~DoubleConditionMask)));
1399     }
1400
1401     // Truncates 'src' to an integer, and places the resulting 'dest'.
1402     // If the result is not representable as a 32 bit value, branch.
1403     // May also branch for some values that are representable in 32 bits
1404     // (specifically, in this case, INT_MIN).
1405     enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
1406     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
1407     {
1408         truncateDoubleToInt32(src, dest);
1409
1410         m_assembler.add(ARMRegisters::S0, dest, ARMAssembler::getOp2Byte(1));
1411         m_assembler.bic(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Byte(1));
1412
1413         ARMWord w = ARMAssembler::getOp2(0x80000000);
1414         ASSERT(w != ARMAssembler::InvalidImmediate);
1415         m_assembler.cmp(ARMRegisters::S0, w);
1416         return Jump(m_assembler.jmp(branchType == BranchIfTruncateFailed ? ARMAssembler::EQ : ARMAssembler::NE));
1417     }
1418
1419     Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
1420     {
1421         truncateDoubleToUint32(src, dest);
1422
1423         m_assembler.add(ARMRegisters::S0, dest, ARMAssembler::getOp2Byte(1));
1424         m_assembler.bic(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Byte(1));
1425
1426         m_assembler.cmp(ARMRegisters::S0, ARMAssembler::getOp2Byte(0));
1427         return Jump(m_assembler.jmp(branchType == BranchIfTruncateFailed ? ARMAssembler::EQ : ARMAssembler::NE));
1428     }
1429
1430     // Result is undefined if the value is outside of the integer range.
1431     void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
1432     {
1433         m_assembler.vcvt_s32_f64(ARMRegisters::SD0 << 1, src);
1434         m_assembler.vmov_arm32(dest, ARMRegisters::SD0 << 1);
1435     }
1436
1437     void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
1438     {
1439         m_assembler.vcvt_u32_f64(ARMRegisters::SD0 << 1, src);
1440         m_assembler.vmov_arm32(dest, ARMRegisters::SD0 << 1);
1441     }
1442
1443     // Convert 'src' to an integer, and places the resulting 'dest'.
1444     // If the result is not representable as a 32 bit value, branch.
1445     // May also branch for some values that are representable in 32 bits
1446     // (specifically, in this case, 0).
1447     void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID, bool negZeroCheck = true)
1448     {
1449         m_assembler.vcvt_s32_f64(ARMRegisters::SD0 << 1, src);
1450         m_assembler.vmov_arm32(dest, ARMRegisters::SD0 << 1);
1451
1452         // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
1453         m_assembler.vcvt_f64_s32(ARMRegisters::SD0, ARMRegisters::SD0 << 1);
1454         failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, ARMRegisters::SD0));
1455
1456         // If the result is zero, it might have been -0.0, and 0.0 equals to -0.0
1457         if (negZeroCheck)
1458             failureCases.append(branchTest32(Zero, dest));
1459     }
1460
1461     Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
1462     {
1463         m_assembler.mov(ARMRegisters::S0, ARMAssembler::getOp2Byte(0));
1464         convertInt32ToDouble(ARMRegisters::S0, scratch);
1465         return branchDouble(DoubleNotEqual, reg, scratch);
1466     }
1467
1468     Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
1469     {
1470         m_assembler.mov(ARMRegisters::S0, ARMAssembler::getOp2Byte(0));
1471         convertInt32ToDouble(ARMRegisters::S0, scratch);
1472         return branchDouble(DoubleEqualOrUnordered, reg, scratch);
1473     }
1474
1475     // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc.
1476     static RelationalCondition invert(RelationalCondition cond)
1477     {
1478         ASSERT((static_cast<uint32_t>(cond & 0x0fffffff)) == 0 && static_cast<uint32_t>(cond) < static_cast<uint32_t>(ARMAssembler::AL));
1479         return static_cast<RelationalCondition>(cond ^ 0x10000000);
1480     }
1481
1482     void nop()
1483     {
1484         m_assembler.nop();
1485     }
1486
1487     void memoryFence()
1488     {
1489         m_assembler.dmbSY();
1490     }
1491
1492     void storeFence()
1493     {
1494         m_assembler.dmbISHST();
1495     }
1496
1497     static FunctionPtr readCallTarget(CodeLocationCall call)
1498     {
1499         return FunctionPtr(reinterpret_cast<void(*)()>(ARMAssembler::readCallTarget(call.dataLocation())));
1500     }
1501
1502     static void replaceWithBreakpoint(CodeLocationLabel instructionStart)
1503     {
1504         ARMAssembler::replaceWithBkpt(instructionStart.executableAddress());
1505     }
1506
1507     static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
1508     {
1509         ARMAssembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation());
1510     }
1511     
1512     static ptrdiff_t maxJumpReplacementSize()
1513     {
1514         return ARMAssembler::maxJumpReplacementSize();
1515     }
1516
1517     static ptrdiff_t patchableJumpSize()
1518     {
1519         return ARMAssembler::patchableJumpSize();
1520     }
1521
1522     static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; }
1523     static bool canJumpReplacePatchableBranch32WithPatch() { return false; }
1524
1525     static CodeLocationLabel startOfPatchableBranch32WithPatchOnAddress(CodeLocationDataLabel32)
1526     {
1527         UNREACHABLE_FOR_PLATFORM();
1528         return CodeLocationLabel();
1529     }
1530
1531     static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr)
1532     {
1533         UNREACHABLE_FOR_PLATFORM();
1534         return CodeLocationLabel();
1535     }
1536
1537     static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label)
1538     {
1539         return label.labelAtOffset(0);
1540     }
1541
1542     static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID reg, void* initialValue)
1543     {
1544         ARMAssembler::revertBranchPtrWithPatch(instructionStart.dataLocation(), reg, reinterpret_cast<uintptr_t>(initialValue) & 0xffff);
1545     }
1546
1547     static void revertJumpReplacementToPatchableBranch32WithPatch(CodeLocationLabel, Address, int32_t)
1548     {
1549         UNREACHABLE_FOR_PLATFORM();
1550     }
1551
1552     static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel, Address, void*)
1553     {
1554         UNREACHABLE_FOR_PLATFORM();
1555     }
1556
1557     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
1558     {
1559         ARMAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
1560     }
1561
1562     static void repatchCall(CodeLocationCall call, FunctionPtr destination)
1563     {
1564         ARMAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
1565     }
1566
1567 #if ENABLE(MASM_PROBE)
1568     void probe(ProbeFunction, void* arg);
1569 #endif // ENABLE(MASM_PROBE)
1570
1571 protected:
1572     ARMAssembler::Condition ARMCondition(RelationalCondition cond)
1573     {
1574         return static_cast<ARMAssembler::Condition>(cond);
1575     }
1576
1577     ARMAssembler::Condition ARMCondition(ResultCondition cond)
1578     {
1579         return static_cast<ARMAssembler::Condition>(cond);
1580     }
1581
1582     void ensureSpace(int insnSpace, int constSpace)
1583     {
1584         m_assembler.ensureSpace(insnSpace, constSpace);
1585     }
1586
1587     int sizeOfConstantPool()
1588     {
1589         return m_assembler.sizeOfConstantPool();
1590     }
1591
1592     void call32(RegisterID base, int32_t offset)
1593     {
1594         load32(Address(base, offset), ARMRegisters::S1);
1595         m_assembler.blx(ARMRegisters::S1);
1596     }
1597
1598 private:
1599     friend class LinkBuffer;
1600
1601     void internalCompare32(RegisterID left, TrustedImm32 right)
1602     {
1603         ARMWord tmp = (!right.value || static_cast<unsigned>(right.m_value) == 0x80000000) ? ARMAssembler::InvalidImmediate : m_assembler.getOp2(-right.m_value);
1604         if (tmp != ARMAssembler::InvalidImmediate)
1605             m_assembler.cmn(left, tmp);
1606         else
1607             m_assembler.cmp(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
1608     }
1609
1610     void internalCompare32(Address left, TrustedImm32 right)
1611     {
1612         ARMWord tmp = (!right.value || static_cast<unsigned>(right.m_value) == 0x80000000) ? ARMAssembler::InvalidImmediate : m_assembler.getOp2(-right.m_value);
1613         load32(left, ARMRegisters::S1);
1614         if (tmp != ARMAssembler::InvalidImmediate)
1615             m_assembler.cmn(ARMRegisters::S1, tmp);
1616         else
1617             m_assembler.cmp(ARMRegisters::S1, m_assembler.getImm(right.m_value, ARMRegisters::S0));
1618     }
1619
1620     static void linkCall(void* code, Call call, FunctionPtr function)
1621     {
1622         if (call.isFlagSet(Call::Tail))
1623             ARMAssembler::linkJump(code, call.m_label, function.value());
1624         else
1625             ARMAssembler::linkCall(code, call.m_label, function.value());
1626     }
1627
1628
1629 #if ENABLE(MASM_PROBE)
1630     inline TrustedImm32 trustedImm32FromPtr(void* ptr)
1631     {
1632         return TrustedImm32(TrustedImmPtr(ptr));
1633     }
1634
1635     inline TrustedImm32 trustedImm32FromPtr(ProbeFunction function)
1636     {
1637         return TrustedImm32(TrustedImmPtr(reinterpret_cast<void*>(function)));
1638     }
1639
1640     inline TrustedImm32 trustedImm32FromPtr(void (*function)())
1641     {
1642         return TrustedImm32(TrustedImmPtr(reinterpret_cast<void*>(function)));
1643     }
1644 #endif
1645
1646     static const bool s_isVFPPresent;
1647 };
1648
1649 } // namespace JSC
1650
1651 #endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)