2008-12-01 Gavin Barraclough <barraclough@apple.com>
[WebKit-https.git] / JavaScriptCore / assembler / X86Assembler.h
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 #ifndef X86Assembler_h
27 #define X86Assembler_h
28
29 #include <wtf/Platform.h>
30
31 #if ENABLE(ASSEMBLER) && (PLATFORM(X86) || PLATFORM(X86_64))
32
33 #include "AssemblerBuffer.h"
34 #include <stdint.h>
35 #include <wtf/Assertions.h>
36 #include <wtf/Vector.h>
37
38 namespace JSC {
39
40 #define MODRM(type, reg, rm) ((type << 6) | (reg << 3) | (rm))
41 #define SIB(type, reg, rm) MODRM(type, reg, rm)
42 #define CAN_SIGN_EXTEND_8_32(value) (value == ((int)(signed char)value))
43
44 namespace X86 {
45     typedef enum {
46         eax,
47         ecx,
48         edx,
49         ebx,
50         esp,
51         ebp,
52         esi,
53         edi,
54
55         noBase = ebp,
56         hasSib = esp,
57         noScale = esp,
58     } RegisterID;
59
60     typedef enum {
61         xmm0,
62         xmm1,
63         xmm2,
64         xmm3,
65         xmm4,
66         xmm5,
67         xmm6,
68         xmm7,
69     } XMMRegisterID;
70 }
71
72 class X86Assembler {
73 public:
74     typedef X86::RegisterID RegisterID;
75     typedef X86::XMMRegisterID XMMRegisterID;
76
77     typedef enum {
78         OP_ADD_EvGv                     = 0x01,
79         OP_ADD_GvEv                     = 0x03,
80         OP_OR_EvGv                      = 0x09,
81         OP_OR_GvEv                      = 0x0B,
82         OP_2BYTE_ESCAPE                 = 0x0F,
83         OP_AND_EvGv                     = 0x21,
84         OP_SUB_EvGv                     = 0x29,
85         OP_SUB_GvEv                     = 0x2B,
86         PRE_PREDICT_BRANCH_NOT_TAKEN    = 0x2E,
87         OP_XOR_EvGv                     = 0x31,
88         OP_CMP_EvGv                     = 0x39,
89         OP_CMP_GvEv                     = 0x3B,
90         REX_W                           = 0x48,
91         OP_PUSH_EAX                     = 0x50,
92         OP_POP_EAX                      = 0x58,
93         PRE_OPERAND_SIZE                = 0x66,
94         PRE_SSE_66                      = 0x66,
95         OP_PUSH_Iz                      = 0x68,
96         OP_IMUL_GvEvIz                  = 0x69,
97         OP_GROUP1_EvIz                  = 0x81,
98         OP_GROUP1_EvIb                  = 0x83,
99         OP_TEST_EvGv                    = 0x85,
100         OP_MOV_EvGv                     = 0x89,
101         OP_MOV_GvEv                     = 0x8B,
102         OP_LEA                          = 0x8D,
103         OP_GROUP1A_Ev                   = 0x8F,
104         OP_CDQ                          = 0x99,
105         OP_SETE                         = 0x94,
106         OP_SETNE                        = 0x95,
107         OP_GROUP2_EvIb                  = 0xC1,
108         OP_RET                          = 0xC3,
109         OP_GROUP11_EvIz                 = 0xC7,
110         OP_INT3                         = 0xCC,
111         OP_GROUP2_Ev1                   = 0xD1,
112         OP_GROUP2_EvCL                  = 0xD3,
113         OP_CALL_rel32                   = 0xE8,
114         OP_JMP_rel32                    = 0xE9,
115         PRE_SSE_F2                      = 0xF2,
116         OP_HLT                          = 0xF4,
117         OP_GROUP3_Ev                    = 0xF7,
118         OP_GROUP3_EvIz                  = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test. 
119         OP_GROUP5_Ev                    = 0xFF,
120
121         OP2_MOVSD_VsdWsd    = 0x10,
122         OP2_MOVSD_WsdVsd    = 0x11,
123         OP2_CVTSI2SD_VsdEd  = 0x2A,
124         OP2_CVTTSD2SI_GdWsd = 0x2C,
125         OP2_UCOMISD_VsdWsd  = 0x2E,
126         OP2_XORPD_VsdWsd    = 0x57,
127         OP2_ADDSD_VsdWsd    = 0x58,
128         OP2_MULSD_VsdWsd    = 0x59,
129         OP2_SUBSD_VsdWsd    = 0x5C,
130         OP2_MOVD_EdVd       = 0x7E,
131         OP2_JO_rel32        = 0x80,
132         OP2_JB_rel32        = 0x82,
133         OP2_JAE_rel32       = 0x83,
134         OP2_JE_rel32        = 0x84,
135         OP2_JNE_rel32       = 0x85,
136         OP2_JBE_rel32       = 0x86,
137         OP2_JA_rel32        = 0x87,
138         OP2_JS_rel32        = 0x88,
139         OP2_JP_rel32        = 0x8A,
140         OP2_JL_rel32        = 0x8C,
141         OP2_JGE_rel32       = 0x8D,
142         OP2_JLE_rel32       = 0x8E,
143         OP2_JG_rel32        = 0x8F,
144         OP2_IMUL_GvEv       = 0xAF,
145         OP2_MOVZX_GvEb      = 0xB6,
146         OP2_MOVZX_GvEw      = 0xB7,
147         OP2_PEXTRW_GdUdIb   = 0xC5,
148
149         GROUP1_OP_ADD = 0,
150         GROUP1_OP_OR  = 1,
151         GROUP1_OP_AND = 4,
152         GROUP1_OP_SUB = 5,
153         GROUP1_OP_XOR = 6,
154         GROUP1_OP_CMP = 7,
155
156         GROUP1A_OP_POP = 0,
157
158         GROUP2_OP_SHL = 4,
159         GROUP2_OP_SAR = 7,
160
161         GROUP3_OP_TEST = 0,
162         GROUP3_OP_NEG  = 3,
163         GROUP3_OP_IDIV = 7,
164
165         GROUP5_OP_CALLN = 2,
166         GROUP5_OP_JMPN  = 4,
167         GROUP5_OP_PUSH  = 6,
168
169         GROUP11_MOV = 0,
170     } OpcodeID;
171     
172     // Opaque label types
173     
174     class JmpSrc {
175         friend class X86Assembler;
176     public:
177         JmpSrc()
178             : m_offset(-1)
179         {
180         }
181
182     private:
183         JmpSrc(int offset)
184             : m_offset(offset)
185         {
186         }
187
188         int m_offset;
189     };
190     
191     class JmpDst {
192         friend class X86Assembler;
193     public:
194         JmpDst()
195             : m_offset(-1)
196         {
197         }
198
199     private:
200         JmpDst(int offset)
201             : m_offset(offset)
202         {
203         }
204
205         int m_offset;
206     };
207
208     static const int maxInstructionSize = 16;
209
210     X86Assembler(AssemblerBuffer* m_buffer)
211         : m_buffer(m_buffer)
212     {
213         m_buffer->reset();
214     }
215
216     void int3()
217     {
218         m_buffer->putByte(OP_INT3);
219     }
220     
221 #if PLATFORM(X86_64)
222     void pushq_r(RegisterID reg)
223     {
224         m_buffer->putByte(OP_PUSH_EAX + reg);
225     }
226
227     void popq_r(RegisterID reg)
228     {
229         m_buffer->putByte(OP_POP_EAX + reg);
230     }
231 #else
232     void pushl_r(RegisterID reg)
233     {
234         m_buffer->putByte(OP_PUSH_EAX + reg);
235     }
236     
237     void pushl_m(int offset, RegisterID base)
238     {
239         m_buffer->putByte(OP_GROUP5_Ev);
240         modRm_opm(GROUP5_OP_PUSH, base, offset);
241     }
242
243     void pushl_i32(int imm)
244     {
245         m_buffer->putByte(OP_PUSH_Iz);
246         m_buffer->putInt(imm);
247     }
248     
249     void popl_r(RegisterID reg)
250     {
251         m_buffer->putByte(OP_POP_EAX + reg);
252     }
253
254     void popl_m(int offset, RegisterID base)
255     {
256         m_buffer->putByte(OP_GROUP1A_Ev);
257         modRm_opm(GROUP1A_OP_POP, base, offset);
258     }
259 #endif
260     
261     void movl_rr(RegisterID src, RegisterID dst)
262     {
263         m_buffer->putByte(OP_MOV_EvGv);
264         modRm_rr(src, dst);
265     }
266     
267 #if PLATFORM(X86_64)
268     void movq_rr(RegisterID src, RegisterID dst)
269     {
270         m_buffer->putByte(REX_W);
271         m_buffer->putByte(OP_MOV_EvGv);
272         modRm_rr(src, dst);
273     }
274 #endif
275
276     void addl_rr(RegisterID src, RegisterID dst)
277     {
278         m_buffer->putByte(OP_ADD_EvGv);
279         modRm_rr(src, dst);
280     }
281
282 #if !PLATFORM(X86_64)
283     void addl_i8m(int imm, void* addr)
284     {
285         m_buffer->putByte(OP_GROUP1_EvIb);
286         modRm_opm(GROUP1_OP_ADD, addr);
287         m_buffer->putByte(imm);
288     }
289 #endif
290
291     void addl_i8r(int imm, RegisterID dst)
292     {
293         m_buffer->putByte(OP_GROUP1_EvIb);
294         modRm_opr(GROUP1_OP_ADD, dst);
295         m_buffer->putByte(imm);
296     }
297
298     void addl_i32r(int imm, RegisterID dst)
299     {
300         m_buffer->putByte(OP_GROUP1_EvIz);
301         modRm_opr(GROUP1_OP_ADD, dst);
302         m_buffer->putInt(imm);
303     }
304
305 #if PLATFORM(X86_64)
306     void addq_i8r(int imm, RegisterID dst)
307     {
308         m_buffer->putByte(REX_W);
309         m_buffer->putByte(OP_GROUP1_EvIb);
310         modRm_opr(GROUP1_OP_ADD, dst);
311         m_buffer->putByte(imm);
312     }
313
314     void addq_i32r(int imm, RegisterID dst)
315     {
316         m_buffer->putByte(REX_W);
317         m_buffer->putByte(OP_GROUP1_EvIz);
318         modRm_opr(GROUP1_OP_ADD, dst);
319         m_buffer->putInt(imm);
320     }
321 #endif
322
323     void addl_mr(int offset, RegisterID base, RegisterID dst)
324     {
325         m_buffer->putByte(OP_ADD_GvEv);
326         modRm_rm(dst, base, offset);
327     }
328
329     void andl_rr(RegisterID src, RegisterID dst)
330     {
331         m_buffer->putByte(OP_AND_EvGv);
332         modRm_rr(src, dst);
333     }
334
335     void andl_i32r(int imm, RegisterID dst)
336     {
337         m_buffer->putByte(OP_GROUP1_EvIz);
338         modRm_opr(GROUP1_OP_AND, dst);
339         m_buffer->putInt(imm);
340     }
341
342     void cmpl_i8r(int imm, RegisterID dst)
343     {
344         m_buffer->putByte(OP_GROUP1_EvIb);
345         modRm_opr(GROUP1_OP_CMP, dst);
346         m_buffer->putByte(imm);
347     }
348
349     void cmpl_rr(RegisterID src, RegisterID dst)
350     {
351         m_buffer->putByte(OP_CMP_EvGv);
352         modRm_rr(src, dst);
353     }
354
355     void cmpl_rm(RegisterID src, int offset, RegisterID base)
356     {
357         m_buffer->putByte(OP_CMP_EvGv);
358         modRm_rm(src, base, offset);
359     }
360
361     void cmpl_mr(int offset, RegisterID base, RegisterID dst)
362     {
363         m_buffer->putByte(OP_CMP_GvEv);
364         modRm_rm(dst, base, offset);
365     }
366
367     void cmpl_i32r(int imm, RegisterID dst)
368     {
369         m_buffer->putByte(OP_GROUP1_EvIz);
370         modRm_opr(GROUP1_OP_CMP, dst);
371         m_buffer->putInt(imm);
372     }
373
374     void cmpl_i32m(int imm, RegisterID dst)
375     {
376         m_buffer->putByte(OP_GROUP1_EvIz);
377         modRm_opm(GROUP1_OP_CMP, dst);
378         m_buffer->putInt(imm);
379     }
380
381     void cmpl_i32m(int imm, int offset, RegisterID dst)
382     {
383         m_buffer->putByte(OP_GROUP1_EvIz);
384         modRm_opm(GROUP1_OP_CMP, dst, offset);
385         m_buffer->putInt(imm);
386     }
387
388 #if !PLATFORM(X86_64)
389     void cmpl_i32m(int imm, void* addr)
390     {
391         m_buffer->putByte(OP_GROUP1_EvIz);
392         modRm_opm(GROUP1_OP_CMP, addr);
393         m_buffer->putInt(imm);
394     }
395 #endif
396
397     void cmpl_i8m(int imm, int offset, RegisterID base, RegisterID index, int scale)
398     {
399         m_buffer->putByte(OP_GROUP1_EvIb);
400         modRm_opmsib(GROUP1_OP_CMP, base, index, scale, offset);
401         m_buffer->putByte(imm);
402     }
403
404     void cmpw_rm(RegisterID src, RegisterID base, RegisterID index, int scale)
405     {
406         m_buffer->putByte(PRE_OPERAND_SIZE);
407         m_buffer->putByte(OP_CMP_EvGv);
408         modRm_rmsib(src, base, index, scale);
409     }
410
411     void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
412     {
413         m_buffer->putByte(PRE_OPERAND_SIZE);
414         m_buffer->putByte(OP_CMP_EvGv);
415         modRm_rmsib(src, base, index, scale, offset);
416     }
417
418     void sete_r(RegisterID dst)
419     {
420         m_buffer->putByte(OP_2BYTE_ESCAPE);
421         m_buffer->putByte(OP_SETE);
422         m_buffer->putByte(MODRM(3, 0, dst));
423     }
424
425     void setz_r(RegisterID dst)
426     {
427         sete_r(dst);
428     }
429
430     void setne_r(RegisterID dst)
431     {
432         m_buffer->putByte(OP_2BYTE_ESCAPE);
433         m_buffer->putByte(OP_SETNE);
434         m_buffer->putByte(MODRM(3, 0, dst));
435     }
436
437     void setnz_r(RegisterID dst)
438     {
439         setne_r(dst);
440     }
441
442     void orl_rr(RegisterID src, RegisterID dst)
443     {
444         m_buffer->putByte(OP_OR_EvGv);
445         modRm_rr(src, dst);
446     }
447
448     void orl_mr(int offset, RegisterID base, RegisterID dst)
449     {
450         m_buffer->putByte(OP_OR_GvEv);
451         modRm_rm(dst, base, offset);
452     }
453
454     void orl_i32r(int imm, RegisterID dst)
455     {
456         m_buffer->putByte(OP_GROUP1_EvIb);
457         modRm_opr(GROUP1_OP_OR, dst);
458         m_buffer->putByte(imm);
459     }
460
461     void subl_rr(RegisterID src, RegisterID dst)
462     {
463         m_buffer->putByte(OP_SUB_EvGv);
464         modRm_rr(src, dst);
465     }
466
467     void subl_i8r(int imm, RegisterID dst)
468     {
469         m_buffer->putByte(OP_GROUP1_EvIb);
470         modRm_opr(GROUP1_OP_SUB, dst);
471         m_buffer->putByte(imm);
472     }
473     
474 #if !PLATFORM(X86_64)
475     void subl_i8m(int imm, void* addr)
476     {
477         m_buffer->putByte(OP_GROUP1_EvIb);
478         modRm_opm(GROUP1_OP_SUB, addr);
479         m_buffer->putByte(imm);
480     }
481 #endif
482
483     void subl_i32r(int imm, RegisterID dst)
484     {
485         m_buffer->putByte(OP_GROUP1_EvIz);
486         modRm_opr(GROUP1_OP_SUB, dst);
487         m_buffer->putInt(imm);
488     }
489
490     void subl_mr(int offset, RegisterID base, RegisterID dst)
491     {
492         m_buffer->putByte(OP_SUB_GvEv);
493         modRm_rm(dst, base, offset);
494     }
495
496     void testl_i32r(int imm, RegisterID dst)
497     {
498         m_buffer->ensureSpace(maxInstructionSize);
499         m_buffer->putByteUnchecked(OP_GROUP3_EvIz);
500         modRm_opr_Unchecked(GROUP3_OP_TEST, dst);
501         m_buffer->putIntUnchecked(imm);
502     }
503
504     void testl_i32m(int imm, RegisterID dst)
505     {
506         m_buffer->putByte(OP_GROUP3_EvIz);
507         modRm_opm(GROUP3_OP_TEST, dst);
508         m_buffer->putInt(imm);
509     }
510
511     void testl_i32m(int imm, int offset, RegisterID dst)
512     {
513         m_buffer->putByte(OP_GROUP3_EvIz);
514         modRm_opm(GROUP3_OP_TEST, dst, offset);
515         m_buffer->putInt(imm);
516     }
517
518     void testl_rr(RegisterID src, RegisterID dst)
519     {
520         m_buffer->putByte(OP_TEST_EvGv);
521         modRm_rr(src, dst);
522     }
523     
524     void xorl_i8r(int imm, RegisterID dst)
525     {
526         m_buffer->putByte(OP_GROUP1_EvIb);
527         modRm_opr(GROUP1_OP_XOR, dst);
528         m_buffer->putByte(imm);
529     }
530
531     void xorl_rr(RegisterID src, RegisterID dst)
532     {
533         m_buffer->putByte(OP_XOR_EvGv);
534         modRm_rr(src, dst);
535     }
536
537     void sarl_i8r(int imm, RegisterID dst)
538     {
539         if (imm == 1) {
540             m_buffer->putByte(OP_GROUP2_Ev1);
541             modRm_opr(GROUP2_OP_SAR, dst);
542         } else {
543             m_buffer->putByte(OP_GROUP2_EvIb);
544             modRm_opr(GROUP2_OP_SAR, dst);
545             m_buffer->putByte(imm);
546         }
547     }
548
549     void sarl_CLr(RegisterID dst)
550     {
551         m_buffer->putByte(OP_GROUP2_EvCL);
552         modRm_opr(GROUP2_OP_SAR, dst);
553     }
554
555     void shl_i8r(int imm, RegisterID dst)
556     {
557         if (imm == 1) {
558             m_buffer->putByte(OP_GROUP2_Ev1);
559             modRm_opr(GROUP2_OP_SHL, dst);
560         } else {
561             m_buffer->putByte(OP_GROUP2_EvIb);
562             modRm_opr(GROUP2_OP_SHL, dst);
563             m_buffer->putByte(imm);
564         }
565     }
566
567     void shll_CLr(RegisterID dst)
568     {
569         m_buffer->putByte(OP_GROUP2_EvCL);
570         modRm_opr(GROUP2_OP_SHL, dst);
571     }
572
573     void imull_rr(RegisterID src, RegisterID dst)
574     {
575         m_buffer->putByte(OP_2BYTE_ESCAPE);
576         m_buffer->putByte(OP2_IMUL_GvEv);
577         modRm_rr(dst, src);
578     }
579     
580     void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
581     {
582         m_buffer->putByte(OP_IMUL_GvEvIz);
583         modRm_rr(dst, src);
584         m_buffer->putInt(value);
585     }
586
587     void idivl_r(RegisterID dst)
588     {
589         m_buffer->putByte(OP_GROUP3_Ev);
590         modRm_opr(GROUP3_OP_IDIV, dst);
591     }
592
593     void negl_r(RegisterID dst)
594     {
595         m_buffer->putByte(OP_GROUP3_Ev);
596         modRm_opr(GROUP3_OP_NEG, dst);
597     }
598
599     void cdq()
600     {
601         m_buffer->putByte(OP_CDQ);
602     }
603
604     void movl_mr(RegisterID base, RegisterID dst)
605     {
606         m_buffer->putByte(OP_MOV_GvEv);
607         modRm_rm(dst, base);
608     }
609
610     void movl_mr(int offset, RegisterID base, RegisterID dst)
611     {
612         m_buffer->ensureSpace(maxInstructionSize);
613         m_buffer->putByteUnchecked(OP_MOV_GvEv);
614         modRm_rm_Unchecked(dst, base, offset);
615     }
616
617 #if PLATFORM(X86_64)
618     void movq_mr(RegisterID base, RegisterID dst)
619     {
620         m_buffer->putByte(REX_W);
621         m_buffer->putByte(OP_MOV_GvEv);
622         modRm_rm(dst, base);
623     }
624
625     void movq_mr(int offset, RegisterID base, RegisterID dst)
626     {
627         m_buffer->ensureSpace(maxInstructionSize);
628         m_buffer->putByteUnchecked(REX_W);
629         m_buffer->putByteUnchecked(OP_MOV_GvEv);
630         modRm_rm_Unchecked(dst, base, offset);
631     }
632 #endif
633
634 #if !PLATFORM(X86_64)
635     void movl_mr(void* addr, RegisterID dst)
636     {
637         m_buffer->putByte(OP_MOV_GvEv);
638         modRm_rm(dst, addr);
639     }
640 #endif
641
642     void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
643     {
644         m_buffer->putByte(OP_MOV_GvEv);
645         modRm_rmsib(dst, base, index, scale, offset);
646     }
647
648     void movzbl_rr(RegisterID src, RegisterID dst)
649     {
650         m_buffer->putByte(OP_2BYTE_ESCAPE);
651         m_buffer->putByte(OP2_MOVZX_GvEb);
652         modRm_rr(dst, src);
653     }
654
655     void movzwl_mr(int offset, RegisterID base, RegisterID dst)
656     {
657         m_buffer->putByte(OP_2BYTE_ESCAPE);
658         m_buffer->putByte(OP2_MOVZX_GvEw);
659         modRm_rm(dst, base, offset);
660     }
661
662     void movzwl_mr(RegisterID base, RegisterID index, int scale, RegisterID dst)
663     {
664         m_buffer->putByte(OP_2BYTE_ESCAPE);
665         m_buffer->putByte(OP2_MOVZX_GvEw);
666         modRm_rmsib(dst, base, index, scale);
667     }
668
669     void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
670     {
671         m_buffer->putByte(OP_2BYTE_ESCAPE);
672         m_buffer->putByte(OP2_MOVZX_GvEw);
673         modRm_rmsib(dst, base, index, scale, offset);
674     }
675
676     void movl_rm(RegisterID src, RegisterID base)
677     {
678         m_buffer->putByte(OP_MOV_EvGv);
679         modRm_rm(src, base);
680     }
681
682     void movl_rm(RegisterID src, int offset, RegisterID base)
683     {
684         m_buffer->ensureSpace(maxInstructionSize);
685         m_buffer->putByteUnchecked(OP_MOV_EvGv);
686         modRm_rm_Unchecked(src, base, offset);
687     }
688
689 #if PLATFORM(X86_64)
690     void movq_rm(RegisterID src, RegisterID base)
691     {
692         m_buffer->putByte(REX_W);
693         m_buffer->putByte(OP_MOV_EvGv);
694         modRm_rm(src, base);
695     }
696
697     void movq_rm(RegisterID src, int offset, RegisterID base)
698     {
699         m_buffer->ensureSpace(maxInstructionSize);
700         m_buffer->putByteUnchecked(REX_W);
701         m_buffer->putByteUnchecked(OP_MOV_EvGv);
702         modRm_rm_Unchecked(src, base, offset);
703     }
704 #endif
705
706     void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
707     {
708         m_buffer->putByte(OP_MOV_EvGv);
709         modRm_rmsib(src, base, index, scale, offset);
710     }
711     
712     void movl_i32r(int imm, RegisterID dst)
713     {
714         m_buffer->putByte(OP_GROUP11_EvIz);
715         modRm_opr(GROUP11_MOV, dst);
716         m_buffer->putInt(imm);
717     }
718
719     void movl_i32m(int imm, int offset, RegisterID base)
720     {
721         m_buffer->ensureSpace(maxInstructionSize);
722         m_buffer->putByteUnchecked(OP_GROUP11_EvIz);
723         modRm_opm_Unchecked(GROUP11_MOV, base, offset);
724         m_buffer->putIntUnchecked(imm);
725     }
726
727 #if !PLATFORM(X86_64)
728     void movl_i32m(int imm, void* addr)
729     {
730         m_buffer->putByte(OP_GROUP11_EvIz);
731         modRm_opm(GROUP11_MOV, addr);
732         m_buffer->putInt(imm);
733     }
734 #endif
735
736     void leal_mr(int offset, RegisterID base, RegisterID dst)
737     {
738         m_buffer->putByte(OP_LEA);
739         modRm_rm(dst, base, offset);
740     }
741
742     void leal_mr(int offset, RegisterID index, int scale, RegisterID dst)
743     {
744         m_buffer->putByte(OP_LEA);
745         modRm_rmsib(dst, X86::noBase, index, scale, offset);
746     }
747
748     void ret()
749     {
750         m_buffer->putByte(OP_RET);
751     }
752     
753     void jmp_r(RegisterID dst)
754     {
755         m_buffer->putByte(OP_GROUP5_Ev);
756         modRm_opr(GROUP5_OP_JMPN, dst);
757     }
758     
759     void jmp_m(int offset, RegisterID base)
760     {
761         m_buffer->putByte(OP_GROUP5_Ev);
762         modRm_opm(GROUP5_OP_JMPN, base, offset);
763     }
764     
765     void movsd_mr(int offset, RegisterID base, XMMRegisterID dst)
766     {
767         m_buffer->putByte(PRE_SSE_F2);
768         m_buffer->putByte(OP_2BYTE_ESCAPE);
769         m_buffer->putByte(OP2_MOVSD_VsdWsd);
770         modRm_rm((RegisterID)dst, base, offset);
771     }
772
773 #if !PLATFORM(X86_64)
774     void xorpd_mr(void* addr, XMMRegisterID dst)
775     {
776         m_buffer->putByte(PRE_SSE_66);
777         m_buffer->putByte(OP_2BYTE_ESCAPE);
778         m_buffer->putByte(OP2_XORPD_VsdWsd);
779         modRm_rm((RegisterID)dst, addr);
780     }
781 #endif
782
783     void movsd_rm(XMMRegisterID src, int offset, RegisterID base)
784     {
785         m_buffer->putByte(PRE_SSE_F2);
786         m_buffer->putByte(OP_2BYTE_ESCAPE);
787         m_buffer->putByte(OP2_MOVSD_WsdVsd);
788         modRm_rm((RegisterID)src, base, offset);
789     }
790
791     void movd_rr(XMMRegisterID src, RegisterID dst)
792     {
793         m_buffer->putByte(PRE_SSE_66);
794         m_buffer->putByte(OP_2BYTE_ESCAPE);
795         m_buffer->putByte(OP2_MOVD_EdVd);
796         modRm_rr((RegisterID)src, dst);
797     }
798
799     void cvtsi2sd_rr(RegisterID src, XMMRegisterID dst)
800     {
801         m_buffer->putByte(PRE_SSE_F2);
802         m_buffer->putByte(OP_2BYTE_ESCAPE);
803         m_buffer->putByte(OP2_CVTSI2SD_VsdEd);
804         modRm_rr((RegisterID)dst, src);
805     }
806
807     void cvttsd2si_rr(XMMRegisterID src, RegisterID dst)
808     {
809         m_buffer->putByte(PRE_SSE_F2);
810         m_buffer->putByte(OP_2BYTE_ESCAPE);
811         m_buffer->putByte(OP2_CVTTSD2SI_GdWsd);
812         modRm_rr(dst, (RegisterID)src);
813     }
814
815     void addsd_mr(int offset, RegisterID base, XMMRegisterID dst)
816     {
817         m_buffer->putByte(PRE_SSE_F2);
818         m_buffer->putByte(OP_2BYTE_ESCAPE);
819         m_buffer->putByte(OP2_ADDSD_VsdWsd);
820         modRm_rm((RegisterID)dst, base, offset);
821     }
822
823     void subsd_mr(int offset, RegisterID base, XMMRegisterID dst)
824     {
825         m_buffer->putByte(PRE_SSE_F2);
826         m_buffer->putByte(OP_2BYTE_ESCAPE);
827         m_buffer->putByte(OP2_SUBSD_VsdWsd);
828         modRm_rm((RegisterID)dst, base, offset);
829     }
830
831     void mulsd_mr(int offset, RegisterID base, XMMRegisterID dst)
832     {
833         m_buffer->putByte(PRE_SSE_F2);
834         m_buffer->putByte(OP_2BYTE_ESCAPE);
835         m_buffer->putByte(OP2_MULSD_VsdWsd);
836         modRm_rm((RegisterID)dst, base, offset);
837     }
838
839     void addsd_rr(XMMRegisterID src, XMMRegisterID dst)
840     {
841         m_buffer->putByte(PRE_SSE_F2);
842         m_buffer->putByte(OP_2BYTE_ESCAPE);
843         m_buffer->putByte(OP2_ADDSD_VsdWsd);
844         modRm_rr((RegisterID)dst, (RegisterID)src);
845     }
846
847     void subsd_rr(XMMRegisterID src, XMMRegisterID dst)
848     {
849         m_buffer->putByte(PRE_SSE_F2);
850         m_buffer->putByte(OP_2BYTE_ESCAPE);
851         m_buffer->putByte(OP2_SUBSD_VsdWsd);
852         modRm_rr((RegisterID)dst, (RegisterID)src);
853     }
854
855     void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)
856     {
857         m_buffer->putByte(PRE_SSE_F2);
858         m_buffer->putByte(OP_2BYTE_ESCAPE);
859         m_buffer->putByte(OP2_MULSD_VsdWsd);
860         modRm_rr((RegisterID)dst, (RegisterID)src);
861     }
862
863     void ucomis_rr(XMMRegisterID src, XMMRegisterID dst)
864     {
865         m_buffer->putByte(PRE_SSE_66);
866         m_buffer->putByte(OP_2BYTE_ESCAPE);
867         m_buffer->putByte(OP2_UCOMISD_VsdWsd);
868         modRm_rr((RegisterID)dst, (RegisterID)src);
869     }
870
871     void pextrw_irr(int whichWord, XMMRegisterID src, RegisterID dst)
872     {
873         m_buffer->putByte(PRE_SSE_66);
874         m_buffer->putByte(OP_2BYTE_ESCAPE);
875         m_buffer->putByte(OP2_PEXTRW_GdUdIb);
876         modRm_rr(dst, (RegisterID)src);
877         m_buffer->putByte(whichWord);
878     }
879
880     JmpSrc call()
881     {
882         m_buffer->putByte(OP_CALL_rel32);
883         m_buffer->putInt(0); // FIXME: make this point to a global label, linked later.
884         return JmpSrc(m_buffer->size());
885     }
886     
887     JmpSrc call(RegisterID dst)
888     {
889         m_buffer->putByte(OP_GROUP5_Ev);
890         modRm_opr(GROUP5_OP_CALLN, dst);
891         return JmpSrc(m_buffer->size());
892     }
893
894     JmpDst label()
895     {
896         return JmpDst(m_buffer->size());
897     }
898     
899     JmpDst align(int alignment)
900     {
901         while (!m_buffer->isAligned(alignment))
902             m_buffer->putByte(OP_HLT);
903
904         return label();
905     }
906
907     JmpSrc jmp()
908     {
909         m_buffer->putByte(OP_JMP_rel32);
910         m_buffer->putInt(0);
911         return JmpSrc(m_buffer->size());
912     }
913     
914     JmpSrc jne()
915     {
916         m_buffer->putByte(OP_2BYTE_ESCAPE);
917         m_buffer->putByte(OP2_JNE_rel32);
918         m_buffer->putInt(0);
919         return JmpSrc(m_buffer->size());
920     }
921     
922     JmpSrc jnz()
923     {
924         return jne();
925     }
926
927     JmpSrc je()
928     {
929         m_buffer->ensureSpace(maxInstructionSize);
930         m_buffer->putByteUnchecked(OP_2BYTE_ESCAPE);
931         m_buffer->putByteUnchecked(OP2_JE_rel32);
932         m_buffer->putIntUnchecked(0);
933         return JmpSrc(m_buffer->size());
934     }
935     
936     JmpSrc jl()
937     {
938         m_buffer->putByte(OP_2BYTE_ESCAPE);
939         m_buffer->putByte(OP2_JL_rel32);
940         m_buffer->putInt(0);
941         return JmpSrc(m_buffer->size());
942     }
943     
944     JmpSrc jb()
945     {
946         m_buffer->putByte(OP_2BYTE_ESCAPE);
947         m_buffer->putByte(OP2_JB_rel32);
948         m_buffer->putInt(0);
949         return JmpSrc(m_buffer->size());
950     }
951     
952     JmpSrc jle()
953     {
954         m_buffer->putByte(OP_2BYTE_ESCAPE);
955         m_buffer->putByte(OP2_JLE_rel32);
956         m_buffer->putInt(0);
957         return JmpSrc(m_buffer->size());
958     }
959     
960     JmpSrc jbe()
961     {
962         m_buffer->putByte(OP_2BYTE_ESCAPE);
963         m_buffer->putByte(OP2_JBE_rel32);
964         m_buffer->putInt(0);
965         return JmpSrc(m_buffer->size());
966     }
967     
968     JmpSrc jge()
969     {
970         m_buffer->putByte(OP_2BYTE_ESCAPE);
971         m_buffer->putByte(OP2_JGE_rel32);
972         m_buffer->putInt(0);
973         return JmpSrc(m_buffer->size());
974     }
975
976     JmpSrc jg()
977     {
978         m_buffer->putByte(OP_2BYTE_ESCAPE);
979         m_buffer->putByte(OP2_JG_rel32);
980         m_buffer->putInt(0);
981         return JmpSrc(m_buffer->size());
982     }
983
984     JmpSrc ja()
985     {
986         m_buffer->putByte(OP_2BYTE_ESCAPE);
987         m_buffer->putByte(OP2_JA_rel32);
988         m_buffer->putInt(0);
989         return JmpSrc(m_buffer->size());
990     }
991     
992     JmpSrc jae()
993     {
994         m_buffer->putByte(OP_2BYTE_ESCAPE);
995         m_buffer->putByte(OP2_JAE_rel32);
996         m_buffer->putInt(0);
997         return JmpSrc(m_buffer->size());
998     }
999     
1000     JmpSrc jo()
1001     {
1002         m_buffer->putByte(OP_2BYTE_ESCAPE);
1003         m_buffer->putByte(OP2_JO_rel32);
1004         m_buffer->putInt(0);
1005         return JmpSrc(m_buffer->size());
1006     }
1007
1008     JmpSrc jp()
1009     {
1010         m_buffer->putByte(OP_2BYTE_ESCAPE);
1011         m_buffer->putByte(OP2_JP_rel32);
1012         m_buffer->putInt(0);
1013         return JmpSrc(m_buffer->size());
1014     }
1015     
1016     JmpSrc js()
1017     {
1018         m_buffer->putByte(OP_2BYTE_ESCAPE);
1019         m_buffer->putByte(OP2_JS_rel32);
1020         m_buffer->putInt(0);
1021         return JmpSrc(m_buffer->size());
1022     }
1023     
1024     void predictNotTaken()
1025     {
1026         m_buffer->putByte(PRE_PREDICT_BRANCH_NOT_TAKEN);
1027     }
1028     
1029     void link(JmpSrc from, JmpDst to)
1030     {
1031         ASSERT(to.m_offset != -1);
1032         ASSERT(from.m_offset != -1);
1033         
1034         reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(m_buffer->data()) + from.m_offset)[-1] = to.m_offset - from.m_offset;
1035     }
1036     
1037     static void linkAbsoluteAddress(void* code, JmpDst useOffset, JmpDst address)
1038     {
1039         ASSERT(useOffset.m_offset != -1);
1040         ASSERT(address.m_offset != -1);
1041         
1042         reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(code) + useOffset.m_offset)[-1] = reinterpret_cast<ptrdiff_t>(code) + address.m_offset;
1043     }
1044     
1045     static void link(void* code, JmpSrc from, void* to)
1046     {
1047         ASSERT(from.m_offset != -1);
1048         
1049         reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(code) + from.m_offset)[-1] = reinterpret_cast<ptrdiff_t>(to) - (reinterpret_cast<ptrdiff_t>(code) + from.m_offset);
1050     }
1051     
1052     static void* getRelocatedAddress(void* code, JmpSrc jump)
1053     {
1054         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
1055     }
1056     
1057     static void* getRelocatedAddress(void* code, JmpDst jump)
1058     {
1059         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
1060     }
1061     
1062     static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
1063     {
1064         return dst.m_offset - src.m_offset;
1065     }
1066     
1067     static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
1068     {
1069         return dst.m_offset - src.m_offset;
1070     }
1071     
1072     static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
1073     {
1074         return dst.m_offset - src.m_offset;
1075     }
1076     
1077     static void repatchImmediate(intptr_t where, int32_t value)
1078     {
1079         reinterpret_cast<int32_t*>(where)[-1] = value;
1080     }
1081     
1082     static void repatchDisplacement(intptr_t where, intptr_t value)
1083     {
1084         reinterpret_cast<intptr_t*>(where)[-1] = value;
1085     }
1086     
1087     static void repatchBranchOffset(intptr_t where, void* destination)
1088     {
1089         reinterpret_cast<intptr_t*>(where)[-1] = (reinterpret_cast<intptr_t>(destination) - where);
1090     }
1091     
1092     void* executableCopy()
1093     {
1094         void* copy = m_buffer->executableCopy();
1095         ASSERT(copy);
1096         return copy;
1097     }
1098
1099 #if USE(CTI_ARGUMENT)
1100     void restoreArgumentReference()
1101     {
1102 #if USE(FAST_CALL_CTI_ARGUMENT)
1103         movl_rr(X86::esp, X86::ecx);
1104 #else
1105         movl_rm(X86::esp, 0, X86::esp);
1106 #endif
1107     }
1108
1109     void restoreArgumentReferenceForTrampoline()
1110     {
1111 #if USE(FAST_CALL_CTI_ARGUMENT)
1112         movl_rr(X86::esp, X86::ecx);
1113         addl_i32r(4, X86::ecx);
1114 #endif
1115     }
1116 #else
1117     void restoreArgumentReference() {}
1118     void restoreArgumentReferenceForTrampoline() {}
1119 #endif
1120
1121 private:
1122     void modRm_rr(RegisterID reg, RegisterID rm)
1123     {
1124         m_buffer->ensureSpace(maxInstructionSize);
1125         modRm_rr_Unchecked(reg, rm);
1126     }
1127
1128     void modRm_rr_Unchecked(RegisterID reg, RegisterID rm)
1129     {
1130         m_buffer->putByteUnchecked(MODRM(3, reg, rm));
1131     }
1132
1133 #if !PLATFORM(X86_64)
1134     void modRm_rm(RegisterID reg, void* addr)
1135     {
1136         m_buffer->putByte(MODRM(0, reg, X86::noBase));
1137         m_buffer->putInt((int)addr);
1138     }
1139 #endif
1140
1141     void modRm_rm(RegisterID reg, RegisterID base)
1142     {
1143         if (base == X86::esp) {
1144             m_buffer->putByte(MODRM(0, reg, X86::hasSib));
1145             m_buffer->putByte(SIB(0, X86::noScale, X86::esp));
1146         } else
1147             m_buffer->putByte(MODRM(0, reg, base));
1148     }
1149
1150     void modRm_rm_Unchecked(RegisterID reg, RegisterID base, int offset)
1151     {
1152         if (base == X86::esp) {
1153             if (CAN_SIGN_EXTEND_8_32(offset)) {
1154                 m_buffer->putByteUnchecked(MODRM(1, reg, X86::hasSib));
1155                 m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp));
1156                 m_buffer->putByteUnchecked(offset);
1157             } else {
1158                 m_buffer->putByteUnchecked(MODRM(2, reg, X86::hasSib));
1159                 m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp));
1160                 m_buffer->putIntUnchecked(offset);
1161             }
1162         } else {
1163             if (CAN_SIGN_EXTEND_8_32(offset)) {
1164                 m_buffer->putByteUnchecked(MODRM(1, reg, base));
1165                 m_buffer->putByteUnchecked(offset);
1166             } else {
1167                 m_buffer->putByteUnchecked(MODRM(2, reg, base));
1168                 m_buffer->putIntUnchecked(offset);
1169             }
1170         }
1171     }
1172
1173     void modRm_rm(RegisterID reg, RegisterID base, int offset)
1174     {
1175         m_buffer->ensureSpace(maxInstructionSize);
1176         modRm_rm_Unchecked(reg, base, offset);
1177     }
1178
1179     void modRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale)
1180     {
1181         int shift = 0;
1182         while (scale >>= 1)
1183             shift++;
1184     
1185         m_buffer->putByte(MODRM(0, reg, X86::hasSib));
1186         m_buffer->putByte(SIB(shift, index, base));
1187     }
1188
1189     void modRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale, int offset)
1190     {
1191         int shift = 0;
1192         while (scale >>= 1)
1193             shift++;
1194     
1195         if (CAN_SIGN_EXTEND_8_32(offset)) {
1196             m_buffer->putByte(MODRM(1, reg, X86::hasSib));
1197             m_buffer->putByte(SIB(shift, index, base));
1198             m_buffer->putByte(offset);
1199         } else {
1200             m_buffer->putByte(MODRM(2, reg, X86::hasSib));
1201             m_buffer->putByte(SIB(shift, index, base));
1202             m_buffer->putInt(offset);
1203         }
1204     }
1205
1206     void modRm_opr(OpcodeID opcodeID, RegisterID rm)
1207     {
1208         m_buffer->ensureSpace(maxInstructionSize);
1209         modRm_opr_Unchecked(opcodeID, rm);
1210     }
1211
1212     void modRm_opr_Unchecked(OpcodeID opcodeID, RegisterID rm)
1213     {
1214         modRm_rr_Unchecked(static_cast<RegisterID>(opcodeID), rm);
1215     }
1216
1217     void modRm_opm(OpcodeID opcodeID, RegisterID base)
1218     {
1219         modRm_rm(static_cast<RegisterID>(opcodeID), base);
1220     }
1221
1222     void modRm_opm_Unchecked(OpcodeID opcodeID, RegisterID base, int offset)
1223     {
1224         modRm_rm_Unchecked(static_cast<RegisterID>(opcodeID), base, offset);
1225     }
1226
1227     void modRm_opm(OpcodeID opcodeID, RegisterID base, int offset)
1228     {
1229         modRm_rm(static_cast<RegisterID>(opcodeID), base, offset);
1230     }
1231
1232 #if !PLATFORM(X86_64)
1233     void modRm_opm(OpcodeID opcodeID, void* addr)
1234     {
1235         modRm_rm(static_cast<RegisterID>(opcodeID), addr);
1236     }
1237 #endif
1238
1239     void modRm_opmsib(OpcodeID opcodeID, RegisterID base, RegisterID index, int scale, int offset)
1240     {
1241         modRm_rmsib(static_cast<RegisterID>(opcodeID), base, index, scale, offset);
1242     }
1243
1244     AssemblerBuffer* m_buffer;
1245 };
1246
1247 } // namespace JSC
1248
1249 #endif // ENABLE(ASSEMBLER) && PLATFORM(X86)
1250
1251 #endif // X86Assembler_h