Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / assembler / assembler / X86Assembler.h
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=8 sw=4 et tw=79:
3  *
4  * ***** BEGIN LICENSE BLOCK *****
5  * Copyright (C) 2008 Apple Inc. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
27  * 
28  * ***** END LICENSE BLOCK ***** */
29
30 #ifndef X86Assembler_h
31 #define X86Assembler_h
32
33 #include "assembler/wtf/Platform.h"
34
35 #if ENABLE_ASSEMBLER && (WTF_CPU_X86 || WTF_CPU_X86_64)
36
37 #include "AssemblerBuffer.h"
38 #include "jsstdint.h"
39 #include "assembler/wtf/Assertions.h"
40 #include "jsvector.h"
41
42 #include "methodjit/Logging.h"
43 #define IPFX  "        %s"
44 #define ISPFX "        "
45 #ifdef JS_METHODJIT_SPEW
46 # define MAYBE_PAD (isOOLPath ? ">  " : "")
47 # define PRETTY_PRINT_OFFSET(os) (((os)<0)?"-":""), (((os)<0)?-(os):(os))
48 # define FIXME_INSN_PRINTING                                \
49     do {                                                    \
50         js::JaegerSpew(js::JSpew_Insns,                     \
51                        ISPFX "FIXME insn printing %s:%d\n", \
52                        __FILE__, __LINE__);                 \
53     } while (0)
54 #else
55 # define MAYBE_PAD ""
56 # define FIXME_INSN_PRINTING ((void) 0)
57 # define PRETTY_PRINT_OFFSET(os) "", 0
58 #endif
59
60
61 namespace JSC {
62
63 inline bool CAN_SIGN_EXTEND_8_32(int32_t value) { return value == (int32_t)(signed char)value; }
64
65 namespace X86Registers {
66     typedef enum {
67         eax,
68         ecx,
69         edx,
70         ebx,
71         esp,
72         ebp,
73         esi,
74         edi
75
76 #if WTF_CPU_X86_64
77        ,r8,
78         r9,
79         r10,
80         r11,
81         r12,
82         r13,
83         r14,
84         r15
85 #endif
86     } RegisterID;
87
88     typedef enum {
89         xmm0,
90         xmm1,
91         xmm2,
92         xmm3,
93         xmm4,
94         xmm5,
95         xmm6,
96         xmm7
97     } XMMRegisterID;
98
99     static const char* nameFPReg(XMMRegisterID fpreg)
100     {
101         static const char* xmmnames[8]
102           = { "%xmm0", "%xmm1", "%xmm2", "%xmm3",
103               "%xmm4", "%xmm5", "%xmm6", "%xmm7" };
104         int off = (XMMRegisterID)fpreg - (XMMRegisterID)xmm0;
105         return (off < 0 || off > 7) ? "%xmm?" : xmmnames[off];
106     }
107
108     static const char* nameIReg(int szB, RegisterID reg)
109     {
110         static const char* r64names[16]
111           = { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
112               "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" };
113         static const char* r32names[16]
114           = { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
115               "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" };
116         static const char* r16names[16]
117           = { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
118               "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" };
119         static const char* r8names[16]
120           = { "%al", "%cl", "%dl", "%bl", "%ah/spl", "%ch/bpl", "%dh/sil", "%bh/dil",
121               "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" };
122         int          off = (RegisterID)reg - (RegisterID)eax;
123         const char** tab = r64names;
124         switch (szB) {
125             case 1: tab = r8names; break;
126             case 2: tab = r16names; break;
127             case 4: tab = r32names; break;
128         }
129         return (off < 0 || off > 15) ? "%r???" : tab[off];
130     }
131
132     static const char* nameIReg(RegisterID reg)
133     {
134 #       if WTF_CPU_X86_64
135         return nameIReg(8, reg);
136 #       else
137         return nameIReg(4, reg);
138 #       endif
139     }
140
141 } /* namespace X86Registers */
142
143
144 class X86Assembler {
145 public:
146     typedef X86Registers::RegisterID RegisterID;
147     typedef X86Registers::XMMRegisterID XMMRegisterID;
148     typedef XMMRegisterID FPRegisterID;
149
150     typedef enum {
151         ConditionO,
152         ConditionNO,
153         ConditionB,
154         ConditionAE,
155         ConditionE,
156         ConditionNE,
157         ConditionBE,
158         ConditionA,
159         ConditionS,
160         ConditionNS,
161         ConditionP,
162         ConditionNP,
163         ConditionL,
164         ConditionGE,
165         ConditionLE,
166         ConditionG,
167
168         ConditionC  = ConditionB,
169         ConditionNC = ConditionAE
170     } Condition;
171
172     static const char* nameCC(Condition cc)
173     {
174         static const char* names[16]
175           = { "o ", "no", "b ", "ae", "e ", "ne", "be", "a ",
176               "s ", "ns", "p ", "np", "l ", "ge", "le", "g " };
177         int ix = (int)cc;
178         return (ix < 0 || ix > 15) ? "??" : names[ix];
179     }
180
181 private:
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_3BYTE_ESCAPE                 = 0x3A,
189         OP_AND_EvGv                     = 0x21,
190         OP_AND_GvEv                     = 0x23,
191         OP_SUB_EvGv                     = 0x29,
192         OP_SUB_GvEv                     = 0x2B,
193         PRE_PREDICT_BRANCH_NOT_TAKEN    = 0x2E,
194         OP_XOR_EvGv                     = 0x31,
195         OP_XOR_GvEv                     = 0x33,
196         OP_CMP_EvGv                     = 0x39,
197         OP_CMP_GvEv                     = 0x3B,
198 #if WTF_CPU_X86_64
199         PRE_REX                         = 0x40,
200 #endif
201         OP_PUSH_EAX                     = 0x50,
202         OP_POP_EAX                      = 0x58,
203 #if WTF_CPU_X86
204         OP_PUSHA                        = 0x60,
205         OP_POPA                         = 0x61,
206 #endif
207 #if WTF_CPU_X86_64
208         OP_MOVSXD_GvEv                  = 0x63,
209 #endif
210         PRE_OPERAND_SIZE                = 0x66,
211         PRE_SSE_66                      = 0x66,
212         OP_PUSH_Iz                      = 0x68,
213         OP_IMUL_GvEvIz                  = 0x69,
214         OP_GROUP1_EbIb                  = 0x80,
215         OP_GROUP1_EvIz                  = 0x81,
216         OP_GROUP1_EvIb                  = 0x83,
217         OP_TEST_EvGv                    = 0x85,
218         OP_XCHG_EvGv                    = 0x87,
219         OP_MOV_EbGv                     = 0x88,
220         OP_MOV_EvGv                     = 0x89,
221         OP_MOV_GvEv                     = 0x8B,
222         OP_LEA                          = 0x8D,
223         OP_GROUP1A_Ev                   = 0x8F,
224         OP_CDQ                          = 0x99,
225         OP_MOV_EAXOv                    = 0xA1,
226         OP_MOV_OvEAX                    = 0xA3,
227         OP_MOV_EAXIv                    = 0xB8,
228         OP_GROUP2_EvIb                  = 0xC1,
229         OP_RET                          = 0xC3,
230         OP_GROUP11_EvIb                 = 0xC6,
231         OP_GROUP11_EvIz                 = 0xC7,
232         OP_INT3                         = 0xCC,
233         OP_GROUP2_Ev1                   = 0xD1,
234         OP_GROUP2_EvCL                  = 0xD3,
235         OP_CALL_rel32                   = 0xE8,
236         OP_JMP_rel32                    = 0xE9,
237         PRE_SSE_F2                      = 0xF2,
238         PRE_SSE_F3                      = 0xF3,
239         OP_HLT                          = 0xF4,
240         OP_GROUP3_EbIb                  = 0xF6,
241         OP_GROUP3_Ev                    = 0xF7,
242         OP_GROUP3_EvIz                  = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test. 
243         OP_GROUP5_Ev                    = 0xFF
244     } OneByteOpcodeID;
245
246     typedef enum {
247         OP2_MOVSD_VsdWsd    = 0x10,
248         OP2_MOVSD_WsdVsd    = 0x11,
249         OP2_UNPCKLPS_VsdWsd = 0x14,
250         OP2_CVTSI2SD_VsdEd  = 0x2A,
251         OP2_CVTTSD2SI_GdWsd = 0x2C,
252         OP2_UCOMISD_VsdWsd  = 0x2E,
253         OP2_ADDSD_VsdWsd    = 0x58,
254         OP2_MULSD_VsdWsd    = 0x59,
255         OP2_CVTSS2SD_VsdEd  = 0x5A,
256         OP2_CVTSD2SS_VsdEd  = 0x5A,
257         OP2_SUBSD_VsdWsd    = 0x5C,
258         OP2_DIVSD_VsdWsd    = 0x5E,
259         OP2_SQRTSD_VsdWsd   = 0x51,
260         OP2_XORPD_VpdWpd    = 0x57,
261         OP2_MOVD_VdEd       = 0x6E,
262         OP2_PSRLDQ_Vd       = 0x73,
263         OP2_MOVD_EdVd       = 0x7E,
264         OP2_JCC_rel32       = 0x80,
265         OP_SETCC            = 0x90,
266         OP2_IMUL_GvEv       = 0xAF,
267         OP2_MOVSX_GvEb      = 0xBE,
268         OP2_MOVSX_GvEw      = 0xBF,
269         OP2_MOVZX_GvEb      = 0xB6,
270         OP2_MOVZX_GvEw      = 0xB7,
271         OP2_PEXTRW_GdUdIb   = 0xC5
272     } TwoByteOpcodeID;
273
274     typedef enum {
275         OP3_PINSRD_VsdWsd   = 0x22
276     } ThreeByteOpcodeID;
277
278     TwoByteOpcodeID jccRel32(Condition cond)
279     {
280         return (TwoByteOpcodeID)(OP2_JCC_rel32 + cond);
281     }
282
283     TwoByteOpcodeID setccOpcode(Condition cond)
284     {
285         return (TwoByteOpcodeID)(OP_SETCC + cond);
286     }
287
288     typedef enum {
289         GROUP1_OP_ADD = 0,
290         GROUP1_OP_OR  = 1,
291         GROUP1_OP_ADC = 2,
292         GROUP1_OP_AND = 4,
293         GROUP1_OP_SUB = 5,
294         GROUP1_OP_XOR = 6,
295         GROUP1_OP_CMP = 7,
296
297         GROUP1A_OP_POP = 0,
298
299         GROUP2_OP_SHL = 4,
300         GROUP2_OP_SHR = 5,
301         GROUP2_OP_SAR = 7,
302
303         GROUP3_OP_TEST = 0,
304         GROUP3_OP_NOT  = 2,
305         GROUP3_OP_NEG  = 3,
306         GROUP3_OP_IDIV = 7,
307
308         GROUP5_OP_CALLN = 2,
309         GROUP5_OP_JMPN  = 4,
310         GROUP5_OP_PUSH  = 6,
311
312         GROUP11_MOV = 0
313     } GroupOpcodeID;
314     
315     class X86InstructionFormatter;
316 public:
317
318 #ifdef JS_METHODJIT_SPEW
319     bool isOOLPath;
320 #endif
321
322     class JmpSrc {
323         friend class X86Assembler;
324         friend class X86InstructionFormatter;
325     public:
326         JmpSrc()
327             : m_offset(-1)
328         {
329         }
330
331     private:
332         JmpSrc(int offset)
333             : m_offset(offset)
334         {
335         }
336
337         int m_offset;
338     };
339     
340     class JmpDst {
341         friend class X86Assembler;
342         friend class X86InstructionFormatter;
343     public:
344         JmpDst()
345             : m_offset(-1)
346             , m_used(false)
347         {
348         }
349
350         bool isUsed() const { return m_used; }
351         void used() { m_used = true; }
352         bool isValid() const { return m_offset != -1; }
353     private:
354         JmpDst(int offset)
355             : m_offset(offset)
356             , m_used(false)
357         {
358             ASSERT(m_offset == offset);
359         }
360
361         signed int m_offset : 31;
362         bool m_used : 1;
363     };
364
365     X86Assembler()
366 #ifdef JS_METHODJIT_SPEW
367       : isOOLPath(false)
368 #endif
369     {
370     }
371
372     size_t size() const { return m_formatter.size(); }
373     unsigned char *buffer() const { return m_formatter.buffer(); }
374     bool oom() const { return m_formatter.oom(); }
375
376     // Stack operations:
377
378     void push_r(RegisterID reg)
379     {
380         js::JaegerSpew(js::JSpew_Insns,
381                        IPFX "push       %s\n", MAYBE_PAD, nameIReg(reg));
382         m_formatter.oneByteOp(OP_PUSH_EAX, reg);
383     }
384
385     void pop_r(RegisterID reg)
386     {
387         js::JaegerSpew(js::JSpew_Insns,
388                        IPFX "pop        %s\n", MAYBE_PAD, nameIReg(reg));
389         m_formatter.oneByteOp(OP_POP_EAX, reg);
390     }
391
392     void push_i32(int imm)
393     {
394         js::JaegerSpew(js::JSpew_Insns,
395                        IPFX "pushl      %s$0x%x\n", MAYBE_PAD,
396                        PRETTY_PRINT_OFFSET(imm));
397         m_formatter.oneByteOp(OP_PUSH_Iz);
398         m_formatter.immediate32(imm);
399     }
400
401     void push_m(int offset, RegisterID base)
402     {
403         js::JaegerSpew(js::JSpew_Insns,
404                        IPFX "push       %s0x%x(%s)\n", MAYBE_PAD,
405                        PRETTY_PRINT_OFFSET(offset), nameIReg(base));
406         m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_PUSH, base, offset);
407     }
408
409     void pop_m(int offset, RegisterID base)
410     {
411         FIXME_INSN_PRINTING;
412         m_formatter.oneByteOp(OP_GROUP1A_Ev, GROUP1A_OP_POP, base, offset);
413     }
414
415     // Arithmetic operations:
416
417 #if !WTF_CPU_X86_64
418     void adcl_im(int imm, void* addr)
419     {
420         FIXME_INSN_PRINTING;
421         if (CAN_SIGN_EXTEND_8_32(imm)) {
422             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADC, addr);
423             m_formatter.immediate8(imm);
424         } else {
425             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADC, addr);
426             m_formatter.immediate32(imm);
427         }
428     }
429 #endif
430
431     void addl_rr(RegisterID src, RegisterID dst)
432     {
433         js::JaegerSpew(js::JSpew_Insns,
434                        IPFX "addl       %s, %s\n", MAYBE_PAD,
435                        nameIReg(4,src), nameIReg(4,dst));
436         m_formatter.oneByteOp(OP_ADD_EvGv, src, dst);
437     }
438
439     void addl_mr(int offset, RegisterID base, RegisterID dst)
440     {
441         FIXME_INSN_PRINTING;
442         m_formatter.oneByteOp(OP_ADD_GvEv, dst, base, offset);
443     }
444
445     void addl_rm(RegisterID src, int offset, RegisterID base)
446     {
447         FIXME_INSN_PRINTING;
448         m_formatter.oneByteOp(OP_ADD_EvGv, src, base, offset);
449     }
450
451     void addl_ir(int imm, RegisterID dst)
452     {
453         js::JaegerSpew(js::JSpew_Insns,
454                        IPFX "addl       $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(4,dst));
455         if (CAN_SIGN_EXTEND_8_32(imm)) {
456             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, dst);
457             m_formatter.immediate8(imm);
458         } else {
459             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, dst);
460             m_formatter.immediate32(imm);
461         }
462     }
463
464     void addl_im(int imm, int offset, RegisterID base)
465     {
466         js::JaegerSpew(js::JSpew_Insns,
467                        IPFX "addl       %d, %s0x%x(%s)\n", MAYBE_PAD,
468                        imm, PRETTY_PRINT_OFFSET(offset), nameIReg(8,base));
469         if (CAN_SIGN_EXTEND_8_32(imm)) {
470             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, offset);
471             m_formatter.immediate8(imm);
472         } else {
473             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, offset);
474             m_formatter.immediate32(imm);
475         }
476     }
477
478 #if WTF_CPU_X86_64
479     void addq_rr(RegisterID src, RegisterID dst)
480     {
481         FIXME_INSN_PRINTING;
482         m_formatter.oneByteOp64(OP_ADD_EvGv, src, dst);
483     }
484
485     void addq_ir(int imm, RegisterID dst)
486     {
487         js::JaegerSpew(js::JSpew_Insns,
488                        IPFX "addq       $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(8,dst));
489         if (CAN_SIGN_EXTEND_8_32(imm)) {
490             m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_ADD, dst);
491             m_formatter.immediate8(imm);
492         } else {
493             m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_ADD, dst);
494             m_formatter.immediate32(imm);
495         }
496     }
497
498     void addq_im(int imm, int offset, RegisterID base)
499     {
500         js::JaegerSpew(js::JSpew_Insns,
501                        IPFX "addq       $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
502                        imm, PRETTY_PRINT_OFFSET(offset), nameIReg(8,base));
503         if (CAN_SIGN_EXTEND_8_32(imm)) {
504             m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, offset);
505             m_formatter.immediate8(imm);
506         } else {
507             m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, offset);
508             m_formatter.immediate32(imm);
509         }
510     }
511 #else
512     void addl_im(int imm, void* addr)
513     {
514         FIXME_INSN_PRINTING;
515         if (CAN_SIGN_EXTEND_8_32(imm)) {
516             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, addr);
517             m_formatter.immediate8(imm);
518         } else {
519             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, addr);
520             m_formatter.immediate32(imm);
521         }
522     }
523 #endif
524
525     void andl_rr(RegisterID src, RegisterID dst)
526     {
527         js::JaegerSpew(js::JSpew_Insns,
528                        IPFX "andl       %s, %s\n", MAYBE_PAD,
529                        nameIReg(4,src), nameIReg(4,dst));
530         m_formatter.oneByteOp(OP_AND_EvGv, src, dst);
531     }
532
533     void andl_mr(int offset, RegisterID base, RegisterID dst)
534     {
535         FIXME_INSN_PRINTING;
536         m_formatter.oneByteOp(OP_AND_GvEv, dst, base, offset);
537     }
538
539     void andl_rm(RegisterID src, int offset, RegisterID base)
540     {
541         FIXME_INSN_PRINTING;
542         m_formatter.oneByteOp(OP_AND_EvGv, src, base, offset);
543     }
544
545     void andl_ir(int imm, RegisterID dst)
546     {
547         js::JaegerSpew(js::JSpew_Insns,
548                        IPFX "andl       $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(4,dst));
549         if (CAN_SIGN_EXTEND_8_32(imm)) {
550             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, dst);
551             m_formatter.immediate8(imm);
552         } else {
553             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, dst);
554             m_formatter.immediate32(imm);
555         }
556     }
557
558     void andl_im(int imm, int offset, RegisterID base)
559     {
560         FIXME_INSN_PRINTING;
561         if (CAN_SIGN_EXTEND_8_32(imm)) {
562             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, base, offset);
563             m_formatter.immediate8(imm);
564         } else {
565             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, base, offset);
566             m_formatter.immediate32(imm);
567         }
568     }
569
570 #if WTF_CPU_X86_64
571     void andq_rr(RegisterID src, RegisterID dst)
572     {
573         js::JaegerSpew(js::JSpew_Insns,
574                        IPFX "andq       %s, %s\n", MAYBE_PAD,
575                        nameIReg(8,src), nameIReg(8,dst));
576         m_formatter.oneByteOp64(OP_AND_EvGv, src, dst);
577     }
578
579     void andq_mr(int offset, RegisterID base, RegisterID dst)
580     {
581         js::JaegerSpew(js::JSpew_Insns,
582                        IPFX "andq       %s0x%x(%s), %s\n", MAYBE_PAD,
583                        PRETTY_PRINT_OFFSET(offset), nameIReg(8,base), nameIReg(8,dst));
584         m_formatter.oneByteOp64(OP_AND_GvEv, dst, base, offset);
585     }
586
587     void orq_mr(int offset, RegisterID base, RegisterID dst)
588     {
589         js::JaegerSpew(js::JSpew_Insns,
590                        IPFX "orq        %s0x%x(%s), %s\n", MAYBE_PAD,
591                        PRETTY_PRINT_OFFSET(offset), nameIReg(8,base), nameIReg(8,dst));
592         m_formatter.oneByteOp64(OP_OR_GvEv, dst, base, offset);
593     }
594
595     void andq_ir(int imm, RegisterID dst)
596     {
597         js::JaegerSpew(js::JSpew_Insns,
598                        IPFX "andq       $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(8,dst));
599         if (CAN_SIGN_EXTEND_8_32(imm)) {
600             m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_AND, dst);
601             m_formatter.immediate8(imm);
602         } else {
603             m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_AND, dst);
604             m_formatter.immediate32(imm);
605         }
606     }
607 #else
608     void andl_im(int imm, void* addr)
609     {
610         FIXME_INSN_PRINTING;
611         if (CAN_SIGN_EXTEND_8_32(imm)) {
612             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, addr);
613             m_formatter.immediate8(imm);
614         } else {
615             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, addr);
616             m_formatter.immediate32(imm);
617         }
618     }
619 #endif
620
621     void negl_r(RegisterID dst)
622     {
623         js::JaegerSpew(js::JSpew_Insns,
624                        IPFX "negl       %s\n", MAYBE_PAD, nameIReg(4,dst));
625         m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NEG, dst);
626     }
627
628     void negl_m(int offset, RegisterID base)
629     {
630         FIXME_INSN_PRINTING;
631         m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NEG, base, offset);
632     }
633
634     void notl_r(RegisterID dst)
635     {
636         js::JaegerSpew(js::JSpew_Insns,
637                        IPFX "notl       %s\n", MAYBE_PAD, nameIReg(4,dst));
638         m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NOT, dst);
639     }
640
641     void notl_m(int offset, RegisterID base)
642     {
643         FIXME_INSN_PRINTING;
644         m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NOT, base, offset);
645     }
646
647     void orl_rr(RegisterID src, RegisterID dst)
648     {
649         js::JaegerSpew(js::JSpew_Insns,
650                        IPFX "orl        %s, %s\n", MAYBE_PAD,
651                        nameIReg(4,src), nameIReg(4,dst));
652         m_formatter.oneByteOp(OP_OR_EvGv, src, dst);
653     }
654
655     void orl_mr(int offset, RegisterID base, RegisterID dst)
656     {
657         FIXME_INSN_PRINTING;
658         m_formatter.oneByteOp(OP_OR_GvEv, dst, base, offset);
659     }
660
661     void orl_rm(RegisterID src, int offset, RegisterID base)
662     {
663         FIXME_INSN_PRINTING;
664         m_formatter.oneByteOp(OP_OR_EvGv, src, base, offset);
665     }
666
667     void orl_ir(int imm, RegisterID dst)
668     {
669         js::JaegerSpew(js::JSpew_Insns,
670                        IPFX "orl        $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(4,dst));
671         if (CAN_SIGN_EXTEND_8_32(imm)) {
672             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, dst);
673             m_formatter.immediate8(imm);
674         } else {
675             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, dst);
676             m_formatter.immediate32(imm);
677         }
678     }
679
680     void orl_im(int imm, int offset, RegisterID base)
681     {
682         FIXME_INSN_PRINTING;
683         if (CAN_SIGN_EXTEND_8_32(imm)) {
684             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, base, offset);
685             m_formatter.immediate8(imm);
686         } else {
687             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, base, offset);
688             m_formatter.immediate32(imm);
689         }
690     }
691
692 #if WTF_CPU_X86_64
693     void orq_rr(RegisterID src, RegisterID dst)
694     {
695         js::JaegerSpew(js::JSpew_Insns,
696                        IPFX "orq        %s, %s\n", MAYBE_PAD,
697                        nameIReg(8,src), nameIReg(8,dst));
698         m_formatter.oneByteOp64(OP_OR_EvGv, src, dst);
699     }
700
701     void orq_ir(int imm, RegisterID dst)
702     {
703         js::JaegerSpew(js::JSpew_Insns,
704                        IPFX "orq        $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(8,dst));
705         if (CAN_SIGN_EXTEND_8_32(imm)) {
706             m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_OR, dst);
707             m_formatter.immediate8(imm);
708         } else {
709             m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_OR, dst);
710             m_formatter.immediate32(imm);
711         }
712     }
713
714     void notq_r(RegisterID dst)
715     {
716         js::JaegerSpew(js::JSpew_Insns,
717                        IPFX "notq       %s\n", MAYBE_PAD, nameIReg(8,dst));
718         m_formatter.oneByteOp64(OP_GROUP3_Ev, GROUP3_OP_NOT, dst);
719     }
720 #else
721     void orl_im(int imm, void* addr)
722     {
723         FIXME_INSN_PRINTING;
724         if (CAN_SIGN_EXTEND_8_32(imm)) {
725             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, addr);
726             m_formatter.immediate8(imm);
727         } else {
728             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, addr);
729             m_formatter.immediate32(imm);
730         }
731     }
732 #endif
733
734     void subl_rr(RegisterID src, RegisterID dst)
735     {
736         js::JaegerSpew(js::JSpew_Insns,
737                        IPFX "subl       %s, %s\n", MAYBE_PAD,
738                        nameIReg(4,src), nameIReg(4,dst));
739         m_formatter.oneByteOp(OP_SUB_EvGv, src, dst);
740     }
741
742     void subl_mr(int offset, RegisterID base, RegisterID dst)
743     {
744         FIXME_INSN_PRINTING;
745         m_formatter.oneByteOp(OP_SUB_GvEv, dst, base, offset);
746     }
747
748     void subl_rm(RegisterID src, int offset, RegisterID base)
749     {
750         FIXME_INSN_PRINTING;
751         m_formatter.oneByteOp(OP_SUB_EvGv, src, base, offset);
752     }
753
754     void subl_ir(int imm, RegisterID dst)
755     {
756         js::JaegerSpew(js::JSpew_Insns,
757                        IPFX "subl       $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(4, dst));
758         if (CAN_SIGN_EXTEND_8_32(imm)) {
759             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, dst);
760             m_formatter.immediate8(imm);
761         } else {
762             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, dst);
763             m_formatter.immediate32(imm);
764         }
765     }
766     
767     void subl_im(int imm, int offset, RegisterID base)
768     {
769         js::JaegerSpew(js::JSpew_Insns,
770                        IPFX "subl       $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
771                        imm, PRETTY_PRINT_OFFSET(offset), nameIReg(4, base));
772         if (CAN_SIGN_EXTEND_8_32(imm)) {
773             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, base, offset);
774             m_formatter.immediate8(imm);
775         } else {
776             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, base, offset);
777             m_formatter.immediate32(imm);
778         }
779     }
780
781 #if WTF_CPU_X86_64
782     void subq_rr(RegisterID src, RegisterID dst)
783     {
784         FIXME_INSN_PRINTING;
785         m_formatter.oneByteOp64(OP_SUB_EvGv, src, dst);
786     }
787
788     void subq_ir(int imm, RegisterID dst)
789     {
790         js::JaegerSpew(js::JSpew_Insns,
791                        IPFX "subq       $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(8,dst));
792         if (CAN_SIGN_EXTEND_8_32(imm)) {
793             m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_SUB, dst);
794             m_formatter.immediate8(imm);
795         } else {
796             m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_SUB, dst);
797             m_formatter.immediate32(imm);
798         }
799     }
800 #else
801     void subl_im(int imm, void* addr)
802     {
803         FIXME_INSN_PRINTING;
804         if (CAN_SIGN_EXTEND_8_32(imm)) {
805             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, addr);
806             m_formatter.immediate8(imm);
807         } else {
808             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, addr);
809             m_formatter.immediate32(imm);
810         }
811     }
812 #endif
813
814     void xorl_rr(RegisterID src, RegisterID dst)
815     {
816         js::JaegerSpew(js::JSpew_Insns,
817                        IPFX "xorl       %s, %s\n", MAYBE_PAD,
818                        nameIReg(4,src), nameIReg(4,dst));
819         m_formatter.oneByteOp(OP_XOR_EvGv, src, dst);
820     }
821
822     void xorl_mr(int offset, RegisterID base, RegisterID dst)
823     {
824         FIXME_INSN_PRINTING;
825         m_formatter.oneByteOp(OP_XOR_GvEv, dst, base, offset);
826     }
827
828     void xorl_rm(RegisterID src, int offset, RegisterID base)
829     {
830         FIXME_INSN_PRINTING;
831         m_formatter.oneByteOp(OP_XOR_EvGv, src, base, offset);
832     }
833
834     void xorl_im(int imm, int offset, RegisterID base)
835     {
836         FIXME_INSN_PRINTING;
837         if (CAN_SIGN_EXTEND_8_32(imm)) {
838             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_XOR, base, offset);
839             m_formatter.immediate8(imm);
840         } else {
841             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_XOR, base, offset);
842             m_formatter.immediate32(imm);
843         }
844     }
845
846     void xorl_ir(int imm, RegisterID dst)
847     {
848         js::JaegerSpew(js::JSpew_Insns,
849                        IPFX "xorl       %d, %s\n", MAYBE_PAD,
850                        imm, nameIReg(4,dst));
851         if (CAN_SIGN_EXTEND_8_32(imm)) {
852             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_XOR, dst);
853             m_formatter.immediate8(imm);
854         } else {
855             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_XOR, dst);
856             m_formatter.immediate32(imm);
857         }
858     }
859
860 #if WTF_CPU_X86_64
861     void xorq_rr(RegisterID src, RegisterID dst)
862     {
863         js::JaegerSpew(js::JSpew_Insns,
864                        IPFX "xorq       %s, %s\n", MAYBE_PAD,
865                        nameIReg(8,src), nameIReg(8, dst));
866         m_formatter.oneByteOp64(OP_XOR_EvGv, src, dst);
867     }
868
869     void xorq_ir(int imm, RegisterID dst)
870     {
871         js::JaegerSpew(js::JSpew_Insns,
872                        IPFX "xorq       %d, %s\n", MAYBE_PAD,
873                        imm, nameIReg(8,dst));
874         if (CAN_SIGN_EXTEND_8_32(imm)) {
875             m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_XOR, dst);
876             m_formatter.immediate8(imm);
877         } else {
878             m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_XOR, dst);
879             m_formatter.immediate32(imm);
880         }
881     }
882 #endif
883
884     void sarl_i8r(int imm, RegisterID dst)
885     {
886         js::JaegerSpew(js::JSpew_Insns,
887                        IPFX "sarl       $%d, %s\n", MAYBE_PAD, imm, nameIReg(4, dst));
888         if (imm == 1)
889             m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SAR, dst);
890         else {
891             m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SAR, dst);
892             m_formatter.immediate8(imm);
893         }
894     }
895
896     void sarl_CLr(RegisterID dst)
897     {
898         js::JaegerSpew(js::JSpew_Insns,
899                        IPFX "sarl       %%cl, %s\n", MAYBE_PAD, nameIReg(4, dst));
900         m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
901     }
902     
903     void shrl_i8r(int imm, RegisterID dst)
904     {
905         if (imm == 1)
906             m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SHR, dst);
907         else {
908             m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SHR, dst);
909             m_formatter.immediate8(imm);
910         }
911     }
912     
913     void shrl_CLr(RegisterID dst)
914     {
915         m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHR, dst);
916     }
917
918     void shll_i8r(int imm, RegisterID dst)
919     {
920         js::JaegerSpew(js::JSpew_Insns,
921                        IPFX "shll       $%d, %s\n", MAYBE_PAD, imm, nameIReg(4, dst));
922         if (imm == 1)
923             m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SHL, dst);
924         else {
925             m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SHL, dst);
926             m_formatter.immediate8(imm);
927         }
928     }
929
930     void shll_CLr(RegisterID dst)
931     {
932         js::JaegerSpew(js::JSpew_Insns,
933                        IPFX "shll       %%cl, %s\n", MAYBE_PAD, nameIReg(4, dst));
934         m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst);
935     }
936
937 #if WTF_CPU_X86_64
938     void sarq_CLr(RegisterID dst)
939     {
940         FIXME_INSN_PRINTING;
941         m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
942     }
943
944     void sarq_i8r(int imm, RegisterID dst)
945     {
946         js::JaegerSpew(js::JSpew_Insns,
947                        IPFX "sarq       $%d, %s\n", MAYBE_PAD, imm, nameIReg(8, dst));
948         if (imm == 1)
949             m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_SAR, dst);
950         else {
951             m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_SAR, dst);
952             m_formatter.immediate8(imm);
953         }
954     }
955
956     void shlq_i8r(int imm, RegisterID dst)
957     {
958         js::JaegerSpew(js::JSpew_Insns,
959                        IPFX "shlq       $%d, %s\n", MAYBE_PAD, imm, nameIReg(8, dst));
960         if (imm == 1)
961             m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_SHL, dst);
962         else {
963             m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_SHL, dst);
964             m_formatter.immediate8(imm);
965         }
966     }
967 #endif
968
969     void imull_rr(RegisterID src, RegisterID dst)
970     {
971         js::JaegerSpew(js::JSpew_Insns,
972                        IPFX "imull       %s, %s\n", MAYBE_PAD, nameIReg(4,src), nameIReg(4, dst));
973         m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, src);
974     }
975
976     void imull_mr(int offset, RegisterID base, RegisterID dst)
977     {
978         FIXME_INSN_PRINTING;
979         m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, base, offset);
980     }
981
982     void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
983     {
984         FIXME_INSN_PRINTING;
985         m_formatter.oneByteOp(OP_IMUL_GvEvIz, dst, src);
986         m_formatter.immediate32(value);
987     }
988
989     void idivl_r(RegisterID dst)
990     {
991         js::JaegerSpew(js::JSpew_Insns,
992                        IPFX "idivl      %s\n", MAYBE_PAD, 
993                        nameIReg(4, dst));
994         m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_IDIV, dst);
995     }
996
997     // Comparisons:
998
999     void cmpl_rr(RegisterID src, RegisterID dst)
1000     {
1001         js::JaegerSpew(js::JSpew_Insns,
1002                        IPFX "cmpl       %s, %s\n", MAYBE_PAD, 
1003                        nameIReg(4, src), nameIReg(4, dst));
1004         m_formatter.oneByteOp(OP_CMP_EvGv, src, dst);
1005     }
1006
1007     void cmpl_rm(RegisterID src, int offset, RegisterID base)
1008     {
1009         js::JaegerSpew(js::JSpew_Insns,
1010                        IPFX "cmpl       %s, %s0x%x(%s)\n", MAYBE_PAD, 
1011                        nameIReg(4, src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1012         m_formatter.oneByteOp(OP_CMP_EvGv, src, base, offset);
1013     }
1014
1015     void cmpl_mr(int offset, RegisterID base, RegisterID src)
1016     {
1017         js::JaegerSpew(js::JSpew_Insns,
1018                        IPFX "cmpl       %s0x%x(%s), %s\n", MAYBE_PAD, 
1019                        PRETTY_PRINT_OFFSET(offset), nameIReg(4, base), nameIReg(src));
1020         m_formatter.oneByteOp(OP_CMP_GvEv, src, base, offset);
1021     }
1022
1023     void cmpl_ir(int imm, RegisterID dst)
1024     {
1025         js::JaegerSpew(js::JSpew_Insns,
1026                        IPFX "cmpl       $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(4, dst));
1027         if (CAN_SIGN_EXTEND_8_32(imm)) {
1028             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, dst);
1029             m_formatter.immediate8(imm);
1030         } else {
1031             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
1032             m_formatter.immediate32(imm);
1033         }
1034     }
1035
1036     void cmpl_ir_force32(int imm, RegisterID dst)
1037     {
1038         js::JaegerSpew(js::JSpew_Insns,
1039                        IPFX "cmpl       $0x%x, %s\n", MAYBE_PAD, imm, nameIReg(4, dst));
1040         m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
1041         m_formatter.immediate32(imm);
1042     }
1043     
1044     void cmpl_im(int imm, int offset, RegisterID base)
1045     {
1046         js::JaegerSpew(js::JSpew_Insns,
1047                        IPFX "cmpl       $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
1048                        imm, PRETTY_PRINT_OFFSET(offset), nameIReg(4,base));
1049         if (CAN_SIGN_EXTEND_8_32(imm)) {
1050             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, offset);
1051             m_formatter.immediate8(imm);
1052         } else {
1053             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset);
1054             m_formatter.immediate32(imm);
1055         }
1056     }
1057     
1058     void cmpb_im(int imm, int offset, RegisterID base)
1059     {
1060         m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, base, offset);
1061         m_formatter.immediate8(imm);
1062     }
1063     
1064     void cmpb_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
1065     {
1066         m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, base, index, scale, offset);
1067         m_formatter.immediate8(imm);
1068     }
1069
1070     void cmpl_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
1071     {
1072         js::JaegerSpew(js::JSpew_Insns,
1073                        IPFX "cmpl       %d, %d(%s,%s,%d)\n", MAYBE_PAD,
1074                        imm, offset, nameIReg(4,base), nameIReg(4,index), scale);
1075         if (CAN_SIGN_EXTEND_8_32(imm)) {
1076             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset);
1077             m_formatter.immediate8(imm);
1078         } else {
1079             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset);
1080             m_formatter.immediate32(imm);
1081         }
1082     }
1083
1084     void cmpl_im_force32(int imm, int offset, RegisterID base)
1085     {
1086         FIXME_INSN_PRINTING;
1087         m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset);
1088         m_formatter.immediate32(imm);
1089     }
1090
1091 #if WTF_CPU_X86_64
1092     void cmpq_rr(RegisterID src, RegisterID dst)
1093     {
1094         js::JaegerSpew(js::JSpew_Insns,
1095                        IPFX "cmpq       %s, %s\n", MAYBE_PAD,
1096                        nameIReg(8, src), nameIReg(8, dst));
1097         m_formatter.oneByteOp64(OP_CMP_EvGv, src, dst);
1098     }
1099
1100     void cmpq_rm(RegisterID src, int offset, RegisterID base)
1101     {
1102         js::JaegerSpew(js::JSpew_Insns,
1103                        IPFX "cmpq       %s, %d(%s)\n", MAYBE_PAD,
1104                        nameIReg(8, src), offset, nameIReg(8, base));
1105         m_formatter.oneByteOp64(OP_CMP_EvGv, src, base, offset);
1106     }
1107
1108     void cmpq_mr(int offset, RegisterID base, RegisterID src)
1109     {
1110         js::JaegerSpew(js::JSpew_Insns,
1111                        IPFX "cmpq       %d(%s), %s\n", MAYBE_PAD,
1112                        offset, nameIReg(8, base), nameIReg(8, src));
1113         m_formatter.oneByteOp64(OP_CMP_GvEv, src, base, offset);
1114     }
1115
1116     void cmpq_ir(int imm, RegisterID dst)
1117     {
1118         js::JaegerSpew(js::JSpew_Insns,
1119                        IPFX "cmpq       %d, %s\n", MAYBE_PAD,
1120                        imm, nameIReg(8, dst));
1121         if (CAN_SIGN_EXTEND_8_32(imm)) {
1122             m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, dst);
1123             m_formatter.immediate8(imm);
1124         } else {
1125             m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
1126             m_formatter.immediate32(imm);
1127         }
1128     }
1129
1130     void cmpq_im(int imm, int offset, RegisterID base)
1131     {
1132         FIXME_INSN_PRINTING;
1133         if (CAN_SIGN_EXTEND_8_32(imm)) {
1134             m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, offset);
1135             m_formatter.immediate8(imm);
1136         } else {
1137             m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset);
1138             m_formatter.immediate32(imm);
1139         }
1140     }
1141
1142     void cmpq_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
1143     {
1144         FIXME_INSN_PRINTING;
1145         if (CAN_SIGN_EXTEND_8_32(imm)) {
1146             m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset);
1147             m_formatter.immediate8(imm);
1148         } else {
1149             m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset);
1150             m_formatter.immediate32(imm);
1151         }
1152     }
1153 #else
1154     void cmpl_rm(RegisterID reg, void* addr)
1155     {
1156         FIXME_INSN_PRINTING;
1157         m_formatter.oneByteOp(OP_CMP_EvGv, reg, addr);
1158     }
1159
1160     void cmpl_im(int imm, void* addr)
1161     {
1162         FIXME_INSN_PRINTING;
1163         if (CAN_SIGN_EXTEND_8_32(imm)) {
1164             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, addr);
1165             m_formatter.immediate8(imm);
1166         } else {
1167             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, addr);
1168             m_formatter.immediate32(imm);
1169         }
1170     }
1171 #endif
1172
1173     void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1174     {
1175         FIXME_INSN_PRINTING;
1176         m_formatter.prefix(PRE_OPERAND_SIZE);
1177         m_formatter.oneByteOp(OP_CMP_EvGv, src, base, index, scale, offset);
1178     }
1179
1180     void cmpw_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
1181     {
1182         FIXME_INSN_PRINTING;
1183         if (CAN_SIGN_EXTEND_8_32(imm)) {
1184             m_formatter.prefix(PRE_OPERAND_SIZE);
1185             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset);
1186             m_formatter.immediate8(imm);
1187         } else {
1188             m_formatter.prefix(PRE_OPERAND_SIZE);
1189             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset);
1190             m_formatter.immediate16(imm);
1191         }
1192     }
1193
1194     void testl_rr(RegisterID src, RegisterID dst)
1195     {
1196         js::JaegerSpew(js::JSpew_Insns,
1197                        IPFX "testl      %s, %s\n", MAYBE_PAD,
1198                        nameIReg(4,src), nameIReg(4,dst));
1199         m_formatter.oneByteOp(OP_TEST_EvGv, src, dst);
1200     }
1201     
1202     void testl_i32r(int imm, RegisterID dst)
1203     {
1204         js::JaegerSpew(js::JSpew_Insns,
1205                        IPFX "testl      $0x%x, %s\n", MAYBE_PAD,
1206                        imm, nameIReg(dst));
1207         m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, dst);
1208         m_formatter.immediate32(imm);
1209     }
1210
1211     void testl_i32m(int imm, int offset, RegisterID base)
1212     {
1213         js::JaegerSpew(js::JSpew_Insns,
1214                        IPFX "testl      $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
1215                        imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1216         m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset);
1217         m_formatter.immediate32(imm);
1218     }
1219     
1220     void testb_im(int imm, int offset, RegisterID base)
1221     {
1222         m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, base, offset);
1223         m_formatter.immediate8(imm);
1224     }
1225     
1226     void testb_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
1227     {
1228         m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, base, index, scale, offset);
1229         m_formatter.immediate8(imm);
1230     }
1231
1232     void testl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1233     {
1234         FIXME_INSN_PRINTING;
1235         m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset);
1236         m_formatter.immediate32(imm);
1237     }
1238
1239 #if WTF_CPU_X86_64
1240     void testq_rr(RegisterID src, RegisterID dst)
1241     {
1242         js::JaegerSpew(js::JSpew_Insns,
1243                        IPFX "testq      %s, %s\n", MAYBE_PAD,
1244                        nameIReg(8,src), nameIReg(8,dst));
1245         m_formatter.oneByteOp64(OP_TEST_EvGv, src, dst);
1246     }
1247
1248     void testq_i32r(int imm, RegisterID dst)
1249     {
1250         FIXME_INSN_PRINTING;
1251         m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, dst);
1252         m_formatter.immediate32(imm);
1253     }
1254
1255     void testq_i32m(int imm, int offset, RegisterID base)
1256     {
1257         js::JaegerSpew(js::JSpew_Insns,
1258                        IPFX "testq      $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
1259                        imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1260         m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset);
1261         m_formatter.immediate32(imm);
1262     }
1263
1264     void testq_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1265     {
1266         FIXME_INSN_PRINTING;
1267         m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset);
1268         m_formatter.immediate32(imm);
1269     }
1270 #endif 
1271
1272     void testw_rr(RegisterID src, RegisterID dst)
1273     {
1274         FIXME_INSN_PRINTING;
1275         m_formatter.prefix(PRE_OPERAND_SIZE);
1276         m_formatter.oneByteOp(OP_TEST_EvGv, src, dst);
1277     }
1278     
1279     void testb_i8r(int imm, RegisterID dst)
1280     {
1281         js::JaegerSpew(js::JSpew_Insns,
1282                        IPFX "testb      $0x%x, %s\n", MAYBE_PAD,
1283                        imm, nameIReg(1,dst));
1284         m_formatter.oneByteOp8(OP_GROUP3_EbIb, GROUP3_OP_TEST, dst);
1285         m_formatter.immediate8(imm);
1286     }
1287
1288     void setCC_r(Condition cond, RegisterID dst)
1289     {
1290         js::JaegerSpew(js::JSpew_Insns,
1291                        IPFX "set%s      %s\n", MAYBE_PAD,
1292                        nameCC(cond), nameIReg(1,dst));
1293         m_formatter.twoByteOp8(setccOpcode(cond), (GroupOpcodeID)0, dst);
1294     }
1295
1296     void sete_r(RegisterID dst)
1297     {
1298         FIXME_INSN_PRINTING;
1299         m_formatter.twoByteOp8(setccOpcode(ConditionE), (GroupOpcodeID)0, dst);
1300     }
1301
1302     void setz_r(RegisterID dst)
1303     {
1304         FIXME_INSN_PRINTING;
1305         sete_r(dst);
1306     }
1307
1308     void setne_r(RegisterID dst)
1309     {
1310         FIXME_INSN_PRINTING;
1311         m_formatter.twoByteOp8(setccOpcode(ConditionNE), (GroupOpcodeID)0, dst);
1312     }
1313
1314     void setnz_r(RegisterID dst)
1315     {
1316         FIXME_INSN_PRINTING;
1317         setne_r(dst);
1318     }
1319
1320     // Various move ops:
1321
1322     void cdq()
1323     {
1324         js::JaegerSpew(js::JSpew_Insns,
1325                        IPFX "cdq              \n", MAYBE_PAD);
1326         m_formatter.oneByteOp(OP_CDQ);
1327     }
1328
1329     void xchgl_rr(RegisterID src, RegisterID dst)
1330     {
1331         js::JaegerSpew(js::JSpew_Insns,
1332                        IPFX "xchgl      %s, %s\n", MAYBE_PAD,
1333                        nameIReg(4,src), nameIReg(4,dst));
1334         m_formatter.oneByteOp(OP_XCHG_EvGv, src, dst);
1335     }
1336
1337 #if WTF_CPU_X86_64
1338     void xchgq_rr(RegisterID src, RegisterID dst)
1339     {
1340         js::JaegerSpew(js::JSpew_Insns,
1341                        IPFX "xchgq      %s, %s\n", MAYBE_PAD,
1342                        nameIReg(8,src), nameIReg(8,dst));
1343         m_formatter.oneByteOp64(OP_XCHG_EvGv, src, dst);
1344     }
1345 #endif
1346
1347     void movl_rr(RegisterID src, RegisterID dst)
1348     {
1349         js::JaegerSpew(js::JSpew_Insns,
1350                        IPFX "movl       %s, %s\n", MAYBE_PAD,
1351                        nameIReg(4,src), nameIReg(4,dst));
1352         m_formatter.oneByteOp(OP_MOV_EvGv, src, dst);
1353     }
1354
1355     void movw_rm(RegisterID src, int offset, RegisterID base)
1356     {
1357         js::JaegerSpew(js::JSpew_Insns,
1358                        IPFX "movw       %s, %s0x%x(%s)\n", MAYBE_PAD,
1359                        nameIReg(2,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1360         m_formatter.prefix(PRE_OPERAND_SIZE);
1361         m_formatter.oneByteOp(OP_MOV_EvGv, src, base, offset);
1362     }
1363     
1364     void movl_rm(RegisterID src, int offset, RegisterID base)
1365     {
1366         js::JaegerSpew(js::JSpew_Insns,
1367                        IPFX "movl       %s, %s0x%x(%s)\n", MAYBE_PAD,
1368                        nameIReg(4,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1369         m_formatter.oneByteOp(OP_MOV_EvGv, src, base, offset);
1370     }
1371
1372     void movl_rm_disp32(RegisterID src, int offset, RegisterID base)
1373     {
1374         FIXME_INSN_PRINTING;
1375         m_formatter.oneByteOp_disp32(OP_MOV_EvGv, src, base, offset);
1376     }
1377
1378     void movw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1379     {
1380         js::JaegerSpew(js::JSpew_Insns,
1381                        IPFX "movw       %s, %d(%s,%s,%d)\n", MAYBE_PAD, 
1382                        nameIReg(2, src), offset, nameIReg(base), nameIReg(index), scale);
1383         m_formatter.prefix(PRE_OPERAND_SIZE);
1384         m_formatter.oneByteOp(OP_MOV_EvGv, src, base, index, scale, offset);
1385     }
1386
1387     void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1388     {
1389         js::JaegerSpew(js::JSpew_Insns,
1390                        IPFX "movl       %s, %d(%s,%s,%d)\n", MAYBE_PAD, 
1391                        nameIReg(4, src), offset, nameIReg(base), nameIReg(index), scale);
1392         m_formatter.oneByteOp(OP_MOV_EvGv, src, base, index, scale, offset);
1393     }
1394     
1395     void movl_mEAX(void* addr)
1396     {
1397         FIXME_INSN_PRINTING;
1398         m_formatter.oneByteOp(OP_MOV_EAXOv);
1399 #if WTF_CPU_X86_64
1400         m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
1401 #else
1402         m_formatter.immediate32(reinterpret_cast<int>(addr));
1403 #endif
1404     }
1405
1406     void movl_mr(int offset, RegisterID base, RegisterID dst)
1407     {
1408         js::JaegerSpew(js::JSpew_Insns,
1409                        IPFX "movl       %s0x%x(%s), %s\n", MAYBE_PAD,
1410                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4, dst));
1411         m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, offset);
1412     }
1413
1414     void movl_mr_disp32(int offset, RegisterID base, RegisterID dst)
1415     {
1416         FIXME_INSN_PRINTING;
1417         m_formatter.oneByteOp_disp32(OP_MOV_GvEv, dst, base, offset);
1418     }
1419
1420     void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1421     {
1422         js::JaegerSpew(js::JSpew_Insns,
1423                        IPFX "movl       %d(%s,%s,%d), %s\n", MAYBE_PAD,
1424                        offset, nameIReg(base), nameIReg(index), scale, nameIReg(4, dst));
1425         m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, index, scale, offset);
1426     }
1427
1428     void movl_i32r(int imm, RegisterID dst)
1429     {
1430         js::JaegerSpew(js::JSpew_Insns,
1431                        IPFX "movl       $0x%x, %s\n", MAYBE_PAD,
1432                        imm, nameIReg(dst));
1433         m_formatter.oneByteOp(OP_MOV_EAXIv, dst);
1434         m_formatter.immediate32(imm);
1435     }
1436
1437     void movb_i8m(int imm, int offset, RegisterID base)
1438     {
1439         js::JaegerSpew(js::JSpew_Insns,
1440                        IPFX "movb       $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
1441                        imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1442         m_formatter.oneByteOp(OP_GROUP11_EvIb, GROUP11_MOV, base, offset);
1443         m_formatter.immediate8(imm);
1444     }
1445
1446     void movb_i8m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1447     {
1448         js::JaegerSpew(js::JSpew_Insns,
1449                        IPFX "movb       $0x%x, %d(%s,%s,%d)\n", MAYBE_PAD,
1450                        imm, offset, nameIReg(base), nameIReg(index), scale);
1451         m_formatter.oneByteOp(OP_GROUP11_EvIb, GROUP11_MOV, base, index, scale, offset);
1452         m_formatter.immediate8(imm);
1453     }
1454
1455     void movw_i16m(int imm, int offset, RegisterID base)
1456     {
1457         js::JaegerSpew(js::JSpew_Insns,
1458                        IPFX "movw       $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
1459                        imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1460         m_formatter.prefix(PRE_OPERAND_SIZE);
1461         m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, offset);
1462         m_formatter.immediate16(imm);
1463     }
1464
1465     void movl_i32m(int imm, int offset, RegisterID base)
1466     {
1467         js::JaegerSpew(js::JSpew_Insns,
1468                        IPFX "movl       $0x%x, %s0x%x(%s)\n", MAYBE_PAD,
1469                        imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1470         m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, offset);
1471         m_formatter.immediate32(imm);
1472     }
1473
1474     void movw_i16m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1475     {
1476         js::JaegerSpew(js::JSpew_Insns,
1477                        IPFX "movw       $0x%x, %d(%s,%s,%d)\n", MAYBE_PAD,
1478                        imm, offset, nameIReg(base), nameIReg(index), scale);
1479         m_formatter.prefix(PRE_OPERAND_SIZE);
1480         m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, index, scale, offset);
1481         m_formatter.immediate16(imm);
1482     }
1483
1484     void movl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1485     {
1486         js::JaegerSpew(js::JSpew_Insns,
1487                        IPFX "movl       $0x%x, %d(%s,%s,%d)\n", MAYBE_PAD,
1488                        imm, offset, nameIReg(base), nameIReg(index), scale);
1489         m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, index, scale, offset);
1490         m_formatter.immediate32(imm);
1491     }
1492
1493     void movl_EAXm(void* addr)
1494     {
1495         FIXME_INSN_PRINTING;
1496         m_formatter.oneByteOp(OP_MOV_OvEAX);
1497 #if WTF_CPU_X86_64
1498         m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
1499 #else
1500         m_formatter.immediate32(reinterpret_cast<int>(addr));
1501 #endif
1502     }
1503
1504 #if WTF_CPU_X86_64
1505     void movq_rr(RegisterID src, RegisterID dst)
1506     {
1507         js::JaegerSpew(js::JSpew_Insns,
1508                        IPFX "movq       %s, %s\n", MAYBE_PAD,
1509                        nameIReg(8,src), nameIReg(8,dst));
1510         m_formatter.oneByteOp64(OP_MOV_EvGv, src, dst);
1511     }
1512
1513     void movq_rm(RegisterID src, int offset, RegisterID base)
1514     {
1515         js::JaegerSpew(js::JSpew_Insns,
1516                        IPFX "movq       %s, %s0x%x(%s)\n", MAYBE_PAD,
1517                        nameIReg(8,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1518         m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, offset);
1519     }
1520
1521     void movq_rm_disp32(RegisterID src, int offset, RegisterID base)
1522     {
1523         FIXME_INSN_PRINTING;
1524         m_formatter.oneByteOp64_disp32(OP_MOV_EvGv, src, base, offset);
1525     }
1526
1527     void movq_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1528     {
1529         js::JaegerSpew(js::JSpew_Insns,
1530                        IPFX "movq       %s, %s0x%x(%s)\n", MAYBE_PAD,
1531                        nameIReg(8,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1532         m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, index, scale, offset);
1533     }
1534
1535     void movq_mEAX(void* addr)
1536     {
1537         FIXME_INSN_PRINTING;
1538         m_formatter.oneByteOp64(OP_MOV_EAXOv);
1539         m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
1540     }
1541
1542     void movq_EAXm(void* addr)
1543     {
1544         FIXME_INSN_PRINTING;
1545         m_formatter.oneByteOp64(OP_MOV_OvEAX);
1546         m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
1547     }
1548
1549     void movq_mr(int offset, RegisterID base, RegisterID dst)
1550     {
1551         js::JaegerSpew(js::JSpew_Insns,
1552                        IPFX  "movq       %s0x%x(%s), %s\n", MAYBE_PAD,
1553                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(8,dst));
1554         m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, offset);
1555     }
1556
1557     void movq_mr_disp32(int offset, RegisterID base, RegisterID dst)
1558     {
1559         FIXME_INSN_PRINTING;
1560         m_formatter.oneByteOp64_disp32(OP_MOV_GvEv, dst, base, offset);
1561     }
1562
1563     void movq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1564     {
1565         js::JaegerSpew(js::JSpew_Insns,
1566                        IPFX "movq       %s0x%x(%s), %s\n", MAYBE_PAD,
1567                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(8,dst));
1568         m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, index, scale, offset);
1569     }
1570
1571     void leaq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1572     {
1573         js::JaegerSpew(js::JSpew_Insns,
1574                        IPFX "leaq       %d(%s,%s,%d), %s\n", MAYBE_PAD,
1575                        offset, nameIReg(base), nameIReg(index), scale, nameIReg(8,dst)),
1576         m_formatter.oneByteOp64(OP_LEA, dst, base, index, scale, offset);
1577     }
1578
1579     void movq_i32m(int imm, int offset, RegisterID base)
1580     {
1581         js::JaegerSpew(js::JSpew_Insns,
1582                        IPFX  "movq       $%d, %s0x%x(%s)\n", MAYBE_PAD,
1583                        imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1584         m_formatter.oneByteOp64(OP_GROUP11_EvIz, GROUP11_MOV, base, offset);
1585         m_formatter.immediate32(imm);
1586     }
1587
1588     void movq_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1589     {
1590         js::JaegerSpew(js::JSpew_Insns,
1591                        IPFX  "movq       $%d, %s0x%x(%s)\n", MAYBE_PAD,
1592                        imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1593         m_formatter.oneByteOp64(OP_GROUP11_EvIz, GROUP11_MOV, base, index, scale, offset);
1594         m_formatter.immediate32(imm);
1595     }
1596
1597     void movq_i64r(int64_t imm, RegisterID dst)
1598     {
1599         js::JaegerSpew(js::JSpew_Insns,
1600                        IPFX "movabsq    $0x%llx, %s\n", MAYBE_PAD,
1601                        (unsigned long long int)imm, nameIReg(8,dst));
1602         m_formatter.oneByteOp64(OP_MOV_EAXIv, dst);
1603         m_formatter.immediate64(imm);
1604     }
1605     
1606     void movsxd_rr(RegisterID src, RegisterID dst)
1607     {
1608         js::JaegerSpew(js::JSpew_Insns,
1609                        IPFX "movsxd     %s, %s\n", MAYBE_PAD,
1610                        nameIReg(4, src), nameIReg(8, dst));
1611         m_formatter.oneByteOp64(OP_MOVSXD_GvEv, dst, src);
1612     }
1613     
1614     
1615 #else
1616     void movl_rm(RegisterID src, void* addr)
1617     {
1618         FIXME_INSN_PRINTING;
1619         if (src == X86Registers::eax)
1620             movl_EAXm(addr);
1621         else 
1622             m_formatter.oneByteOp(OP_MOV_EvGv, src, addr);
1623     }
1624     
1625     void movl_mr(void* addr, RegisterID dst)
1626     {
1627         js::JaegerSpew(js::JSpew_Insns,
1628                        IPFX "movl       0(%p), %s\n", MAYBE_PAD,
1629                        addr, nameIReg(4, dst));
1630         if (dst == X86Registers::eax)
1631             movl_mEAX(addr);
1632         else
1633             m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
1634     }
1635
1636     void movl_i32m(int imm, void* addr)
1637     {
1638         FIXME_INSN_PRINTING;
1639         m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, addr);
1640         m_formatter.immediate32(imm);
1641     }
1642 #endif
1643
1644     void movb_rm(RegisterID src, int offset, RegisterID base)
1645     {
1646         js::JaegerSpew(js::JSpew_Insns,
1647                        IPFX "movb       %s, %s0x%x(%s)\n", MAYBE_PAD,
1648                        nameIReg(1, src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
1649         m_formatter.oneByteOp8(OP_MOV_EbGv, src, base, offset);
1650     }
1651
1652     void movb_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1653     {
1654         js::JaegerSpew(js::JSpew_Insns,
1655                        IPFX "movb       %s, %d(%s,%s,%d)\n", MAYBE_PAD,
1656                        nameIReg(1, src), offset, nameIReg(base), nameIReg(index), scale);
1657         m_formatter.oneByteOp8(OP_MOV_EbGv, src, base, index, scale, offset);
1658     }
1659
1660     void movzbl_mr(int offset, RegisterID base, RegisterID dst)
1661     {
1662         js::JaegerSpew(js::JSpew_Insns,
1663                        IPFX "movzbl     %s0x%x(%s), %s\n", MAYBE_PAD,
1664                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4, dst));
1665         m_formatter.twoByteOp(OP2_MOVZX_GvEb, dst, base, offset);
1666     }
1667
1668     void movzbl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1669     {
1670         js::JaegerSpew(js::JSpew_Insns,
1671                        IPFX "movzbl     %d(%s,%s,%d), %s\n", MAYBE_PAD,
1672                        offset, nameIReg(base), nameIReg(index), scale, nameIReg(dst));
1673         m_formatter.twoByteOp(OP2_MOVZX_GvEb, dst, base, index, scale, offset);
1674     }
1675
1676     void movxbl_mr(int offset, RegisterID base, RegisterID dst)
1677     {
1678         js::JaegerSpew(js::JSpew_Insns,
1679                        IPFX "movxbl     %s0x%x(%s), %s\n", MAYBE_PAD,
1680                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4, dst));
1681         m_formatter.twoByteOp(OP2_MOVSX_GvEb, dst, base, offset);
1682     }
1683
1684     void movxbl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1685     {
1686         js::JaegerSpew(js::JSpew_Insns,
1687                        IPFX "movxbl     %d(%s,%s,%d), %s\n", MAYBE_PAD,
1688                        offset, nameIReg(base), nameIReg(index), scale, nameIReg(dst));
1689         m_formatter.twoByteOp(OP2_MOVSX_GvEb, dst, base, index, scale, offset);
1690     }
1691
1692     void movzwl_mr(int offset, RegisterID base, RegisterID dst)
1693     {
1694         js::JaegerSpew(js::JSpew_Insns,
1695                        IPFX "movzwl     %s0x%x(%s), %s\n", MAYBE_PAD,
1696                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4, dst));
1697         m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, offset);
1698     }
1699
1700     void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1701     {
1702         js::JaegerSpew(js::JSpew_Insns,
1703                        IPFX "movzwl     %d(%s,%s,%d), %s\n", MAYBE_PAD,
1704                        offset, nameIReg(base), nameIReg(index), scale, nameIReg(dst));
1705         m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, index, scale, offset);
1706     }
1707
1708     void movxwl_mr(int offset, RegisterID base, RegisterID dst)
1709     {
1710         js::JaegerSpew(js::JSpew_Insns,
1711                        IPFX "movxwl     %s0x%x(%s), %s\n", MAYBE_PAD,
1712                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4, dst));
1713         m_formatter.twoByteOp(OP2_MOVSX_GvEw, dst, base, offset);
1714     }
1715
1716     void movxwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1717     {
1718         js::JaegerSpew(js::JSpew_Insns,
1719                        IPFX "movxwl     %d(%s,%s,%d), %s\n", MAYBE_PAD,
1720                        offset, nameIReg(base), nameIReg(index), scale, nameIReg(dst));
1721         m_formatter.twoByteOp(OP2_MOVSX_GvEw, dst, base, index, scale, offset);
1722     }
1723
1724     void movzbl_rr(RegisterID src, RegisterID dst)
1725     {
1726         // In 64-bit, this may cause an unnecessary REX to be planted (if the dst register
1727         // is in the range ESP-EDI, and the src would not have required a REX).  Unneeded
1728         // REX prefixes are defined to be silently ignored by the processor.
1729         js::JaegerSpew(js::JSpew_Insns,
1730                        IPFX "movzbl      %s, %s\n", MAYBE_PAD,
1731                        nameIReg(4,src), nameIReg(4,dst));
1732         m_formatter.twoByteOp8(OP2_MOVZX_GvEb, dst, src);
1733     }
1734
1735     void leal_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1736     {
1737         js::JaegerSpew(js::JSpew_Insns,
1738                        IPFX "leal       %d(%s,%s,%d), %s\n", MAYBE_PAD,
1739                        offset, nameIReg(base), nameIReg(index), scale, nameIReg(dst));
1740         m_formatter.oneByteOp(OP_LEA, dst, base, index, scale, offset);
1741     }
1742
1743     void leal_mr(int offset, RegisterID base, RegisterID dst)
1744     {
1745         js::JaegerSpew(js::JSpew_Insns,
1746                        IPFX "leal       %s0x%x(%s), %s\n", MAYBE_PAD,
1747                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4,dst));
1748         m_formatter.oneByteOp(OP_LEA, dst, base, offset);
1749     }
1750 #if WTF_CPU_X86_64
1751     void leaq_mr(int offset, RegisterID base, RegisterID dst)
1752     {
1753         js::JaegerSpew(js::JSpew_Insns,
1754                        IPFX "leaq       %s0x%x(%s), %s\n", MAYBE_PAD,
1755                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(8,dst));
1756         m_formatter.oneByteOp64(OP_LEA, dst, base, offset);
1757     }
1758 #endif
1759
1760     // Flow control:
1761
1762     JmpSrc call()
1763     {
1764         m_formatter.oneByteOp(OP_CALL_rel32);
1765         JmpSrc r = m_formatter.immediateRel32();
1766         js::JaegerSpew(js::JSpew_Insns,
1767                        IPFX "call       ((%d))\n", MAYBE_PAD, r.m_offset);
1768         return r;
1769     }
1770     
1771     JmpSrc call(RegisterID dst)
1772     {
1773         m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_CALLN, dst);
1774         JmpSrc r = JmpSrc(m_formatter.size());
1775         js::JaegerSpew(js::JSpew_Insns,
1776                        IPFX "call       *%s\n", MAYBE_PAD, nameIReg(dst));
1777         return r;
1778     }
1779     
1780     void call_m(int offset, RegisterID base)
1781     {
1782         FIXME_INSN_PRINTING;
1783         m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_CALLN, base, offset);
1784     }
1785
1786     JmpSrc jmp()
1787     {
1788         m_formatter.oneByteOp(OP_JMP_rel32);
1789         JmpSrc r = m_formatter.immediateRel32();
1790         js::JaegerSpew(js::JSpew_Insns,
1791                        IPFX "jmp        ((%d))\n", MAYBE_PAD, r.m_offset);
1792         return r;
1793     }
1794     
1795     // Return a JmpSrc so we have a label to the jump, so we can use this
1796     // To make a tail recursive call on x86-64.  The MacroAssembler
1797     // really shouldn't wrap this as a Jump, since it can't be linked. :-/
1798     JmpSrc jmp_r(RegisterID dst)
1799     {
1800         js::JaegerSpew(js::JSpew_Insns,
1801                        IPFX "jmp        ((%s))\n", MAYBE_PAD,
1802            nameIReg(dst));
1803         m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, dst);
1804         return JmpSrc(m_formatter.size());
1805     }
1806     
1807     void jmp_m(int offset, RegisterID base)
1808     {
1809         FIXME_INSN_PRINTING;
1810         m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, base, offset);
1811     }
1812
1813     void jmp_m(int offset, RegisterID base, RegisterID index, int scale) {
1814         js::JaegerSpew(js::JSpew_Insns,
1815                        IPFX "jmp       ((%d(%s,%s,%d)))\n", MAYBE_PAD,
1816                        offset, nameIReg(base), nameIReg(index), scale);
1817         m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, base, index, scale, offset);
1818     }
1819
1820     JmpSrc jne()
1821     {
1822         return jCC(ConditionNE);
1823     }
1824     
1825     JmpSrc jnz()
1826     {
1827         // printing done by jne()
1828         return jne();
1829     }
1830
1831     JmpSrc je()
1832     {
1833         FIXME_INSN_PRINTING;
1834         m_formatter.twoByteOp(jccRel32(ConditionE));
1835         return m_formatter.immediateRel32();
1836     }
1837     
1838     JmpSrc jz()
1839     {
1840         // printing done by je()
1841         return je();
1842     }
1843
1844     JmpSrc jl()
1845     {
1846         FIXME_INSN_PRINTING;
1847         m_formatter.twoByteOp(jccRel32(ConditionL));
1848         return m_formatter.immediateRel32();
1849     }
1850     
1851     JmpSrc jb()
1852     {
1853         FIXME_INSN_PRINTING;
1854         m_formatter.twoByteOp(jccRel32(ConditionB));
1855         return m_formatter.immediateRel32();
1856     }
1857     
1858     JmpSrc jle()
1859     {
1860         FIXME_INSN_PRINTING;
1861         m_formatter.twoByteOp(jccRel32(ConditionLE));
1862         return m_formatter.immediateRel32();
1863     }
1864     
1865     JmpSrc jbe()
1866     {
1867         FIXME_INSN_PRINTING;
1868         m_formatter.twoByteOp(jccRel32(ConditionBE));
1869         return m_formatter.immediateRel32();
1870     }
1871     
1872     JmpSrc jge()
1873     {
1874         FIXME_INSN_PRINTING;
1875         m_formatter.twoByteOp(jccRel32(ConditionGE));
1876         return m_formatter.immediateRel32();
1877     }
1878
1879     JmpSrc jg()
1880     {
1881         FIXME_INSN_PRINTING;
1882         m_formatter.twoByteOp(jccRel32(ConditionG));
1883         return m_formatter.immediateRel32();
1884     }
1885
1886     JmpSrc ja()
1887     {
1888         FIXME_INSN_PRINTING;
1889         m_formatter.twoByteOp(jccRel32(ConditionA));
1890         return m_formatter.immediateRel32();
1891     }
1892     
1893     JmpSrc jae()
1894     {
1895         FIXME_INSN_PRINTING;
1896         m_formatter.twoByteOp(jccRel32(ConditionAE));
1897         return m_formatter.immediateRel32();
1898     }
1899     
1900     JmpSrc jo()
1901     {
1902         FIXME_INSN_PRINTING;
1903         m_formatter.twoByteOp(jccRel32(ConditionO));
1904         return m_formatter.immediateRel32();
1905     }
1906
1907     JmpSrc jp()
1908     {
1909         return jCC(ConditionP);
1910     }
1911     
1912     JmpSrc js()
1913     {
1914         FIXME_INSN_PRINTING;
1915         m_formatter.twoByteOp(jccRel32(ConditionS));
1916         return m_formatter.immediateRel32();
1917     }
1918
1919     JmpSrc jCC(Condition cond)
1920     {
1921         m_formatter.twoByteOp(jccRel32(cond));
1922         JmpSrc r = m_formatter.immediateRel32();
1923         js::JaegerSpew(js::JSpew_Insns,
1924                        IPFX "j%s        ((%d))\n", MAYBE_PAD,
1925                        nameCC(cond), r.m_offset);
1926         return r;
1927     }
1928
1929     // SSE operations:
1930
1931     void addsd_rr(XMMRegisterID src, XMMRegisterID dst)
1932     {
1933         js::JaegerSpew(js::JSpew_Insns,
1934                        IPFX "addsd      %s, %s\n", MAYBE_PAD,
1935                        nameFPReg(src), nameFPReg(dst));
1936         m_formatter.prefix(PRE_SSE_F2);
1937         m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
1938     }
1939
1940     void addsd_mr(int offset, RegisterID base, XMMRegisterID dst)
1941     {
1942         js::JaegerSpew(js::JSpew_Insns,
1943                        IPFX "addsd      %s0x%x(%s), %s\n", MAYBE_PAD,
1944                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
1945         m_formatter.prefix(PRE_SSE_F2);
1946         m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, base, offset);
1947     }
1948
1949     void cvtss2sd_rr(XMMRegisterID src, XMMRegisterID dst)
1950     {
1951         js::JaegerSpew(js::JSpew_Insns,
1952                        IPFX "cvtps2pd   %s, %s\n", MAYBE_PAD,
1953                        nameFPReg(src), nameFPReg(dst));
1954         m_formatter.prefix(PRE_SSE_F3);
1955         m_formatter.twoByteOp(OP2_CVTSS2SD_VsdEd, (RegisterID)dst, (RegisterID)src);
1956     }
1957
1958     void cvtsd2ss_rr(XMMRegisterID src, XMMRegisterID dst)
1959     {
1960         js::JaegerSpew(js::JSpew_Insns,
1961                        IPFX "cvtps2pd   %s, %s\n", MAYBE_PAD,
1962                        nameFPReg(src), nameFPReg(dst));
1963         m_formatter.prefix(PRE_SSE_F2);
1964         m_formatter.twoByteOp(OP2_CVTSD2SS_VsdEd, (RegisterID)dst, (RegisterID)src);
1965     }
1966
1967     void cvtsi2sd_rr(RegisterID src, XMMRegisterID dst)
1968     {
1969         js::JaegerSpew(js::JSpew_Insns,
1970                        IPFX "cvtsi2sd   %s, %s\n", MAYBE_PAD,
1971                        nameIReg(src), nameFPReg(dst));
1972         m_formatter.prefix(PRE_SSE_F2);
1973         m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
1974     }
1975
1976 #if WTF_CPU_X86_64
1977     void cvtsq2sd_rr(RegisterID src, XMMRegisterID dst)
1978     {
1979         js::JaegerSpew(js::JSpew_Insns,
1980                        IPFX "cvtsq2sd   %s, %s\n", MAYBE_PAD,
1981                        nameIReg(src), nameFPReg(dst));
1982         m_formatter.prefix(PRE_SSE_F2);
1983         m_formatter.twoByteOp64(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
1984     }
1985 #endif
1986
1987     void cvtsi2sd_mr(int offset, RegisterID base, XMMRegisterID dst)
1988     {
1989         js::JaegerSpew(js::JSpew_Insns,
1990                        IPFX "cvtsi2sd   %s0x%x(%s), %s\n", MAYBE_PAD,
1991                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
1992         m_formatter.prefix(PRE_SSE_F2);
1993         m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, base, offset);
1994     }
1995
1996 #if !WTF_CPU_X86_64
1997     void cvtsi2sd_mr(void* address, XMMRegisterID dst)
1998     {
1999         js::JaegerSpew(js::JSpew_Insns,
2000                        IPFX "cvtsi2sd   %p, %s\n", MAYBE_PAD,
2001                        address, nameFPReg(dst));
2002         m_formatter.prefix(PRE_SSE_F2);
2003         m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, address);
2004     }
2005 #endif
2006
2007     void cvttsd2si_rr(XMMRegisterID src, RegisterID dst)
2008     {
2009         js::JaegerSpew(js::JSpew_Insns,
2010                        IPFX "cvttsd2si  %s, %s\n", MAYBE_PAD,
2011                        nameFPReg(src), nameIReg(dst));
2012         m_formatter.prefix(PRE_SSE_F2);
2013         m_formatter.twoByteOp(OP2_CVTTSD2SI_GdWsd, dst, (RegisterID)src);
2014     }
2015
2016     void unpcklps_rr(XMMRegisterID src, XMMRegisterID dst)
2017     {
2018         js::JaegerSpew(js::JSpew_Insns,
2019                        IPFX "unpcklps   %s, %s\n", MAYBE_PAD,
2020                        nameFPReg(src), nameFPReg(dst));
2021         m_formatter.twoByteOp(OP2_UNPCKLPS_VsdWsd, (RegisterID)dst, (RegisterID)src);
2022     }
2023
2024     void movd_rr(RegisterID src, XMMRegisterID dst)
2025     {
2026         js::JaegerSpew(js::JSpew_Insns,
2027                        IPFX "movd       %s, %s\n", MAYBE_PAD,
2028                        nameIReg(src), nameFPReg(dst));
2029         m_formatter.prefix(PRE_SSE_66);
2030         m_formatter.twoByteOp(OP2_MOVD_VdEd, (RegisterID)dst, src);
2031     }
2032
2033     void psrldq_rr(XMMRegisterID dest, int shift)
2034     {
2035         js::JaegerSpew(js::JSpew_Insns,
2036                        IPFX "pslldq     %s, %d\n", MAYBE_PAD,
2037                        nameFPReg(dest), shift);
2038         m_formatter.prefix(PRE_SSE_66);
2039         m_formatter.twoByteOp(OP2_PSRLDQ_Vd, (RegisterID)3, (RegisterID)dest);
2040         m_formatter.immediate8(shift);
2041     }
2042
2043     void movd_rr(XMMRegisterID src, RegisterID dst)
2044     {
2045         js::JaegerSpew(js::JSpew_Insns,
2046                        IPFX "movd       %s, %s\n", MAYBE_PAD,
2047                        nameFPReg(src), nameIReg(dst));
2048         m_formatter.prefix(PRE_SSE_66);
2049         m_formatter.twoByteOp(OP2_MOVD_EdVd, (RegisterID)src, dst);
2050     }
2051
2052 #if WTF_CPU_X86_64
2053     void movq_rr(XMMRegisterID src, RegisterID dst)
2054     {
2055         js::JaegerSpew(js::JSpew_Insns,
2056                        IPFX "movq       %s, %s\n", MAYBE_PAD,
2057                        nameFPReg(src), nameIReg(dst));
2058         m_formatter.prefix(PRE_SSE_66);
2059         m_formatter.twoByteOp64(OP2_MOVD_EdVd, (RegisterID)src, dst);
2060     }
2061
2062     void movq_rr(RegisterID src, XMMRegisterID dst)
2063     {
2064         js::JaegerSpew(js::JSpew_Insns,
2065                        IPFX "movq       %s, %s\n", MAYBE_PAD,
2066                        nameIReg(src), nameFPReg(dst));
2067         m_formatter.prefix(PRE_SSE_66);
2068         m_formatter.twoByteOp64(OP2_MOVD_VdEd, (RegisterID)dst, src);
2069     }
2070 #endif
2071
2072     void movsd_rm(XMMRegisterID src, int offset, RegisterID base)
2073     {
2074         js::JaegerSpew(js::JSpew_Insns,
2075                        IPFX "movsd      %s, %s0x%x(%s)\n", MAYBE_PAD,
2076                        nameFPReg(src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
2077         m_formatter.prefix(PRE_SSE_F2);
2078         m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, offset);
2079     }
2080
2081     void movss_rm(XMMRegisterID src, int offset, RegisterID base)
2082     {
2083         js::JaegerSpew(js::JSpew_Insns,
2084                        IPFX "movss      %s, %s0x%x(%s)\n", MAYBE_PAD,
2085                        nameFPReg(src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
2086         m_formatter.prefix(PRE_SSE_F3);
2087         m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, offset);
2088     }
2089
2090     void movss_mr(int offset, RegisterID base, XMMRegisterID dst)
2091     {
2092         js::JaegerSpew(js::JSpew_Insns,
2093                        IPFX "movss      %s0x%x(%s), %s\n", MAYBE_PAD,
2094                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
2095         m_formatter.prefix(PRE_SSE_F3);
2096         m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset);
2097     }
2098
2099     void movsd_rm(XMMRegisterID src, int offset, RegisterID base, RegisterID index, int scale)
2100     {
2101         js::JaegerSpew(js::JSpew_Insns,
2102                        IPFX "movsd       %s, %d(%s,%s,%d)\n", MAYBE_PAD, 
2103                        nameFPReg(src), offset, nameIReg(base), nameIReg(index), scale);
2104         m_formatter.prefix(PRE_SSE_F2);
2105         m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, index, scale, offset);
2106     }
2107
2108     void movss_rm(XMMRegisterID src, int offset, RegisterID base, RegisterID index, int scale)
2109     {
2110         js::JaegerSpew(js::JSpew_Insns,
2111                        IPFX "movss       %s, %d(%s,%s,%d)\n", MAYBE_PAD, 
2112                        nameFPReg(src), offset, nameIReg(base), nameIReg(index), scale);
2113         m_formatter.prefix(PRE_SSE_F3);
2114         m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, index, scale, offset);
2115     }
2116
2117     void movss_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
2118     {
2119         js::JaegerSpew(js::JSpew_Insns,
2120                        IPFX "movss      %d(%s,%s,%d), %s\n", MAYBE_PAD,
2121                        offset, nameIReg(base), nameIReg(index), scale, nameFPReg(dst));
2122         m_formatter.prefix(PRE_SSE_F3);
2123         m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, index, scale, offset);
2124     }
2125
2126     void movsd_mr(int offset, RegisterID base, XMMRegisterID dst)
2127     {
2128         js::JaegerSpew(js::JSpew_Insns,
2129                        IPFX "movsd      %s0x%x(%s), %s\n", MAYBE_PAD,
2130                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
2131         m_formatter.prefix(PRE_SSE_F2);
2132         m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset);
2133     }
2134
2135     void movsd_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
2136     {
2137         js::JaegerSpew(js::JSpew_Insns,
2138                        IPFX "movsd      %d(%s,%s,%d), %s\n", MAYBE_PAD,
2139                        offset, nameIReg(base), nameIReg(index), scale, nameFPReg(dst));
2140         m_formatter.prefix(PRE_SSE_F2);
2141         m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, index, scale, offset);
2142     }
2143
2144     void movsd_rr(XMMRegisterID src, XMMRegisterID dst)
2145     {
2146         js::JaegerSpew(js::JSpew_Insns,
2147                        IPFX "movsd      %s, %s\n", MAYBE_PAD,
2148                        nameFPReg(src), nameFPReg(dst));
2149         m_formatter.prefix(PRE_SSE_F2);
2150         m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
2151     }
2152
2153 #if !WTF_CPU_X86_64
2154     void movsd_mr(const void* address, XMMRegisterID dst)
2155     {
2156         js::JaegerSpew(js::JSpew_Insns,
2157                        IPFX "movsd      %p, %s\n", MAYBE_PAD,
2158                        address, nameFPReg(dst));
2159         m_formatter.prefix(PRE_SSE_F2);
2160         m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, address);
2161     }
2162 #endif
2163
2164     void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)
2165     {
2166         js::JaegerSpew(js::JSpew_Insns,
2167                        IPFX "mulsd      %s, %s\n", MAYBE_PAD,
2168                        nameFPReg(src), nameFPReg(dst));
2169         m_formatter.prefix(PRE_SSE_F2);
2170         m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
2171     }
2172
2173     void mulsd_mr(int offset, RegisterID base, XMMRegisterID dst)
2174     {
2175         js::JaegerSpew(js::JSpew_Insns,
2176                        IPFX "mulsd      %s0x%x(%s), %s\n", MAYBE_PAD,
2177                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
2178         m_formatter.prefix(PRE_SSE_F2);
2179         m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, base, offset);
2180     }
2181
2182     void pextrw_irr(int whichWord, XMMRegisterID src, RegisterID dst)
2183     {
2184         FIXME_INSN_PRINTING;
2185         m_formatter.prefix(PRE_SSE_66);
2186         m_formatter.twoByteOp(OP2_PEXTRW_GdUdIb, (RegisterID)dst, (RegisterID)src);
2187         m_formatter.immediate8(whichWord);
2188     }
2189
2190     void subsd_rr(XMMRegisterID src, XMMRegisterID dst)
2191     {
2192         js::JaegerSpew(js::JSpew_Insns,
2193                        IPFX "subsd      %s, %s\n", MAYBE_PAD,
2194                        nameFPReg(src), nameFPReg(dst));
2195         m_formatter.prefix(PRE_SSE_F2);
2196         m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
2197     }
2198
2199     void subsd_mr(int offset, RegisterID base, XMMRegisterID dst)
2200     {
2201         js::JaegerSpew(js::JSpew_Insns,
2202                        IPFX "subsd      %s0x%x(%s), %s\n", MAYBE_PAD,
2203                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
2204         m_formatter.prefix(PRE_SSE_F2);
2205         m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, base, offset);
2206     }
2207
2208     void ucomisd_rr(XMMRegisterID src, XMMRegisterID dst)
2209     {
2210         js::JaegerSpew(js::JSpew_Insns,
2211                        IPFX "ucomisd    %s, %s\n", MAYBE_PAD,
2212                        nameFPReg(src), nameFPReg(dst));
2213         m_formatter.prefix(PRE_SSE_66);
2214         m_formatter.twoByteOp(OP2_UCOMISD_VsdWsd, (RegisterID)dst, (RegisterID)src);
2215     }
2216
2217     void ucomisd_mr(int offset, RegisterID base, XMMRegisterID dst)
2218     {
2219         js::JaegerSpew(js::JSpew_Insns,
2220                        IPFX "ucomisd    %s0x%x(%s), %s\n", MAYBE_PAD,
2221                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
2222         m_formatter.prefix(PRE_SSE_66);
2223         m_formatter.twoByteOp(OP2_UCOMISD_VsdWsd, (RegisterID)dst, base, offset);
2224     }
2225
2226     void divsd_rr(XMMRegisterID src, XMMRegisterID dst)
2227     {
2228         js::JaegerSpew(js::JSpew_Insns,
2229                        IPFX "divsd      %s, %s\n", MAYBE_PAD,
2230                        nameFPReg(src), nameFPReg(dst));
2231         m_formatter.prefix(PRE_SSE_F2);
2232         m_formatter.twoByteOp(OP2_DIVSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
2233     }
2234
2235     void divsd_mr(int offset, RegisterID base, XMMRegisterID dst)
2236     {
2237         js::JaegerSpew(js::JSpew_Insns,
2238                        IPFX "divsd      %s0x%x(%s), %s\n", MAYBE_PAD,
2239                        PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
2240         m_formatter.prefix(PRE_SSE_F2);
2241         m_formatter.twoByteOp(OP2_DIVSD_VsdWsd, (RegisterID)dst, base, offset);
2242     }
2243
2244     void xorpd_rr(XMMRegisterID src, XMMRegisterID dst)
2245     {
2246         js::JaegerSpew(js::JSpew_Insns,
2247                        IPFX "xorpd      %s, %s\n", MAYBE_PAD,
2248                        nameFPReg(src), nameFPReg(dst));
2249         m_formatter.prefix(PRE_SSE_66);
2250         m_formatter.twoByteOp(OP2_XORPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
2251     }
2252
2253     void sqrtsd_rr(XMMRegisterID src, XMMRegisterID dst)
2254     {
2255         js::JaegerSpew(js::JSpew_Insns,
2256                        IPFX "sqrtsd     %s, %s\n", MAYBE_PAD,
2257                        nameFPReg(src), nameFPReg(dst));
2258         m_formatter.prefix(PRE_SSE_F2);
2259         m_formatter.twoByteOp(OP2_SQRTSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
2260     }
2261
2262     void pinsrd_rr(RegisterID src, XMMRegisterID dst)
2263     {
2264         js::JaegerSpew(js::JSpew_Insns,
2265                        IPFX "pinsrd     $1, %s, %s\n", MAYBE_PAD,
2266                        nameIReg(src), nameFPReg(dst));
2267         m_formatter.prefix(PRE_SSE_66);
2268         m_formatter.threeByteOp(OP3_PINSRD_VsdWsd, (RegisterID)dst, (RegisterID)src);
2269         m_formatter.immediate8(0x01); // the $1
2270     }
2271
2272     // Misc instructions:
2273
2274     void int3()
2275     {
2276         js::JaegerSpew(js::JSpew_Insns, IPFX "int3\n", MAYBE_PAD);
2277         m_formatter.oneByteOp(OP_INT3);
2278     }
2279     
2280     void ret()
2281     {
2282         js::JaegerSpew(js::JSpew_Insns, IPFX "ret\n", MAYBE_PAD);
2283         m_formatter.oneByteOp(OP_RET);
2284     }
2285
2286     void predictNotTaken()
2287     {
2288         FIXME_INSN_PRINTING;
2289         m_formatter.prefix(PRE_PREDICT_BRANCH_NOT_TAKEN);
2290     }
2291
2292 #if WTF_CPU_X86
2293     void pusha()
2294     {
2295         js::JaegerSpew(js::JSpew_Insns, IPFX "pusha\n", MAYBE_PAD);
2296         m_formatter.oneByteOp(OP_PUSHA);
2297     }
2298
2299     void popa()
2300     {
2301         js::JaegerSpew(js::JSpew_Insns, IPFX "popa\n", MAYBE_PAD);
2302         m_formatter.oneByteOp(OP_POPA);
2303     }
2304 #endif
2305
2306     // Assembler admin methods:
2307
2308     JmpDst label()
2309     {
2310         JmpDst r = JmpDst(m_formatter.size());
2311         js::JaegerSpew(js::JSpew_Insns,
2312                        IPFX "#label     ((%d))\n", MAYBE_PAD, r.m_offset);
2313         return r;
2314     }
2315     
2316     static JmpDst labelFor(JmpSrc jump, intptr_t offset = 0)
2317     {
2318         FIXME_INSN_PRINTING;
2319         return JmpDst(jump.m_offset + offset);
2320     }
2321     
2322     JmpDst align(int alignment)
2323     {
2324         FIXME_INSN_PRINTING;
2325         while (!m_formatter.isAligned(alignment))
2326             m_formatter.oneByteOp(OP_HLT);
2327
2328         return label();
2329     }
2330
2331     // Linking & patching:
2332     //
2333     // 'link' and 'patch' methods are for use on unprotected code - such as the code
2334     // within the AssemblerBuffer, and code being patched by the patch buffer.  Once
2335     // code has been finalized it is (platform support permitting) within a non-
2336     // writable region of memory; to modify the code in an execute-only execuable
2337     // pool the 'repatch' and 'relink' methods should be used.
2338
2339     void linkJump(JmpSrc from, JmpDst to)
2340     {
2341         ASSERT(from.m_offset != -1);
2342         ASSERT(to.m_offset != -1);
2343
2344         js::JaegerSpew(js::JSpew_Insns,
2345                        IPFX "##link     ((%d)) jumps to ((%d))\n", MAYBE_PAD,
2346                        from.m_offset, to.m_offset);
2347         char* code = reinterpret_cast<char*>(m_formatter.data());
2348         setRel32(code + from.m_offset, code + to.m_offset);
2349     }
2350     
2351     static void linkJump(void* code, JmpSrc from, void* to)
2352     {
2353         ASSERT(from.m_offset != -1);
2354
2355         js::JaegerSpew(js::JSpew_Insns,
2356                        ISPFX "##link     ((%d)) jumps to ((%p))\n",
2357                        from.m_offset, to);
2358         setRel32(reinterpret_cast<char*>(code) + from.m_offset, to);
2359     }
2360
2361     static void linkCall(void* code, JmpSrc from, void* to)
2362     {
2363         ASSERT(from.m_offset != -1);
2364
2365         FIXME_INSN_PRINTING;
2366         setRel32(reinterpret_cast<char*>(code) + from.m_offset, to);
2367     }
2368
2369     static void linkPointer(void* code, JmpDst where, void* value)
2370     {
2371         ASSERT(where.m_offset != -1);
2372
2373         FIXME_INSN_PRINTING;
2374         setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
2375     }
2376
2377     static void relinkJump(void* from, void* to)
2378     {
2379         js::JaegerSpew(js::JSpew_Insns,
2380                        ISPFX "##relinkJump ((from=%p)) ((to=%p))\n",
2381                        from, to);
2382         setRel32(from, to);
2383     }
2384
2385     static bool canRelinkJump(void* from, void* to)
2386     {
2387         intptr_t offset = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from);
2388         return (offset == static_cast<int32_t>(offset));
2389     }
2390     
2391     static void relinkCall(void* from, void* to)
2392     {
2393         js::JaegerSpew(js::JSpew_Insns,
2394                        ISPFX "##relinkCall ((from=%p)) ((to=%p))\n",
2395                        from, to);
2396         setRel32(from, to);
2397     }
2398
2399     static void repatchInt32(void* where, int32_t value)
2400     {
2401         js::JaegerSpew(js::JSpew_Insns,
2402                        ISPFX "##relinkInt32 ((where=%p)) ((value=%d))\n",
2403                        where, value);
2404         setInt32(where, value);
2405     }
2406
2407     static void repatchPointer(void* where, void* value)
2408     {
2409         js::JaegerSpew(js::JSpew_Insns,
2410                        ISPFX "##repatchPtr ((where=%p)) ((value=%p))\n",
2411                        where, value);
2412         setPointer(where, value);
2413     }
2414
2415     static void repatchLoadPtrToLEA(void* where)
2416     {
2417         js::JaegerSpew(js::JSpew_Insns,
2418                        ISPFX "##repatchLoadPtrToLEA ((where=%p))\n",
2419                        where);
2420
2421 #if WTF_CPU_X86_64
2422         // On x86-64 pointer memory accesses require a 64-bit operand, and as such a REX prefix.
2423         // Skip over the prefix byte.
2424         where = reinterpret_cast<char*>(where) + 1;
2425 #endif
2426         *reinterpret_cast<unsigned char*>(where) = static_cast<unsigned char>(OP_LEA);
2427     }
2428     
2429     static void repatchLEAToLoadPtr(void* where)
2430     {
2431         js::JaegerSpew(js::JSpew_Insns,
2432                        ISPFX "##repatchLEAToLoadPtr ((where=%p))\n",
2433                        where);
2434 #if WTF_CPU_X86_64
2435         // On x86-64 pointer memory accesses require a 64-bit operand, and as such a REX prefix.
2436         // Skip over the prefix byte.
2437         where = reinterpret_cast<char*>(where) + 1;
2438 #endif
2439         *reinterpret_cast<unsigned char*>(where) = static_cast<unsigned char>(OP_MOV_GvEv);
2440     }
2441
2442     static unsigned getCallReturnOffset(JmpSrc call)
2443     {
2444         ASSERT(call.m_offset >= 0);
2445         return call.m_offset;
2446     }
2447
2448     static void* getRelocatedAddress(void* code, JmpSrc jump)
2449     {
2450         ASSERT(jump.m_offset != -1);
2451
2452         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
2453     }
2454     
2455     static void* getRelocatedAddress(void* code, JmpDst destination)
2456     {
2457         ASSERT(destination.m_offset != -1);
2458
2459         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
2460     }
2461     
2462     static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
2463     {
2464         return dst.m_offset - src.m_offset;
2465     }
2466     
2467     static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
2468     {
2469         return dst.m_offset - src.m_offset;
2470     }
2471     
2472     static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
2473     {
2474         return dst.m_offset - src.m_offset;
2475     }
2476     
2477     void* executableCopy(ExecutablePool* allocator)
2478     {
2479         void* copy = m_formatter.executableCopy(allocator);
2480         return copy;
2481     }
2482
2483     void* executableCopy(void* buffer)
2484     {
2485         if (m_formatter.oom())
2486             return NULL;
2487         return memcpy(buffer, m_formatter.buffer(), size());
2488     }
2489
2490 private:
2491
2492     static void setPointer(void* where, void* value)
2493     {
2494         js::JaegerSpew(js::JSpew_Insns,
2495                        ISPFX "##setPtr     ((where=%p)) ((value=%p))\n", where, value);
2496         reinterpret_cast<void**>(where)[-1] = value;
2497     }
2498
2499     static void setInt32(void* where, int32_t value)
2500     {
2501         reinterpret_cast<int32_t*>(where)[-1] = value;
2502     }
2503
2504     static void setRel32(void* from, void* to)
2505     {
2506         intptr_t offset = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from);
2507         ASSERT(offset == static_cast<int32_t>(offset));
2508 #define JS_CRASH(x) *(int *)x = 0
2509         if (offset != static_cast<int32_t>(offset))
2510             JS_CRASH(0xC0DE);
2511 #undef JS_CRASH
2512
2513         js::JaegerSpew(js::JSpew_Insns,
2514                        ISPFX "##setRel32 ((from=%p)) ((to=%p))\n", from, to);
2515         setInt32(from, offset);
2516     }
2517
2518     class X86InstructionFormatter {
2519
2520         static const int maxInstructionSize = 16;
2521
2522     public:
2523
2524         // Legacy prefix bytes:
2525         //
2526         // These are emmitted prior to the instruction.
2527
2528         void prefix(OneByteOpcodeID pre)
2529         {
2530             m_buffer.putByte(pre);
2531         }
2532
2533         // Word-sized operands / no operand instruction formatters.
2534         //
2535         // In addition to the opcode, the following operand permutations are supported:
2536         //   * None - instruction takes no operands.
2537         //   * One register - the low three bits of the RegisterID are added into the opcode.
2538         //   * Two registers - encode a register form ModRm (for all ModRm formats, the reg field is passed first, and a GroupOpcodeID may be passed in its place).
2539         //   * Three argument ModRM - a register, and a register and an offset describing a memory operand.
2540         //   * Five argument ModRM - a register, and a base register, an index, scale, and offset describing a memory operand.
2541         //
2542         // For 32-bit x86 targets, the address operand may also be provided as a void*.
2543         // On 64-bit targets REX prefixes will be planted as necessary, where high numbered registers are used.
2544         //
2545         // The twoByteOp methods plant two-byte Intel instructions sequences (first opcode byte 0x0F).
2546
2547         void oneByteOp(OneByteOpcodeID opcode)
2548         {
2549             m_buffer.ensureSpace(maxInstructionSize);
2550             m_buffer.putByteUnchecked(opcode);
2551         }
2552
2553         void oneByteOp(OneByteOpcodeID opcode, RegisterID reg)
2554         {
2555             m_buffer.ensureSpace(maxInstructionSize);
2556             emitRexIfNeeded(0, 0, reg);
2557             m_buffer.putByteUnchecked(opcode + (reg & 7));
2558         }
2559
2560         void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID rm)
2561         {
2562             m_buffer.ensureSpace(maxInstructionSize);
2563             emitRexIfNeeded(reg, 0, rm);
2564             m_buffer.putByteUnchecked(opcode);
2565             registerModRM(reg, rm);
2566         }
2567
2568         void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2569         {
2570             m_buffer.ensureSpace(maxInstructionSize);
2571             emitRexIfNeeded(reg, 0, base);
2572             m_buffer.putByteUnchecked(opcode);
2573             memoryModRM(reg, base, offset);
2574         }
2575
2576         void oneByteOp_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2577         {
2578             m_buffer.ensureSpace(maxInstructionSize);
2579             emitRexIfNeeded(reg, 0, base);
2580             m_buffer.putByteUnchecked(opcode);
2581             memoryModRM_disp32(reg, base, offset);
2582         }
2583
2584         void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
2585         {
2586             m_buffer.ensureSpace(maxInstructionSize);
2587             emitRexIfNeeded(reg, index, base);
2588             m_buffer.putByteUnchecked(opcode);
2589             memoryModRM(reg, base, index, scale, offset);
2590         }
2591
2592 #if !WTF_CPU_X86_64
2593         void oneByteOp(OneByteOpcodeID opcode, int reg, void* address)
2594         {
2595             m_buffer.ensureSpace(maxInstructionSize);
2596             m_buffer.putByteUnchecked(opcode);
2597             memoryModRM(reg, address);
2598         }
2599 #endif
2600
2601         void twoByteOp(TwoByteOpcodeID opcode)
2602         {
2603             m_buffer.ensureSpace(maxInstructionSize);
2604             m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2605             m_buffer.putByteUnchecked(opcode);
2606         }
2607
2608         void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID rm)
2609         {
2610             m_buffer.ensureSpace(maxInstructionSize);
2611             emitRexIfNeeded(reg, 0, rm);
2612             m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2613             m_buffer.putByteUnchecked(opcode);
2614             registerModRM(reg, rm);
2615         }
2616
2617         void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, int offset)
2618         {
2619             m_buffer.ensureSpace(maxInstructionSize);
2620             emitRexIfNeeded(reg, 0, base);
2621             m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2622             m_buffer.putByteUnchecked(opcode);
2623             memoryModRM(reg, base, offset);
2624         }
2625
2626         void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
2627         {
2628             m_buffer.ensureSpace(maxInstructionSize);
2629             emitRexIfNeeded(reg, index, base);
2630             m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2631             m_buffer.putByteUnchecked(opcode);
2632             memoryModRM(reg, base, index, scale, offset);
2633         }
2634
2635 #if !WTF_CPU_X86_64
2636         void twoByteOp(TwoByteOpcodeID opcode, int reg, const void* address)
2637         {
2638             m_buffer.ensureSpace(maxInstructionSize);
2639             m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2640             m_buffer.putByteUnchecked(opcode);
2641             memoryModRM(reg, address);
2642         }
2643 #endif
2644
2645         void threeByteOp(ThreeByteOpcodeID opcode, int reg, RegisterID rm)
2646         {
2647             m_buffer.ensureSpace(maxInstructionSize);
2648             emitRexIfNeeded(reg, 0, rm);
2649             m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2650             m_buffer.putByteUnchecked(OP_3BYTE_ESCAPE);
2651             m_buffer.putByteUnchecked(opcode);
2652             registerModRM(reg, rm);
2653         }
2654
2655 #if WTF_CPU_X86_64
2656         // Quad-word-sized operands:
2657         //
2658         // Used to format 64-bit operantions, planting a REX.w prefix.
2659         // When planting d64 or f64 instructions, not requiring a REX.w prefix,
2660         // the normal (non-'64'-postfixed) formatters should be used.
2661
2662         void oneByteOp64(OneByteOpcodeID opcode)
2663         {
2664             m_buffer.ensureSpace(maxInstructionSize);
2665             emitRexW(0, 0, 0);
2666             m_buffer.putByteUnchecked(opcode);
2667         }
2668
2669         void oneByteOp64(OneByteOpcodeID opcode, RegisterID reg)
2670         {
2671             m_buffer.ensureSpace(maxInstructionSize);
2672             emitRexW(0, 0, reg);
2673             m_buffer.putByteUnchecked(opcode + (reg & 7));
2674         }
2675
2676         void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID rm)
2677         {
2678             m_buffer.ensureSpace(maxInstructionSize);
2679             emitRexW(reg, 0, rm);
2680             m_buffer.putByteUnchecked(opcode);
2681             registerModRM(reg, rm);
2682         }
2683
2684         void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2685         {
2686             m_buffer.ensureSpace(maxInstructionSize);
2687             emitRexW(reg, 0, base);
2688             m_buffer.putByteUnchecked(opcode);
2689             memoryModRM(reg, base, offset);
2690         }
2691
2692         void oneByteOp64_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2693         {
2694             m_buffer.ensureSpace(maxInstructionSize);
2695             emitRexW(reg, 0, base);
2696             m_buffer.putByteUnchecked(opcode);
2697             memoryModRM_disp32(reg, base, offset);
2698         }
2699
2700         void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
2701         {
2702             m_buffer.ensureSpace(maxInstructionSize);
2703             emitRexW(reg, index, base);
2704             m_buffer.putByteUnchecked(opcode);
2705             memoryModRM(reg, base, index, scale, offset);
2706         }
2707
2708         void twoByteOp64(TwoByteOpcodeID opcode, int reg, RegisterID rm)
2709         {
2710             m_buffer.ensureSpace(maxInstructionSize);
2711             emitRexW(reg, 0, rm);
2712             m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2713             m_buffer.putByteUnchecked(opcode);
2714             registerModRM(reg, rm);
2715         }
2716 #endif
2717
2718         // Byte-operands:
2719         //
2720         // These methods format byte operations.  Byte operations differ from the normal
2721         // formatters in the circumstances under which they will decide to emit REX prefixes.
2722         // These should be used where any register operand signifies a byte register.
2723         //
2724         // The disctinction is due to the handling of register numbers in the range 4..7 on
2725         // x86-64.  These register numbers may either represent the second byte of the first
2726         // four registers (ah..bh) or the first byte of the second four registers (spl..dil).
2727         //
2728         // Since ah..bh cannot be used in all permutations of operands (specifically cannot
2729         // be accessed where a REX prefix is present), these are likely best treated as
2730         // deprecated.  In order to ensure the correct registers spl..dil are selected a
2731         // REX prefix will be emitted for any byte register operand in the range 4..15.
2732         //
2733         // These formatters may be used in instructions where a mix of operand sizes, in which
2734         // case an unnecessary REX will be emitted, for example:
2735         //     movzbl %al, %edi
2736         // In this case a REX will be planted since edi is 7 (and were this a byte operand
2737         // a REX would be required to specify dil instead of bh).  Unneeded REX prefixes will
2738         // be silently ignored by the processor.
2739         //
2740         // Address operands should still be checked using regRequiresRex(), while byteRegRequiresRex()
2741         // is provided to check byte register operands.
2742
2743         void oneByteOp8(OneByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm)
2744         {
2745 #if !WTF_CPU_X86_64
2746             ASSERT(!byteRegRequiresRex(rm));
2747 #endif
2748             m_buffer.ensureSpace(maxInstructionSize);
2749             emitRexIf(byteRegRequiresRex(rm), 0, 0, rm);
2750             m_buffer.putByteUnchecked(opcode);
2751             registerModRM(groupOp, rm);
2752         }
2753
2754         void oneByteOp8(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2755         {
2756 #if !WTF_CPU_X86_64
2757             ASSERT(!byteRegRequiresRex(reg));
2758 #endif
2759             m_buffer.ensureSpace(maxInstructionSize);
2760             emitRexIf(byteRegRequiresRex(reg), reg, 0, base);
2761             m_buffer.putByteUnchecked(opcode);
2762             memoryModRM(reg, base, offset);
2763         }
2764
2765         void oneByteOp8(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
2766         {
2767 #if !WTF_CPU_X86_64
2768             ASSERT(!byteRegRequiresRex(reg));
2769 #endif
2770             m_buffer.ensureSpace(maxInstructionSize);
2771             emitRexIf(byteRegRequiresRex(reg), reg, index, base);
2772             m_buffer.putByteUnchecked(opcode);
2773             memoryModRM(reg, base, index, scale, offset);
2774         }
2775
2776         void twoByteOp8(TwoByteOpcodeID opcode, RegisterID reg, RegisterID rm)
2777         {
2778             m_buffer.ensureSpace(maxInstructionSize);
2779             emitRexIf(byteRegRequiresRex(reg)|byteRegRequiresRex(rm), reg, 0, rm);
2780             m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2781             m_buffer.putByteUnchecked(opcode);
2782             registerModRM(reg, rm);
2783         }
2784
2785         void twoByteOp8(TwoByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm)
2786         {
2787             m_buffer.ensureSpace(maxInstructionSize);
2788             emitRexIf(byteRegRequiresRex(rm), 0, 0, rm);
2789             m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2790             m_buffer.putByteUnchecked(opcode);
2791             registerModRM(groupOp, rm);
2792         }
2793
2794         // Immediates:
2795         //
2796         // An immedaite should be appended where appropriate after an op has been emitted.
2797         // The writes are unchecked since the opcode formatters above will have ensured space.
2798
2799         void immediate8(int imm)
2800         {
2801             m_buffer.putByteUnchecked(imm);
2802         }
2803
2804         void immediate16(int imm)
2805         {
2806             m_buffer.putShortUnchecked(imm);
2807         }
2808
2809         void immediate32(int imm)
2810         {
2811             m_buffer.putIntUnchecked(imm);
2812         }
2813
2814         void immediate64(int64_t imm)
2815         {
2816             m_buffer.putInt64Unchecked(imm);
2817         }
2818
2819         JmpSrc immediateRel32()
2820         {
2821             m_buffer.putIntUnchecked(0);
2822             return JmpSrc(m_buffer.size());
2823         }
2824
2825         // Administrative methods:
2826
2827         size_t size() const { return m_buffer.size(); }
2828         unsigned char *buffer() const { return m_buffer.buffer(); }
2829         bool oom() const { return m_buffer.oom(); }
2830         bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
2831         void* data() const { return m_buffer.data(); }
2832         void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
2833
2834     private:
2835
2836         // Internals; ModRm and REX formatters.
2837
2838         // Byte operand register spl & above require a REX prefix (to prevent the 'H' registers be accessed).
2839         inline bool byteRegRequiresRex(int reg)
2840         {
2841             return (reg >= X86Registers::esp);
2842         }
2843
2844         static const RegisterID noBase = X86Registers::ebp;
2845         static const RegisterID hasSib = X86Registers::esp;
2846         static const RegisterID noIndex = X86Registers::esp;
2847 #if WTF_CPU_X86_64
2848         static const RegisterID noBase2 = X86Registers::r13;
2849         static const RegisterID hasSib2 = X86Registers::r12;
2850
2851         // Registers r8 & above require a REX prefixe.
2852         inline bool regRequiresRex(int reg)
2853         {
2854             return (reg >= X86Registers::r8);
2855         }
2856
2857         // Format a REX prefix byte.
2858         inline void emitRex(bool w, int r, int x, int b)
2859         {
2860             m_buffer.putByteUnchecked(PRE_REX | ((int)w << 3) | ((r>>3)<<2) | ((x>>3)<<1) | (b>>3));
2861         }
2862
2863         // Used to plant a REX byte with REX.w set (for 64-bit operations).
2864         inline void emitRexW(int r, int x, int b)
2865         {
2866             emitRex(true, r, x, b);
2867         }
2868
2869         // Used for operations with byte operands - use byteRegRequiresRex() to check register operands,
2870         // regRequiresRex() to check other registers (i.e. address base & index).
2871         // 
2872         // NB: WebKit's use of emitRexIf() is limited such that the reqRequiresRex() checks are
2873         // not needed. SpiderMonkey extends oneByteOp8 functionality such that r, x, and b can
2874         // all be used.
2875         inline void emitRexIf(bool condition, int r, int x, int b)
2876         {
2877             if (condition || regRequiresRex(r) || regRequiresRex(x) || regRequiresRex(b))
2878                 emitRex(false, r, x, b);
2879         }
2880
2881         // Used for word sized operations, will plant a REX prefix if necessary (if any register is r8 or above).
2882         inline void emitRexIfNeeded(int r, int x, int b)
2883         {
2884             emitRexIf(regRequiresRex(r) || regRequiresRex(x) || regRequiresRex(b), r, x, b);
2885         }
2886 #else
2887         // No REX prefix bytes on 32-bit x86.
2888         inline bool regRequiresRex(int) { return false; }
2889         inline void emitRexIf(bool, int, int, int) {}
2890         inline void emitRexIfNeeded(int, int, int) {}
2891 #endif
2892
2893         enum ModRmMode {
2894             ModRmMemoryNoDisp,
2895             ModRmMemoryDisp8,
2896             ModRmMemoryDisp32,
2897             ModRmRegister
2898         };
2899
2900         void putModRm(ModRmMode mode, int reg, RegisterID rm)
2901         {
2902             m_buffer.putByteUnchecked((mode << 6) | ((reg & 7) << 3) | (rm & 7));
2903         }
2904
2905         void putModRmSib(ModRmMode mode, int reg, RegisterID base, RegisterID index, int scale)
2906         {
2907             ASSERT(mode != ModRmRegister);
2908
2909             putModRm(mode, reg, hasSib);
2910             m_buffer.putByteUnchecked((scale << 6) | ((index & 7) << 3) | (base & 7));
2911         }
2912
2913         void registerModRM(int reg, RegisterID rm)
2914         {
2915             putModRm(ModRmRegister, reg, rm);
2916         }
2917
2918         void memoryModRM(int reg, RegisterID base, int offset)
2919         {
2920             // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
2921 #if WTF_CPU_X86_64
2922             if ((base == hasSib) || (base == hasSib2)) {
2923 #else
2924             if (base == hasSib) {
2925 #endif
2926                 if (!offset) // No need to check if the base is noBase, since we know it is hasSib!
2927                     putModRmSib(ModRmMemoryNoDisp, reg, base, noIndex, 0);
2928                 else if (CAN_SIGN_EXTEND_8_32(offset)) {
2929                     putModRmSib(ModRmMemoryDisp8, reg, base, noIndex, 0);
2930                     m_buffer.putByteUnchecked(offset);
2931                 } else {
2932                     putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0);
2933                     m_buffer.putIntUnchecked(offset);
2934                 }
2935             } else {
2936 #if WTF_CPU_X86_64
2937                 if (!offset && (base != noBase) && (base != noBase2))
2938 #else
2939                 if (!offset && (base != noBase))
2940 #endif
2941                     putModRm(ModRmMemoryNoDisp, reg, base);
2942                 else if (CAN_SIGN_EXTEND_8_32(offset)) {
2943                     putModRm(ModRmMemoryDisp8, reg, base);
2944                     m_buffer.putByteUnchecked(offset);
2945                 } else {
2946                     putModRm(ModRmMemoryDisp32, reg, base);
2947                     m_buffer.putIntUnchecked(offset);
2948                 }
2949             }
2950         }
2951     
2952         void memoryModRM_disp32(int reg, RegisterID base, int offset)
2953         {
2954             // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
2955 #if WTF_CPU_X86_64
2956             if ((base == hasSib) || (base == hasSib2)) {
2957 #else
2958             if (base == hasSib) {
2959 #endif
2960                 putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0);
2961                 m_buffer.putIntUnchecked(offset);
2962             } else {
2963                 putModRm(ModRmMemoryDisp32, reg, base);
2964                 m_buffer.putIntUnchecked(offset);
2965             }
2966         }
2967     
2968         void memoryModRM(int reg, RegisterID base, RegisterID index, int scale, int offset)
2969         {
2970             ASSERT(index != noIndex);
2971
2972 #if WTF_CPU_X86_64
2973             if (!offset && (base != noBase) && (base != noBase2))
2974 #else
2975             if (!offset && (base != noBase))
2976 #endif
2977                 putModRmSib(ModRmMemoryNoDisp, reg, base, index, scale);
2978             else if (CAN_SIGN_EXTEND_8_32(offset)) {
2979                 putModRmSib(ModRmMemoryDisp8, reg, base, index, scale);
2980                 m_buffer.putByteUnchecked(offset);
2981             } else {
2982                 putModRmSib(ModRmMemoryDisp32, reg, base, index, scale);
2983                 m_buffer.putIntUnchecked(offset);
2984             }
2985         }
2986
2987 #if !WTF_CPU_X86_64
2988         void memoryModRM(int reg, const void* address)
2989         {
2990             // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32!
2991             putModRm(ModRmMemoryNoDisp, reg, noBase);
2992             m_buffer.putIntUnchecked(reinterpret_cast<int32_t>(address));
2993         }
2994 #endif
2995
2996         AssemblerBuffer m_buffer;
2997     } m_formatter;
2998 };
2999
3000 } // namespace JSC
3001
3002 #endif // ENABLE(ASSEMBLER) && CPU(X86)
3003
3004 #endif // X86Assembler_h