bda055cdf0442d47bb202899e9b86ccaa9105b3d
[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 #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         *(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
167 class X86Assembler {
168 public:
169     typedef X86::RegisterID RegisterID;
170
171     typedef enum {
172         OP_ADD_EvGv                     = 0x01,
173         OP_ADD_GvEv                     = 0x03,
174         OP_OR_EvGv                      = 0x09,
175         OP_2BYTE_ESCAPE                 = 0x0F,
176         OP_AND_EvGv                     = 0x21,
177         OP_SUB_EvGv                     = 0x29,
178         OP_SUB_GvEv                     = 0x2B,
179         PRE_PREDICT_BRANCH_NOT_TAKEN    = 0x2E,
180         OP_XOR_EvGv                     = 0x31,
181         OP_CMP_EvGv                     = 0x39,
182         OP_PUSH_EAX                     = 0x50,
183         OP_POP_EAX                      = 0x58,
184         PRE_OPERAND_SIZE                = 0x66,
185         OP_IMUL_GvEvIz                  = 0x69,
186         OP_GROUP1_EvIz                  = 0x81,
187         OP_GROUP1_EvIb                  = 0x83,
188         OP_TEST_EvGv                    = 0x85,
189         OP_MOV_EvGv                     = 0x89,
190         OP_MOV_GvEv                     = 0x8B,
191         OP_LEA                          = 0x8D,
192         OP_GROUP1A_Ev                   = 0x8F,
193         OP_CDQ                          = 0x99,
194         OP_GROUP2_EvIb                  = 0xC1,
195         OP_RET                          = 0xC3,
196         OP_GROUP11_EvIz                 = 0xC7,
197         OP_INT3                         = 0xCC,
198         OP_GROUP2_Ev1                   = 0xD1,
199         OP_GROUP2_EvCL                  = 0xD3,
200         OP_CALL_rel32                   = 0xE8,
201         OP_JMP_rel32                    = 0xE9,
202         OP_GROUP3_Ev                    = 0xF7,
203         OP_GROUP3_EvIz                  = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test. 
204         OP_GROUP5_Ev                    = 0xFF,
205
206         OP2_JO_rel32    = 0x80,
207         OP2_JB_rel32    = 0x82,
208         OP2_JAE_rel32   = 0x83,
209         OP2_JE_rel32    = 0x84,
210         OP2_JNE_rel32   = 0x85,
211         OP2_JBE_rel32   = 0x86,
212         OP2_JL_rel32    = 0x8C,
213         OP2_JGE_rel32   = 0x8D,
214         OP2_JLE_rel32   = 0x8E,
215         OP2_IMUL_GvEv   = 0xAF,
216         OP2_MOVZX_GvEw  = 0xB7,
217
218         GROUP1_OP_ADD = 0,
219         GROUP1_OP_OR  = 1,
220         GROUP1_OP_AND = 4,
221         GROUP1_OP_SUB = 5,
222         GROUP1_OP_XOR = 6,
223         GROUP1_OP_CMP = 7,
224
225         GROUP1A_OP_POP = 0,
226
227         GROUP2_OP_SHL = 4,
228         GROUP2_OP_SAR = 7,
229
230         GROUP3_OP_TEST = 0,
231         GROUP3_OP_IDIV = 7,
232
233         GROUP5_OP_CALLN = 2,
234         GROUP5_OP_JMPN  = 4,
235         GROUP5_OP_PUSH  = 6,
236
237         GROUP11_MOV = 0,
238     } OpcodeID;
239     
240     static const int MAX_INSTRUCTION_SIZE = 16;
241
242     X86Assembler(JITCodeBuffer* m_buffer)
243         : m_buffer(m_buffer)
244     {
245         m_buffer->reset();
246     }
247
248     void emitInt3()
249     {
250         m_buffer->putByte(OP_INT3);
251     }
252     
253     void pushl_r(RegisterID reg)
254     {
255         m_buffer->putByte(OP_PUSH_EAX + reg);
256     }
257     
258     void pushl_m(int offset, RegisterID base)
259     {
260         m_buffer->putByte(OP_GROUP5_Ev);
261         emitModRm_opm(GROUP5_OP_PUSH, base, offset);
262     }
263     
264     void popl_r(RegisterID reg)
265     {
266         m_buffer->putByte(OP_POP_EAX + reg);
267     }
268
269     void popl_m(int offset, RegisterID base)
270     {
271         m_buffer->putByte(OP_GROUP1A_Ev);
272         emitModRm_opm(GROUP1A_OP_POP, base, offset);
273     }
274     
275     void movl_rr(RegisterID src, RegisterID dst)
276     {
277         m_buffer->putByte(OP_MOV_EvGv);
278         emitModRm_rr(src, dst);
279     }
280     
281     void addl_rr(RegisterID src, RegisterID dst)
282     {
283         m_buffer->putByte(OP_ADD_EvGv);
284         emitModRm_rr(src, dst);
285     }
286
287     void addl_i8r(int imm, RegisterID dst)
288     {
289         m_buffer->putByte(OP_GROUP1_EvIb);
290         emitModRm_opr(GROUP1_OP_ADD, dst);
291         m_buffer->putByte(imm);
292     }
293
294     void addl_i32r(int imm, RegisterID dst)
295     {
296         m_buffer->putByte(OP_GROUP1_EvIz);
297         emitModRm_opr(GROUP1_OP_ADD, dst);
298         m_buffer->putInt(imm);
299     }
300
301     void addl_mr(int offset, RegisterID base, RegisterID dst)
302     {
303         m_buffer->putByte(OP_ADD_GvEv);
304         emitModRm_rm(dst, base, offset);
305     }
306
307     void andl_rr(RegisterID src, RegisterID dst)
308     {
309         m_buffer->putByte(OP_AND_EvGv);
310         emitModRm_rr(src, dst);
311     }
312
313     void andl_i32r(int imm, RegisterID dst)
314     {
315         m_buffer->putByte(OP_GROUP1_EvIz);
316         emitModRm_opr(GROUP1_OP_AND, dst);
317         m_buffer->putInt(imm);
318     }
319
320     void cmpl_i8r(int imm, RegisterID dst)
321     {
322         m_buffer->putByte(OP_GROUP1_EvIb);
323         emitModRm_opr(GROUP1_OP_CMP, dst);
324         m_buffer->putByte(imm);
325     }
326
327     void cmpl_rr(RegisterID src, RegisterID dst)
328     {
329         m_buffer->putByte(OP_CMP_EvGv);
330         emitModRm_rr(src, dst);
331     }
332
333     void cmpl_rm(RegisterID src, int offset, RegisterID base)
334     {
335         m_buffer->putByte(OP_CMP_EvGv);
336         emitModRm_rm(src, base, offset);
337     }
338
339     void cmpl_i32r(int imm, RegisterID dst)
340     {
341         m_buffer->putByte(OP_GROUP1_EvIz);
342         emitModRm_opr(GROUP1_OP_CMP, dst);
343         m_buffer->putInt(imm);
344     }
345
346     void cmpl_i32m(int imm, RegisterID dst)
347     {
348         m_buffer->putByte(OP_GROUP1_EvIz);
349         emitModRm_opm(GROUP1_OP_CMP, dst);
350         m_buffer->putInt(imm);
351     }
352
353     void cmpl_i32m(int imm, int offset, RegisterID dst)
354     {
355         m_buffer->putByte(OP_GROUP1_EvIz);
356         emitModRm_opm(GROUP1_OP_CMP, dst, offset);
357         m_buffer->putInt(imm);
358     }
359
360     void cmpl_i32m(int imm, void* addr)
361     {
362         m_buffer->putByte(OP_GROUP1_EvIz);
363         emitModRm_opm(GROUP1_OP_CMP, addr);
364         m_buffer->putInt(imm);
365     }
366
367     void cmpw_rm(RegisterID src, RegisterID base, RegisterID index, int scale)
368     {
369         m_buffer->putByte(PRE_OPERAND_SIZE);
370         m_buffer->putByte(OP_CMP_EvGv);
371         emitModRm_rmsib(src, base, index, scale);
372     }
373
374     void orl_rr(RegisterID src, RegisterID dst)
375     {
376         m_buffer->putByte(OP_OR_EvGv);
377         emitModRm_rr(src, dst);
378     }
379
380     void orl_i32r(int imm, RegisterID dst)
381     {
382         m_buffer->putByte(OP_GROUP1_EvIb);
383         emitModRm_opr(GROUP1_OP_OR, dst);
384         m_buffer->putByte(imm);
385     }
386
387     void subl_rr(RegisterID src, RegisterID dst)
388     {
389         m_buffer->putByte(OP_SUB_EvGv);
390         emitModRm_rr(src, dst);
391     }
392
393     void subl_i8r(int imm, RegisterID dst)
394     {
395         m_buffer->putByte(OP_GROUP1_EvIb);
396         emitModRm_opr(GROUP1_OP_SUB, dst);
397         m_buffer->putByte(imm);
398     }
399
400     void subl_i32r(int imm, RegisterID dst)
401     {
402         m_buffer->putByte(OP_GROUP1_EvIz);
403         emitModRm_opr(GROUP1_OP_SUB, dst);
404         m_buffer->putInt(imm);
405     }
406
407     void subl_mr(int offset, RegisterID base, RegisterID dst)
408     {
409         m_buffer->putByte(OP_SUB_GvEv);
410         emitModRm_rm(dst, base, offset);
411     }
412
413     void testl_i32r(int imm, RegisterID dst)
414     {
415         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
416         m_buffer->putByteUnchecked(OP_GROUP3_EvIz);
417         emitModRm_opr_Unchecked(GROUP3_OP_TEST, dst);
418         m_buffer->putIntUnchecked(imm);
419     }
420
421     void testl_rr(RegisterID src, RegisterID dst)
422     {
423         m_buffer->putByte(OP_TEST_EvGv);
424         emitModRm_rr(src, dst);
425     }
426     
427     void xorl_i8r(int imm, RegisterID dst)
428     {
429         m_buffer->putByte(OP_GROUP1_EvIb);
430         emitModRm_opr(GROUP1_OP_XOR, dst);
431         m_buffer->putByte(imm);
432     }
433
434     void xorl_rr(RegisterID src, RegisterID dst)
435     {
436         m_buffer->putByte(OP_XOR_EvGv);
437         emitModRm_rr(src, dst);
438     }
439
440     void sarl_i8r(int imm, RegisterID dst)
441     {
442         if (imm == 1) {
443             m_buffer->putByte(OP_GROUP2_Ev1);
444             emitModRm_opr(GROUP2_OP_SAR, dst);
445         } else {
446             m_buffer->putByte(OP_GROUP2_EvIb);
447             emitModRm_opr(GROUP2_OP_SAR, dst);
448             m_buffer->putByte(imm);
449         }
450     }
451
452     void sarl_CLr(RegisterID dst)
453     {
454         m_buffer->putByte(OP_GROUP2_EvCL);
455         emitModRm_opr(GROUP2_OP_SAR, dst);
456     }
457
458     void shl_i8r(int imm, RegisterID dst)
459     {
460         if (imm == 1) {
461             m_buffer->putByte(OP_GROUP2_Ev1);
462             emitModRm_opr(GROUP2_OP_SHL, dst);
463         } else {
464             m_buffer->putByte(OP_GROUP2_EvIb);
465             emitModRm_opr(GROUP2_OP_SHL, dst);
466             m_buffer->putByte(imm);
467         }
468     }
469
470     void shll_CLr(RegisterID dst)
471     {
472         m_buffer->putByte(OP_GROUP2_EvCL);
473         emitModRm_opr(GROUP2_OP_SHL, dst);
474     }
475
476     void imull_rr(RegisterID src, RegisterID dst)
477     {
478         m_buffer->putByte(OP_2BYTE_ESCAPE);
479         m_buffer->putByte(OP2_IMUL_GvEv);
480         emitModRm_rr(dst, src);
481     }
482     
483     void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
484     {
485         m_buffer->putByte(OP_IMUL_GvEvIz);
486         emitModRm_rr(dst, src);
487         m_buffer->putInt(value);
488     }
489
490     void idivl_r(RegisterID dst)
491     {
492         m_buffer->putByte(OP_GROUP3_Ev);
493         emitModRm_opr(GROUP3_OP_IDIV, dst);
494     }
495
496     void cdq()
497     {
498         m_buffer->putByte(OP_CDQ);
499     }
500
501     void movl_mr(RegisterID base, RegisterID dst)
502     {
503         m_buffer->putByte(OP_MOV_GvEv);
504         emitModRm_rm(dst, base);
505     }
506
507     void movl_mr(int offset, RegisterID base, RegisterID dst)
508     {
509         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
510         m_buffer->putByteUnchecked(OP_MOV_GvEv);
511         emitModRm_rm_Unchecked(dst, base, offset);
512     }
513
514     void movl_mr(void* addr, RegisterID dst)
515     {
516         m_buffer->putByte(OP_MOV_GvEv);
517         emitModRm_rm(dst, addr);
518     }
519
520     void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
521     {
522         m_buffer->putByte(OP_MOV_GvEv);
523         emitModRm_rmsib(dst, base, index, scale, offset);
524     }
525
526     void movzwl_mr(int offset, RegisterID base, RegisterID dst)
527     {
528         m_buffer->putByte(OP_2BYTE_ESCAPE);
529         m_buffer->putByte(OP2_MOVZX_GvEw);
530         emitModRm_rm(dst, base, offset);
531     }
532
533     void movzwl_mr(RegisterID base, RegisterID index, int scale, RegisterID dst)
534     {
535         m_buffer->putByte(OP_2BYTE_ESCAPE);
536         m_buffer->putByte(OP2_MOVZX_GvEw);
537         emitModRm_rmsib(dst, base, index, scale);
538     }
539
540     void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
541     {
542         m_buffer->putByte(OP_2BYTE_ESCAPE);
543         m_buffer->putByte(OP2_MOVZX_GvEw);
544         emitModRm_rmsib(dst, base, index, scale, offset);
545     }
546
547     void movl_rm(RegisterID src, RegisterID base)
548     {
549         m_buffer->putByte(OP_MOV_EvGv);
550         emitModRm_rm(src, base);
551     }
552
553     void movl_rm(RegisterID src, int offset, RegisterID base)
554     {
555         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
556         m_buffer->putByteUnchecked(OP_MOV_EvGv);
557         emitModRm_rm_Unchecked(src, base, offset);
558     }
559     
560     void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
561     {
562         m_buffer->putByte(OP_MOV_EvGv);
563         emitModRm_rmsib(src, base, index, scale, offset);
564     }
565     
566     void movl_i32r(int imm, RegisterID dst)
567     {
568         m_buffer->putByte(OP_GROUP11_EvIz);
569         emitModRm_opr(GROUP11_MOV, dst);
570         m_buffer->putInt(imm);
571     }
572
573     void movl_i32m(int imm, int offset, RegisterID base)
574     {
575         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
576         m_buffer->putByteUnchecked(OP_GROUP11_EvIz);
577         emitModRm_opm_Unchecked(GROUP11_MOV, base, offset);
578         m_buffer->putIntUnchecked(imm);
579     }
580
581     void movl_i32m(int imm, void* addr)
582     {
583         m_buffer->putByte(OP_GROUP11_EvIz);
584         emitModRm_opm(GROUP11_MOV, addr);
585         m_buffer->putInt(imm);
586     }
587
588     void leal_mr(int offset, RegisterID base, RegisterID dst)
589     {
590         m_buffer->putByte(OP_LEA);
591         emitModRm_rm(dst, base, offset);
592     }
593
594     void ret()
595     {
596         m_buffer->putByte(OP_RET);
597     }
598     
599     void jmp_r(RegisterID dst)
600     {
601         m_buffer->putByte(OP_GROUP5_Ev);
602         emitModRm_opr(GROUP5_OP_JMPN, dst);
603     }
604     
605     void jmp_m(int offset, RegisterID base)
606     {
607         m_buffer->putByte(OP_GROUP5_Ev);
608         emitModRm_opm(GROUP5_OP_JMPN, base, offset);
609     }
610     
611     void call_r(RegisterID dst)
612     {
613         m_buffer->putByte(OP_GROUP5_Ev);
614         emitModRm_opr(GROUP5_OP_CALLN, dst);
615     }
616
617     // Opaque label types
618     
619     class JmpSrc {
620         friend class X86Assembler;
621     public:
622         JmpSrc()
623             : m_offset(-1)
624         {
625         }
626
627     private:
628         JmpSrc(int offset)
629             : m_offset(offset)
630         {
631         }
632
633         int m_offset;
634     };
635     
636     class JmpDst {
637         friend class X86Assembler;
638     public:
639         JmpDst()
640             : m_offset(-1)
641         {
642         }
643
644     private:
645         JmpDst(int offset)
646             : m_offset(offset)
647         {
648         }
649
650         int m_offset;
651     };
652
653     // FIXME: make this point to a global label, linked later.
654     JmpSrc emitCall()
655     {
656         m_buffer->putByte(OP_CALL_rel32);
657         m_buffer->putInt(0);
658         return JmpSrc(m_buffer->getOffset());
659     }
660     
661     JmpDst label()
662     {
663         return JmpDst(m_buffer->getOffset());
664     }
665     
666     JmpSrc emitUnlinkedJmp()
667     {
668         m_buffer->putByte(OP_JMP_rel32);
669         m_buffer->putInt(0);
670         return JmpSrc(m_buffer->getOffset());
671     }
672     
673     JmpSrc emitUnlinkedJne()
674     {
675         m_buffer->putByte(OP_2BYTE_ESCAPE);
676         m_buffer->putByte(OP2_JNE_rel32);
677         m_buffer->putInt(0);
678         return JmpSrc(m_buffer->getOffset());
679     }
680     
681     JmpSrc emitUnlinkedJe()
682     {
683         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
684         m_buffer->putByteUnchecked(OP_2BYTE_ESCAPE);
685         m_buffer->putByteUnchecked(OP2_JE_rel32);
686         m_buffer->putIntUnchecked(0);
687         return JmpSrc(m_buffer->getOffset());
688     }
689     
690     JmpSrc emitUnlinkedJl()
691     {
692         m_buffer->putByte(OP_2BYTE_ESCAPE);
693         m_buffer->putByte(OP2_JL_rel32);
694         m_buffer->putInt(0);
695         return JmpSrc(m_buffer->getOffset());
696     }
697     
698     JmpSrc emitUnlinkedJb()
699     {
700         m_buffer->putByte(OP_2BYTE_ESCAPE);
701         m_buffer->putByte(OP2_JB_rel32);
702         m_buffer->putInt(0);
703         return JmpSrc(m_buffer->getOffset());
704     }
705     
706     JmpSrc emitUnlinkedJle()
707     {
708         m_buffer->putByte(OP_2BYTE_ESCAPE);
709         m_buffer->putByte(OP2_JLE_rel32);
710         m_buffer->putInt(0);
711         return JmpSrc(m_buffer->getOffset());
712     }
713     
714     JmpSrc emitUnlinkedJbe()
715     {
716         m_buffer->putByte(OP_2BYTE_ESCAPE);
717         m_buffer->putByte(OP2_JBE_rel32);
718         m_buffer->putInt(0);
719         return JmpSrc(m_buffer->getOffset());
720     }
721     
722     JmpSrc emitUnlinkedJge()
723     {
724         m_buffer->putByte(OP_2BYTE_ESCAPE);
725         m_buffer->putByte(OP2_JGE_rel32);
726         m_buffer->putInt(0);
727         return JmpSrc(m_buffer->getOffset());
728     }
729     
730     JmpSrc emitUnlinkedJae()
731     {
732         m_buffer->putByte(OP_2BYTE_ESCAPE);
733         m_buffer->putByte(OP2_JAE_rel32);
734         m_buffer->putInt(0);
735         return JmpSrc(m_buffer->getOffset());
736     }
737     
738     JmpSrc emitUnlinkedJo()
739     {
740         m_buffer->putByte(OP_2BYTE_ESCAPE);
741         m_buffer->putByte(OP2_JO_rel32);
742         m_buffer->putInt(0);
743         return JmpSrc(m_buffer->getOffset());
744     }
745     
746     void emitPredictionNotTaken()
747     {
748         m_buffer->putByte(PRE_PREDICT_BRANCH_NOT_TAKEN);
749     }
750     
751     void link(JmpSrc from, JmpDst to)
752     {
753         ASSERT(to.m_offset != -1);
754         ASSERT(from.m_offset != -1);
755         
756         ((int*)(((ptrdiff_t)(m_buffer->start())) + from.m_offset))[-1] = to.m_offset - from.m_offset;
757     }
758     
759     static void linkAbsoluteAddress(void* code, JmpDst useOffset, JmpDst address)
760     {
761         ASSERT(useOffset.m_offset != -1);
762         ASSERT(address.m_offset != -1);
763         
764         ((int*)(((ptrdiff_t)code) + useOffset.m_offset))[-1] = ((ptrdiff_t)code) + address.m_offset;
765     }
766     
767     static void link(void* code, JmpSrc from, void* to)
768     {
769         ASSERT(from.m_offset != -1);
770         
771         ((int*)((ptrdiff_t)code + from.m_offset))[-1] = (ptrdiff_t)to - ((ptrdiff_t)code + from.m_offset);
772     }
773     
774     void* getRelocatedAddress(void* code, JmpSrc jump)
775     {
776         return reinterpret_cast<void*>((ptrdiff_t)code + jump.m_offset);
777     }
778     
779     void* getRelocatedAddress(void* code, JmpDst jump)
780     {
781         return reinterpret_cast<void*>((ptrdiff_t)code + jump.m_offset);
782     }
783     
784     void* copy() 
785     {
786         return m_buffer->copy();
787     }
788
789 #if COMPILER(MSVC)
790     void emitConvertToFastCall()
791     {
792         movl_mr(4, X86::esp, X86::eax);
793         movl_mr(8, X86::esp, X86::edx);
794         movl_mr(12, X86::esp, X86::ecx);
795     }
796
797     void emitRestoreArgumentReference()
798     {
799         movl_rm(X86::esp, 0, X86::esp);
800     }
801 #else
802     void emitConvertToFastCall() {};
803     void emitRestoreArgumentReference() {};
804 #endif
805
806 private:
807     void emitModRm_rr(RegisterID reg, RegisterID rm)
808     {
809         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
810         emitModRm_rr_Unchecked(reg, rm);
811     }
812
813     void emitModRm_rr_Unchecked(RegisterID reg, RegisterID rm)
814     {
815         m_buffer->putByteUnchecked(MODRM(3, reg, rm));
816     }
817
818     void emitModRm_rm(RegisterID reg, void* addr)
819     {
820         m_buffer->putByte(MODRM(0, reg, X86::noBase));
821         m_buffer->putInt((int)addr);
822     }
823
824     void emitModRm_rm(RegisterID reg, RegisterID base)
825     {
826         if (base == X86::esp) {
827             m_buffer->putByte(MODRM(0, reg, X86::hasSib));
828             m_buffer->putByte(SIB(0, X86::noScale, X86::esp));
829         } else
830             m_buffer->putByte(MODRM(0, reg, base));
831     }
832
833     void emitModRm_rm_Unchecked(RegisterID reg, RegisterID base, int offset)
834     {
835         if (base == X86::esp) {
836             if (CAN_SIGN_EXTEND_8_32(offset)) {
837                 m_buffer->putByteUnchecked(MODRM(1, reg, X86::hasSib));
838                 m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp));
839                 m_buffer->putByteUnchecked(offset);
840             } else {
841                 m_buffer->putByteUnchecked(MODRM(2, reg, X86::hasSib));
842                 m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp));
843                 m_buffer->putIntUnchecked(offset);
844             }
845         } else {
846             if (CAN_SIGN_EXTEND_8_32(offset)) {
847                 m_buffer->putByteUnchecked(MODRM(1, reg, base));
848                 m_buffer->putByteUnchecked(offset);
849             } else {
850                 m_buffer->putByteUnchecked(MODRM(2, reg, base));
851                 m_buffer->putIntUnchecked(offset);
852             }
853         }
854     }
855
856     void emitModRm_rm(RegisterID reg, RegisterID base, int offset)
857     {
858         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
859         emitModRm_rm_Unchecked(reg, base, offset);
860     }
861
862     void emitModRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale)
863     {
864         int shift = 0;
865         while (scale >>= 1)
866             shift++;
867     
868         m_buffer->putByte(MODRM(0, reg, X86::hasSib));
869         m_buffer->putByte(SIB(shift, index, base));
870     }
871
872     void emitModRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale, int offset)
873     {
874         int shift = 0;
875         while (scale >>= 1)
876             shift++;
877     
878         if (CAN_SIGN_EXTEND_8_32(offset)) {
879             m_buffer->putByte(MODRM(1, reg, X86::hasSib));
880             m_buffer->putByte(SIB(shift, index, base));
881             m_buffer->putByte(offset);
882         } else {
883             m_buffer->putByte(MODRM(2, reg, X86::hasSib));
884             m_buffer->putByte(SIB(shift, index, base));
885             m_buffer->putInt(offset);
886         }
887     }
888
889     void emitModRm_opr(OpcodeID opcode, RegisterID rm)
890     {
891         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
892         emitModRm_opr_Unchecked(opcode, rm);
893     }
894
895     void emitModRm_opr_Unchecked(OpcodeID opcode, RegisterID rm)
896     {
897         emitModRm_rr_Unchecked(static_cast<RegisterID>(opcode), rm);
898     }
899
900     void emitModRm_opm(OpcodeID opcode, RegisterID base)
901     {
902         emitModRm_rm(static_cast<RegisterID>(opcode), base);
903     }
904
905     void emitModRm_opm_Unchecked(OpcodeID opcode, RegisterID base, int offset)
906     {
907         emitModRm_rm_Unchecked(static_cast<RegisterID>(opcode), base, offset);
908     }
909
910     void emitModRm_opm(OpcodeID opcode, RegisterID base, int offset)
911     {
912         emitModRm_rm(static_cast<RegisterID>(opcode), base, offset);
913     }
914
915     void emitModRm_opm(OpcodeID opcode, void* addr)
916     {
917         emitModRm_rm(static_cast<RegisterID>(opcode), addr);
918     }
919
920     JITCodeBuffer* m_buffer;
921 };
922
923 } // namespace JSC
924
925 #endif // ENABLE(MASM) && PLATFORM(X86)
926
927 #endif // X86Assembler_h