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