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