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