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