c5fa6e69bb2d28bbe6ecfc9b033a0f5c87fd7a35
[WebKit.git] / JavaScriptCore / masm / X86Assembler.h
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef X86Assembler_h
27 #define X86Assembler_h
28
29 #if ENABLE(MASM) && PLATFORM(X86)
30
31 #include <wtf/Assertions.h>
32 #include <wtf/AlwaysInline.h>
33 #if HAVE(MMAN)
34 #include <sys/mman.h>
35 #endif
36
37 #include <string.h>
38
39 namespace JSC {
40
41 class JITCodeBuffer {
42 public:
43     JITCodeBuffer(int size)
44         : m_buffer(static_cast<char*>(fastMalloc(size)))
45         , m_size(size)
46         , m_index(0)
47     {
48     }
49
50     ~JITCodeBuffer()
51     {
52         fastFree(m_buffer);
53     }
54
55     void ensureSpace(int space)
56     {
57         if (m_index > m_size - space)
58             growBuffer();
59     }
60
61     void putByteUnchecked(int value)
62     {
63         m_buffer[m_index] = value;
64         m_index++;
65     }
66
67     void putByte(int value)
68     {
69         if (m_index > m_size - 4)
70             growBuffer();
71         putByteUnchecked(value);
72     }
73     
74     void putShortUnchecked(int value)
75     {
76         *(short*)(&m_buffer[m_index]) = value;
77         m_index += 2;
78     }
79
80     void putShort(int value)
81     {
82         if (m_index > m_size - 4)
83             growBuffer();
84         putShortUnchecked(value);
85     }
86     
87     void putIntUnchecked(int value)
88     {
89         *(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_SETE                         = 0x94,
195         OP_GROUP2_EvIb                  = 0xC1,
196         OP_RET                          = 0xC3,
197         OP_GROUP11_EvIz                 = 0xC7,
198         OP_INT3                         = 0xCC,
199         OP_GROUP2_Ev1                   = 0xD1,
200         OP_GROUP2_EvCL                  = 0xD3,
201         OP_CALL_rel32                   = 0xE8,
202         OP_JMP_rel32                    = 0xE9,
203         OP_GROUP3_Ev                    = 0xF7,
204         OP_GROUP3_EvIz                  = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test. 
205         OP_GROUP5_Ev                    = 0xFF,
206
207         OP2_JO_rel32    = 0x80,
208         OP2_JB_rel32    = 0x82,
209         OP2_JAE_rel32   = 0x83,
210         OP2_JE_rel32    = 0x84,
211         OP2_JNE_rel32   = 0x85,
212         OP2_JBE_rel32   = 0x86,
213         OP2_JA_rel32    = 0x87,
214         OP2_JL_rel32    = 0x8C,
215         OP2_JGE_rel32   = 0x8D,
216         OP2_JLE_rel32   = 0x8E,
217         OP2_IMUL_GvEv   = 0xAF,
218         OP2_MOVZX_GvEb  = 0xB6,
219         OP2_MOVZX_GvEw  = 0xB7,
220
221         GROUP1_OP_ADD = 0,
222         GROUP1_OP_OR  = 1,
223         GROUP1_OP_AND = 4,
224         GROUP1_OP_SUB = 5,
225         GROUP1_OP_XOR = 6,
226         GROUP1_OP_CMP = 7,
227
228         GROUP1A_OP_POP = 0,
229
230         GROUP2_OP_SHL = 4,
231         GROUP2_OP_SAR = 7,
232
233         GROUP3_OP_TEST = 0,
234         GROUP3_OP_IDIV = 7,
235
236         GROUP5_OP_CALLN = 2,
237         GROUP5_OP_JMPN  = 4,
238         GROUP5_OP_PUSH  = 6,
239
240         GROUP11_MOV = 0,
241     } OpcodeID;
242     
243     static const int MAX_INSTRUCTION_SIZE = 16;
244
245     X86Assembler(JITCodeBuffer* m_buffer)
246         : m_buffer(m_buffer)
247     {
248         m_buffer->reset();
249     }
250
251     void emitInt3()
252     {
253         m_buffer->putByte(OP_INT3);
254     }
255     
256     void pushl_r(RegisterID reg)
257     {
258         m_buffer->putByte(OP_PUSH_EAX + reg);
259     }
260     
261     void pushl_m(int offset, RegisterID base)
262     {
263         m_buffer->putByte(OP_GROUP5_Ev);
264         emitModRm_opm(GROUP5_OP_PUSH, base, offset);
265     }
266     
267     void popl_r(RegisterID reg)
268     {
269         m_buffer->putByte(OP_POP_EAX + reg);
270     }
271
272     void popl_m(int offset, RegisterID base)
273     {
274         m_buffer->putByte(OP_GROUP1A_Ev);
275         emitModRm_opm(GROUP1A_OP_POP, base, offset);
276     }
277     
278     void movl_rr(RegisterID src, RegisterID dst)
279     {
280         m_buffer->putByte(OP_MOV_EvGv);
281         emitModRm_rr(src, dst);
282     }
283     
284     void addl_rr(RegisterID src, RegisterID dst)
285     {
286         m_buffer->putByte(OP_ADD_EvGv);
287         emitModRm_rr(src, dst);
288     }
289
290     void addl_i8r(int imm, RegisterID dst)
291     {
292         m_buffer->putByte(OP_GROUP1_EvIb);
293         emitModRm_opr(GROUP1_OP_ADD, dst);
294         m_buffer->putByte(imm);
295     }
296
297     void addl_i8m(int imm, void* addr)
298     {
299         m_buffer->putByte(OP_GROUP1_EvIb);
300         emitModRm_opm(GROUP1_OP_ADD, addr);
301         m_buffer->putByte(imm);
302     }
303
304     void addl_i32r(int imm, RegisterID dst)
305     {
306         m_buffer->putByte(OP_GROUP1_EvIz);
307         emitModRm_opr(GROUP1_OP_ADD, dst);
308         m_buffer->putInt(imm);
309     }
310
311     void addl_mr(int offset, RegisterID base, RegisterID dst)
312     {
313         m_buffer->putByte(OP_ADD_GvEv);
314         emitModRm_rm(dst, base, offset);
315     }
316
317     void andl_rr(RegisterID src, RegisterID dst)
318     {
319         m_buffer->putByte(OP_AND_EvGv);
320         emitModRm_rr(src, dst);
321     }
322
323     void andl_i32r(int imm, RegisterID dst)
324     {
325         m_buffer->putByte(OP_GROUP1_EvIz);
326         emitModRm_opr(GROUP1_OP_AND, dst);
327         m_buffer->putInt(imm);
328     }
329
330     void cmpl_i8r(int imm, RegisterID dst)
331     {
332         m_buffer->putByte(OP_GROUP1_EvIb);
333         emitModRm_opr(GROUP1_OP_CMP, dst);
334         m_buffer->putByte(imm);
335     }
336
337     void cmpl_rr(RegisterID src, RegisterID dst)
338     {
339         m_buffer->putByte(OP_CMP_EvGv);
340         emitModRm_rr(src, dst);
341     }
342
343     void cmpl_rm(RegisterID src, int offset, RegisterID base)
344     {
345         m_buffer->putByte(OP_CMP_EvGv);
346         emitModRm_rm(src, base, offset);
347     }
348
349     void cmpl_i32r(int imm, RegisterID dst)
350     {
351         m_buffer->putByte(OP_GROUP1_EvIz);
352         emitModRm_opr(GROUP1_OP_CMP, dst);
353         m_buffer->putInt(imm);
354     }
355
356     void cmpl_i32m(int imm, RegisterID dst)
357     {
358         m_buffer->putByte(OP_GROUP1_EvIz);
359         emitModRm_opm(GROUP1_OP_CMP, dst);
360         m_buffer->putInt(imm);
361     }
362
363     void cmpl_i32m(int imm, int offset, RegisterID dst)
364     {
365         m_buffer->putByte(OP_GROUP1_EvIz);
366         emitModRm_opm(GROUP1_OP_CMP, dst, offset);
367         m_buffer->putInt(imm);
368     }
369
370     void cmpl_i32m(int imm, void* addr)
371     {
372         m_buffer->putByte(OP_GROUP1_EvIz);
373         emitModRm_opm(GROUP1_OP_CMP, addr);
374         m_buffer->putInt(imm);
375     }
376
377     void cmpl_i8m(int imm, int offset, RegisterID base, RegisterID index, int scale)
378     {
379         m_buffer->putByte(OP_GROUP1_EvIb);
380         emitModRm_opmsib(GROUP1_OP_CMP, base, index, scale, offset);
381         m_buffer->putByte(imm);
382     }
383
384     void cmpw_rm(RegisterID src, RegisterID base, RegisterID index, int scale)
385     {
386         m_buffer->putByte(PRE_OPERAND_SIZE);
387         m_buffer->putByte(OP_CMP_EvGv);
388         emitModRm_rmsib(src, base, index, scale);
389     }
390
391     void sete_r(RegisterID dst)
392     {
393         m_buffer->putByte(OP_2BYTE_ESCAPE);
394         m_buffer->putByte(OP_SETE);
395         m_buffer->putByte(MODRM(3, 0, dst));
396     }
397
398     void setz_r(RegisterID dst)
399     {
400         sete_r(dst);
401     }
402
403     void orl_rr(RegisterID src, RegisterID dst)
404     {
405         m_buffer->putByte(OP_OR_EvGv);
406         emitModRm_rr(src, dst);
407     }
408
409     void orl_i32r(int imm, RegisterID dst)
410     {
411         m_buffer->putByte(OP_GROUP1_EvIb);
412         emitModRm_opr(GROUP1_OP_OR, dst);
413         m_buffer->putByte(imm);
414     }
415
416     void subl_rr(RegisterID src, RegisterID dst)
417     {
418         m_buffer->putByte(OP_SUB_EvGv);
419         emitModRm_rr(src, dst);
420     }
421
422     void subl_i8r(int imm, RegisterID dst)
423     {
424         m_buffer->putByte(OP_GROUP1_EvIb);
425         emitModRm_opr(GROUP1_OP_SUB, dst);
426         m_buffer->putByte(imm);
427     }
428     
429     void subl_i8m(int imm, void* addr)
430     {
431         m_buffer->putByte(OP_GROUP1_EvIb);
432         emitModRm_opm(GROUP1_OP_SUB, addr);
433         m_buffer->putByte(imm);
434     }
435
436     void subl_i32r(int imm, RegisterID dst)
437     {
438         m_buffer->putByte(OP_GROUP1_EvIz);
439         emitModRm_opr(GROUP1_OP_SUB, dst);
440         m_buffer->putInt(imm);
441     }
442
443     void subl_mr(int offset, RegisterID base, RegisterID dst)
444     {
445         m_buffer->putByte(OP_SUB_GvEv);
446         emitModRm_rm(dst, base, offset);
447     }
448
449     void testl_i32r(int imm, RegisterID dst)
450     {
451         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
452         m_buffer->putByteUnchecked(OP_GROUP3_EvIz);
453         emitModRm_opr_Unchecked(GROUP3_OP_TEST, dst);
454         m_buffer->putIntUnchecked(imm);
455     }
456
457     void testl_rr(RegisterID src, RegisterID dst)
458     {
459         m_buffer->putByte(OP_TEST_EvGv);
460         emitModRm_rr(src, dst);
461     }
462     
463     void xorl_i8r(int imm, RegisterID dst)
464     {
465         m_buffer->putByte(OP_GROUP1_EvIb);
466         emitModRm_opr(GROUP1_OP_XOR, dst);
467         m_buffer->putByte(imm);
468     }
469
470     void xorl_rr(RegisterID src, RegisterID dst)
471     {
472         m_buffer->putByte(OP_XOR_EvGv);
473         emitModRm_rr(src, dst);
474     }
475
476     void sarl_i8r(int imm, RegisterID dst)
477     {
478         if (imm == 1) {
479             m_buffer->putByte(OP_GROUP2_Ev1);
480             emitModRm_opr(GROUP2_OP_SAR, dst);
481         } else {
482             m_buffer->putByte(OP_GROUP2_EvIb);
483             emitModRm_opr(GROUP2_OP_SAR, dst);
484             m_buffer->putByte(imm);
485         }
486     }
487
488     void sarl_CLr(RegisterID dst)
489     {
490         m_buffer->putByte(OP_GROUP2_EvCL);
491         emitModRm_opr(GROUP2_OP_SAR, dst);
492     }
493
494     void shl_i8r(int imm, RegisterID dst)
495     {
496         if (imm == 1) {
497             m_buffer->putByte(OP_GROUP2_Ev1);
498             emitModRm_opr(GROUP2_OP_SHL, dst);
499         } else {
500             m_buffer->putByte(OP_GROUP2_EvIb);
501             emitModRm_opr(GROUP2_OP_SHL, dst);
502             m_buffer->putByte(imm);
503         }
504     }
505
506     void shll_CLr(RegisterID dst)
507     {
508         m_buffer->putByte(OP_GROUP2_EvCL);
509         emitModRm_opr(GROUP2_OP_SHL, dst);
510     }
511
512     void imull_rr(RegisterID src, RegisterID dst)
513     {
514         m_buffer->putByte(OP_2BYTE_ESCAPE);
515         m_buffer->putByte(OP2_IMUL_GvEv);
516         emitModRm_rr(dst, src);
517     }
518     
519     void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
520     {
521         m_buffer->putByte(OP_IMUL_GvEvIz);
522         emitModRm_rr(dst, src);
523         m_buffer->putInt(value);
524     }
525
526     void idivl_r(RegisterID dst)
527     {
528         m_buffer->putByte(OP_GROUP3_Ev);
529         emitModRm_opr(GROUP3_OP_IDIV, dst);
530     }
531
532     void cdq()
533     {
534         m_buffer->putByte(OP_CDQ);
535     }
536
537     void movl_mr(RegisterID base, RegisterID dst)
538     {
539         m_buffer->putByte(OP_MOV_GvEv);
540         emitModRm_rm(dst, base);
541     }
542
543     void movl_mr(int offset, RegisterID base, RegisterID dst)
544     {
545         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
546         m_buffer->putByteUnchecked(OP_MOV_GvEv);
547         emitModRm_rm_Unchecked(dst, base, offset);
548     }
549
550     void movl_mr(void* addr, RegisterID dst)
551     {
552         m_buffer->putByte(OP_MOV_GvEv);
553         emitModRm_rm(dst, addr);
554     }
555
556     void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
557     {
558         m_buffer->putByte(OP_MOV_GvEv);
559         emitModRm_rmsib(dst, base, index, scale, offset);
560     }
561
562     void movzbl_rr(RegisterID src, RegisterID dst)
563     {
564         m_buffer->putByte(OP_2BYTE_ESCAPE);
565         m_buffer->putByte(OP2_MOVZX_GvEb);
566         emitModRm_rr(dst, src);
567     }
568
569     void movzwl_mr(int offset, RegisterID base, RegisterID dst)
570     {
571         m_buffer->putByte(OP_2BYTE_ESCAPE);
572         m_buffer->putByte(OP2_MOVZX_GvEw);
573         emitModRm_rm(dst, base, offset);
574     }
575
576     void movzwl_mr(RegisterID base, RegisterID index, int scale, RegisterID dst)
577     {
578         m_buffer->putByte(OP_2BYTE_ESCAPE);
579         m_buffer->putByte(OP2_MOVZX_GvEw);
580         emitModRm_rmsib(dst, base, index, scale);
581     }
582
583     void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
584     {
585         m_buffer->putByte(OP_2BYTE_ESCAPE);
586         m_buffer->putByte(OP2_MOVZX_GvEw);
587         emitModRm_rmsib(dst, base, index, scale, offset);
588     }
589
590     void movl_rm(RegisterID src, RegisterID base)
591     {
592         m_buffer->putByte(OP_MOV_EvGv);
593         emitModRm_rm(src, base);
594     }
595
596     void movl_rm(RegisterID src, int offset, RegisterID base)
597     {
598         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
599         m_buffer->putByteUnchecked(OP_MOV_EvGv);
600         emitModRm_rm_Unchecked(src, base, offset);
601     }
602     
603     void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
604     {
605         m_buffer->putByte(OP_MOV_EvGv);
606         emitModRm_rmsib(src, base, index, scale, offset);
607     }
608     
609     void movl_i32r(int imm, RegisterID dst)
610     {
611         m_buffer->putByte(OP_GROUP11_EvIz);
612         emitModRm_opr(GROUP11_MOV, dst);
613         m_buffer->putInt(imm);
614     }
615
616     void movl_i32m(int imm, int offset, RegisterID base)
617     {
618         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
619         m_buffer->putByteUnchecked(OP_GROUP11_EvIz);
620         emitModRm_opm_Unchecked(GROUP11_MOV, base, offset);
621         m_buffer->putIntUnchecked(imm);
622     }
623
624     void movl_i32m(int imm, void* addr)
625     {
626         m_buffer->putByte(OP_GROUP11_EvIz);
627         emitModRm_opm(GROUP11_MOV, addr);
628         m_buffer->putInt(imm);
629     }
630
631     void leal_mr(int offset, RegisterID base, RegisterID dst)
632     {
633         m_buffer->putByte(OP_LEA);
634         emitModRm_rm(dst, base, offset);
635     }
636
637     void ret()
638     {
639         m_buffer->putByte(OP_RET);
640     }
641     
642     void jmp_r(RegisterID dst)
643     {
644         m_buffer->putByte(OP_GROUP5_Ev);
645         emitModRm_opr(GROUP5_OP_JMPN, dst);
646     }
647     
648     void jmp_m(int offset, RegisterID base)
649     {
650         m_buffer->putByte(OP_GROUP5_Ev);
651         emitModRm_opm(GROUP5_OP_JMPN, base, offset);
652     }
653     
654     void call_r(RegisterID dst)
655     {
656         m_buffer->putByte(OP_GROUP5_Ev);
657         emitModRm_opr(GROUP5_OP_CALLN, dst);
658     }
659
660     // Opaque label types
661     
662     class JmpSrc {
663         friend class X86Assembler;
664     public:
665         JmpSrc()
666             : m_offset(-1)
667         {
668         }
669
670     private:
671         JmpSrc(int offset)
672             : m_offset(offset)
673         {
674         }
675
676         int m_offset;
677     };
678     
679     class JmpDst {
680         friend class X86Assembler;
681     public:
682         JmpDst()
683             : m_offset(-1)
684         {
685         }
686
687     private:
688         JmpDst(int offset)
689             : m_offset(offset)
690         {
691         }
692
693         int m_offset;
694     };
695
696     // FIXME: make this point to a global label, linked later.
697     JmpSrc emitCall()
698     {
699         m_buffer->putByte(OP_CALL_rel32);
700         m_buffer->putInt(0);
701         return JmpSrc(m_buffer->getOffset());
702     }
703     
704     JmpDst label()
705     {
706         return JmpDst(m_buffer->getOffset());
707     }
708     
709     JmpSrc emitUnlinkedJmp()
710     {
711         m_buffer->putByte(OP_JMP_rel32);
712         m_buffer->putInt(0);
713         return JmpSrc(m_buffer->getOffset());
714     }
715     
716     JmpSrc emitUnlinkedJne()
717     {
718         m_buffer->putByte(OP_2BYTE_ESCAPE);
719         m_buffer->putByte(OP2_JNE_rel32);
720         m_buffer->putInt(0);
721         return JmpSrc(m_buffer->getOffset());
722     }
723     
724     JmpSrc emitUnlinkedJnz()
725     {
726         return emitUnlinkedJne();
727     }
728
729     JmpSrc emitUnlinkedJe()
730     {
731         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
732         m_buffer->putByteUnchecked(OP_2BYTE_ESCAPE);
733         m_buffer->putByteUnchecked(OP2_JE_rel32);
734         m_buffer->putIntUnchecked(0);
735         return JmpSrc(m_buffer->getOffset());
736     }
737     
738     JmpSrc emitUnlinkedJl()
739     {
740         m_buffer->putByte(OP_2BYTE_ESCAPE);
741         m_buffer->putByte(OP2_JL_rel32);
742         m_buffer->putInt(0);
743         return JmpSrc(m_buffer->getOffset());
744     }
745     
746     JmpSrc emitUnlinkedJb()
747     {
748         m_buffer->putByte(OP_2BYTE_ESCAPE);
749         m_buffer->putByte(OP2_JB_rel32);
750         m_buffer->putInt(0);
751         return JmpSrc(m_buffer->getOffset());
752     }
753     
754     JmpSrc emitUnlinkedJle()
755     {
756         m_buffer->putByte(OP_2BYTE_ESCAPE);
757         m_buffer->putByte(OP2_JLE_rel32);
758         m_buffer->putInt(0);
759         return JmpSrc(m_buffer->getOffset());
760     }
761     
762     JmpSrc emitUnlinkedJbe()
763     {
764         m_buffer->putByte(OP_2BYTE_ESCAPE);
765         m_buffer->putByte(OP2_JBE_rel32);
766         m_buffer->putInt(0);
767         return JmpSrc(m_buffer->getOffset());
768     }
769     
770     JmpSrc emitUnlinkedJge()
771     {
772         m_buffer->putByte(OP_2BYTE_ESCAPE);
773         m_buffer->putByte(OP2_JGE_rel32);
774         m_buffer->putInt(0);
775         return JmpSrc(m_buffer->getOffset());
776     }
777     
778     JmpSrc emitUnlinkedJa()
779     {
780         m_buffer->putByte(OP_2BYTE_ESCAPE);
781         m_buffer->putByte(OP2_JA_rel32);
782         m_buffer->putInt(0);
783         return JmpSrc(m_buffer->getOffset());
784     }
785     
786     JmpSrc emitUnlinkedJae()
787     {
788         m_buffer->putByte(OP_2BYTE_ESCAPE);
789         m_buffer->putByte(OP2_JAE_rel32);
790         m_buffer->putInt(0);
791         return JmpSrc(m_buffer->getOffset());
792     }
793     
794     JmpSrc emitUnlinkedJo()
795     {
796         m_buffer->putByte(OP_2BYTE_ESCAPE);
797         m_buffer->putByte(OP2_JO_rel32);
798         m_buffer->putInt(0);
799         return JmpSrc(m_buffer->getOffset());
800     }
801     
802     void emitPredictionNotTaken()
803     {
804         m_buffer->putByte(PRE_PREDICT_BRANCH_NOT_TAKEN);
805     }
806     
807     void link(JmpSrc from, JmpDst to)
808     {
809         ASSERT(to.m_offset != -1);
810         ASSERT(from.m_offset != -1);
811         
812         ((int*)(((ptrdiff_t)(m_buffer->start())) + from.m_offset))[-1] = to.m_offset - from.m_offset;
813     }
814     
815     static void linkAbsoluteAddress(void* code, JmpDst useOffset, JmpDst address)
816     {
817         ASSERT(useOffset.m_offset != -1);
818         ASSERT(address.m_offset != -1);
819         
820         ((int*)(((ptrdiff_t)code) + useOffset.m_offset))[-1] = ((ptrdiff_t)code) + address.m_offset;
821     }
822     
823     static void link(void* code, JmpSrc from, void* to)
824     {
825         ASSERT(from.m_offset != -1);
826         
827         ((int*)((ptrdiff_t)code + from.m_offset))[-1] = (ptrdiff_t)to - ((ptrdiff_t)code + from.m_offset);
828     }
829     
830     static void* getRelocatedAddress(void* code, JmpSrc jump)
831     {
832         return reinterpret_cast<void*>((ptrdiff_t)code + jump.m_offset);
833     }
834     
835     static void* getRelocatedAddress(void* code, JmpDst jump)
836     {
837         return reinterpret_cast<void*>((ptrdiff_t)code + jump.m_offset);
838     }
839     
840     static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
841     {
842         return dst.m_offset - src.m_offset;
843     }
844     
845     static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
846     {
847         return dst.m_offset - src.m_offset;
848     }
849     
850     static void repatchImmediate(intptr_t where, int32_t value)
851     {
852         reinterpret_cast<int32_t*>(where)[-1] = value;
853     }
854     
855     static void repatchDisplacement(intptr_t where, intptr_t value)
856     {
857         reinterpret_cast<intptr_t*>(where)[-1] = value;
858     }
859     
860     static void repatchBranchOffset(intptr_t where, void* destination)
861     {
862         reinterpret_cast<intptr_t*>(where)[-1] = (reinterpret_cast<intptr_t>(destination) - where);
863     }
864     
865     void* copy() 
866     {
867         return m_buffer->copy();
868     }
869
870 #if COMPILER(MSVC)
871     void emitConvertToFastCall()
872     {
873         movl_mr(4, X86::esp, X86::eax);
874         movl_mr(8, X86::esp, X86::edx);
875         movl_mr(12, X86::esp, X86::ecx);
876     }
877
878     void emitRestoreArgumentReference()
879     {
880         movl_rm(X86::esp, 0, X86::esp);
881     }
882 #else
883     void emitConvertToFastCall() {};
884     void emitRestoreArgumentReference() {};
885 #endif
886
887 private:
888     void emitModRm_rr(RegisterID reg, RegisterID rm)
889     {
890         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
891         emitModRm_rr_Unchecked(reg, rm);
892     }
893
894     void emitModRm_rr_Unchecked(RegisterID reg, RegisterID rm)
895     {
896         m_buffer->putByteUnchecked(MODRM(3, reg, rm));
897     }
898
899     void emitModRm_rm(RegisterID reg, void* addr)
900     {
901         m_buffer->putByte(MODRM(0, reg, X86::noBase));
902         m_buffer->putInt((int)addr);
903     }
904
905     void emitModRm_rm(RegisterID reg, RegisterID base)
906     {
907         if (base == X86::esp) {
908             m_buffer->putByte(MODRM(0, reg, X86::hasSib));
909             m_buffer->putByte(SIB(0, X86::noScale, X86::esp));
910         } else
911             m_buffer->putByte(MODRM(0, reg, base));
912     }
913
914     void emitModRm_rm_Unchecked(RegisterID reg, RegisterID base, int offset)
915     {
916         if (base == X86::esp) {
917             if (CAN_SIGN_EXTEND_8_32(offset)) {
918                 m_buffer->putByteUnchecked(MODRM(1, reg, X86::hasSib));
919                 m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp));
920                 m_buffer->putByteUnchecked(offset);
921             } else {
922                 m_buffer->putByteUnchecked(MODRM(2, reg, X86::hasSib));
923                 m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp));
924                 m_buffer->putIntUnchecked(offset);
925             }
926         } else {
927             if (CAN_SIGN_EXTEND_8_32(offset)) {
928                 m_buffer->putByteUnchecked(MODRM(1, reg, base));
929                 m_buffer->putByteUnchecked(offset);
930             } else {
931                 m_buffer->putByteUnchecked(MODRM(2, reg, base));
932                 m_buffer->putIntUnchecked(offset);
933             }
934         }
935     }
936
937     void emitModRm_rm(RegisterID reg, RegisterID base, int offset)
938     {
939         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
940         emitModRm_rm_Unchecked(reg, base, offset);
941     }
942
943     void emitModRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale)
944     {
945         int shift = 0;
946         while (scale >>= 1)
947             shift++;
948     
949         m_buffer->putByte(MODRM(0, reg, X86::hasSib));
950         m_buffer->putByte(SIB(shift, index, base));
951     }
952
953     void emitModRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale, int offset)
954     {
955         int shift = 0;
956         while (scale >>= 1)
957             shift++;
958     
959         if (CAN_SIGN_EXTEND_8_32(offset)) {
960             m_buffer->putByte(MODRM(1, reg, X86::hasSib));
961             m_buffer->putByte(SIB(shift, index, base));
962             m_buffer->putByte(offset);
963         } else {
964             m_buffer->putByte(MODRM(2, reg, X86::hasSib));
965             m_buffer->putByte(SIB(shift, index, base));
966             m_buffer->putInt(offset);
967         }
968     }
969
970     void emitModRm_opr(OpcodeID opcode, RegisterID rm)
971     {
972         m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
973         emitModRm_opr_Unchecked(opcode, rm);
974     }
975
976     void emitModRm_opr_Unchecked(OpcodeID opcode, RegisterID rm)
977     {
978         emitModRm_rr_Unchecked(static_cast<RegisterID>(opcode), rm);
979     }
980
981     void emitModRm_opm(OpcodeID opcode, RegisterID base)
982     {
983         emitModRm_rm(static_cast<RegisterID>(opcode), base);
984     }
985
986     void emitModRm_opm_Unchecked(OpcodeID opcode, RegisterID base, int offset)
987     {
988         emitModRm_rm_Unchecked(static_cast<RegisterID>(opcode), base, offset);
989     }
990
991     void emitModRm_opm(OpcodeID opcode, RegisterID base, int offset)
992     {
993         emitModRm_rm(static_cast<RegisterID>(opcode), base, offset);
994     }
995
996     void emitModRm_opm(OpcodeID opcode, void* addr)
997     {
998         emitModRm_rm(static_cast<RegisterID>(opcode), addr);
999     }
1000
1001     void emitModRm_opmsib(OpcodeID opcode, RegisterID base, RegisterID index, int scale, int offset)
1002     {
1003         emitModRm_rmsib(static_cast<RegisterID>(opcode), base, index, scale, offset);
1004     }
1005
1006     JITCodeBuffer* m_buffer;
1007 };
1008
1009 } // namespace JSC
1010
1011 #endif // ENABLE(MASM) && PLATFORM(X86)
1012
1013 #endif // X86Assembler_h