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