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