Home | History | Annotate | Download | only in libenc
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 /**
     18  * @author Alexander V. Astapchuk
     19  */
     20 /**
     21  * @file
     22  * @brief Simple interface for generating processor instructions.
     23  *
     24  * The interface works for both IA32 and EM64T. By default, only IA32
     25  * capabilities are presented. To enable EM64T feature, the _EM64T_ macro
     26  * must be defined (and, of course, a proper library version to be used).
     27  *
     28  * The interface is based on the original ia32.h encoder interface,
     29  * with some simplifications and add-ons - EM64T-specific, SSE and SSE2.
     30  *
     31  * The interface mostly intended for existing legacy code like LIL code
     32  * generator. From the implementation point of view, it's just a wrapper
     33  * around the EncoderBase functionality.
     34  */
     35 
     36 #ifndef _VM_ENCODER_H_
     37 #define _VM_ENCODER_H_
     38 
     39 #include <limits.h>
     40 #include "enc_base.h"
     41 //#include "open/types.h"
     42 
     43 #ifdef _EM64T_
     44 // size of general-purpose value on the stack in bytes
     45 #define GR_STACK_SIZE 8
     46 // size of floating-point value on the stack in bytes
     47 #define FR_STACK_SIZE 8
     48 
     49 #if defined(WIN32) || defined(_WIN64)
     50     // maximum number of GP registers for inputs
     51     const int MAX_GR = 4;
     52     // maximum number of FP registers for inputs
     53     const int MAX_FR = 4;
     54     // WIN64 reserves 4 words for shadow space
     55     const int SHADOW = 4 * GR_STACK_SIZE;
     56 #else
     57     // maximum number of GP registers for inputs
     58     const int MAX_GR = 6;
     59     // maximum number of FP registers for inputs
     60     const int MAX_FR = 8;
     61     // Linux x64 doesn't reserve shadow space
     62     const int SHADOW = 0;
     63 #endif
     64 
     65 #else
     66 // size of general-purpose value on the stack in bytes
     67 #define GR_STACK_SIZE 4
     68 // size of general-purpose value on the stack in bytes
     69 #define FR_STACK_SIZE 8
     70 
     71 // maximum number of GP registers for inputs
     72 const int MAX_GR = 0;
     73 // maximum number of FP registers for inputs
     74 const int MAX_FR = 0;
     75 #endif
     76 
     77 typedef enum Reg_No {
     78 #ifdef _EM64T_
     79     rax_reg = 0,rbx_reg,    rcx_reg,    rdx_reg,
     80     rdi_reg,    rsi_reg,    rsp_reg,    rbp_reg,
     81     r8_reg,     r9_reg,     r10_reg,    r11_reg,
     82     r12_reg,    r13_reg,    r14_reg,    r15_reg,
     83     xmm0_reg,   xmm1_reg,   xmm2_reg,   xmm3_reg,
     84     xmm4_reg,   xmm5_reg,   xmm6_reg,   xmm7_reg,
     85     xmm8_reg,   xmm9_reg,   xmm10_reg,  xmm11_reg,
     86     xmm12_reg,  xmm13_reg,  xmm14_reg,  xmm15_reg,
     87 
     88 #else   // !defined(_EM64T_)
     89 
     90     eax_reg = 0,ebx_reg,    ecx_reg,    edx_reg,
     91     edi_reg,    esi_reg,    esp_reg,    ebp_reg,
     92     xmm0_reg,   xmm1_reg,   xmm2_reg,   xmm3_reg,
     93     xmm4_reg,   xmm5_reg,   xmm6_reg,   xmm7_reg,
     94     fs_reg,
     95 #endif
     96     /** @brief Total number of registers.*/
     97     n_reg
     98 } Reg_No;
     99 //
    100 // instruction operand sizes: 8,16,32,64 bits
    101 //
    102 typedef enum Opnd_Size {
    103     size_8 = 0,
    104     size_16,
    105     size_32,
    106     size_64,
    107     n_size,
    108 #ifdef _EM64T_
    109     size_platf = size_64
    110 #else
    111     size_platf = size_32
    112 #endif
    113 } Opnd_Size;
    114 
    115 //
    116 // opcodes for alu instructions
    117 //
    118 typedef enum ALU_Opcode {
    119     add_opc = 0,or_opc,     adc_opc,    sbb_opc,
    120     and_opc,    sub_opc,    xor_opc,    cmp_opc,
    121     n_alu
    122 } ALU_Opcode;
    123 
    124 //
    125 // opcodes for shift instructions
    126 //
    127 typedef enum Shift_Opcode {
    128     shld_opc,   shrd_opc,   shl_opc,    shr_opc,
    129     sar_opc,    ror_opc, max_shift_opcode=6,     n_shift = 6
    130 } Shift_Opcode;
    131 
    132 typedef enum ConditionCode {
    133     Condition_O     = 0,
    134     Condition_NO    = 1,
    135     Condition_B     = 2,
    136     Condition_NAE   = Condition_B,
    137     Condition_C     = Condition_B,
    138     Condition_NB    = 3,
    139     Condition_AE    = Condition_NB,
    140     Condition_NC    = Condition_NB,
    141     Condition_Z     = 4,
    142     Condition_E     = Condition_Z,
    143     Condition_NZ    = 5,
    144     Condition_NE    = Condition_NZ,
    145     Condition_BE    = 6,
    146     Condition_NA    = Condition_BE,
    147     Condition_NBE   = 7,
    148     Condition_A     = Condition_NBE,
    149 
    150     Condition_S     = 8,
    151     Condition_NS    = 9,
    152     Condition_P     = 10,
    153     Condition_PE    = Condition_P,
    154     Condition_NP    = 11,
    155     Condition_PO    = Condition_NP,
    156     Condition_L     = 12,
    157     Condition_NGE   = Condition_L,
    158     Condition_NL    = 13,
    159     Condition_GE    = Condition_NL,
    160     Condition_LE    = 14,
    161     Condition_NG    = Condition_LE,
    162     Condition_NLE   = 15,
    163     Condition_G     = Condition_NLE,
    164     Condition_Count = 16
    165 } ConditionCode;
    166 
    167 //
    168 // prefix code
    169 //
    170 typedef enum InstrPrefix {
    171     no_prefix,
    172     lock_prefix                     = 0xF0,
    173     hint_branch_taken_prefix        = 0x2E,
    174     hint_branch_not_taken_prefix    = 0x3E,
    175     prefix_repne                    = 0xF2,
    176     prefix_repnz                    = prefix_repne,
    177     prefix_repe                     = 0xF3,
    178     prefix_repz                     = prefix_repe,
    179     prefix_rep                      = 0xF3,
    180     prefix_cs                       = 0x2E,
    181     prefix_ss                       = 0x36,
    182     prefix_ds                       = 0x3E,
    183     prefix_es                       = 0x26,
    184     prefix_fs                       = 0x64,
    185     prefix_gs                       = 0x65
    186 } InstrPrefix;
    187 
    188 
    189 //
    190 // an instruction operand
    191 //
    192 class Opnd {
    193 
    194 protected:
    195     enum Tag { SignedImm, UnsignedImm, Reg, Mem, FP, XMM };
    196 
    197     const Tag  tag;
    198 
    199     Opnd(Tag t): tag(t) {}
    200 
    201 public:
    202     void * operator new(size_t, void * mem) {
    203         return mem;
    204     }
    205 
    206     void operator delete(void *) {}
    207 
    208     void operator delete(void *, void *) {}
    209 
    210 private:
    211     // disallow copying
    212     Opnd(const Opnd &): tag(Mem) { assert(false); }
    213     Opnd& operator=(const Opnd &) { assert(false); return *this; }
    214 };
    215 typedef int I_32;
    216 class Imm_Opnd: public Opnd {
    217 
    218 protected:
    219     union {
    220 #ifdef _EM64T_
    221         int64           value;
    222         unsigned char   bytes[8];
    223 #else
    224         I_32           value;
    225         unsigned char   bytes[4];
    226 #endif
    227     };
    228     Opnd_Size           size;
    229 
    230 public:
    231     Imm_Opnd(I_32 val, bool isSigned = true):
    232         Opnd(isSigned ? SignedImm : UnsignedImm), value(val), size(size_32) {
    233         if (isSigned) {
    234             if (CHAR_MIN <= val && val <= CHAR_MAX) {
    235                 size = size_8;
    236             } else if (SHRT_MIN <= val && val <= SHRT_MAX) {
    237                 size = size_16;
    238             }
    239         } else {
    240             assert(val >= 0);
    241             if (val <= UCHAR_MAX) {
    242                 size = size_8;
    243             } else if (val <= USHRT_MAX) {
    244                 size = size_16;
    245             }
    246         }
    247     }
    248     Imm_Opnd(const Imm_Opnd& that): Opnd(that.tag), value(that.value), size(that.size) {};
    249 
    250 #ifdef _EM64T_
    251     Imm_Opnd(Opnd_Size sz, int64 val, bool isSigned = true):
    252         Opnd(isSigned ? SignedImm : UnsignedImm), value(val), size(sz) {
    253 #ifndef NDEBUG
    254         switch (size) {
    255         case size_8:
    256             assert(val == (int64)(I_8)val);
    257             break;
    258         case size_16:
    259             assert(val == (int64)(int16)val);
    260             break;
    261         case size_32:
    262             assert(val == (int64)(I_32)val);
    263             break;
    264         case size_64:
    265             break;
    266         case n_size:
    267             assert(false);
    268             break;
    269         }
    270 #endif // NDEBUG
    271     }
    272 
    273     int64 get_value() const { return value; }
    274 
    275 #else
    276 
    277     Imm_Opnd(Opnd_Size sz, I_32 val, int isSigned = true):
    278         Opnd(isSigned ? SignedImm : UnsignedImm), value(val), size(sz) {
    279 #ifndef NDEBUG
    280         switch (size) {
    281         case size_8:
    282             assert((I_32)val == (I_32)(I_8)val);
    283             break;
    284         case size_16:
    285             assert((I_32)val == (I_32)(int16)val);
    286             break;
    287         case size_32:
    288             break;
    289         case size_64:
    290         case n_size:
    291             assert(false);
    292             break;
    293         }
    294 #endif // NDEBUG
    295     }
    296 
    297     I_32 get_value() const { return value; }
    298 
    299 #endif
    300     Opnd_Size get_size() const { return size; }
    301     bool      is_signed() const { return tag == SignedImm; }
    302 };
    303 
    304 class RM_Opnd: public Opnd {
    305 
    306 public:
    307     bool is_reg() const { return tag != SignedImm && tag != UnsignedImm && tag != Mem; }
    308 
    309 protected:
    310     RM_Opnd(Tag t): Opnd(t) {}
    311 
    312 private:
    313     // disallow copying
    314     RM_Opnd(const RM_Opnd &): Opnd(Reg) { assert(false); }
    315 };
    316 
    317 class R_Opnd: public RM_Opnd {
    318 
    319 protected:
    320     Reg_No      _reg_no;
    321 
    322 public:
    323     R_Opnd(Reg_No r): RM_Opnd(Reg), _reg_no(r) {}
    324     Reg_No  reg_no() const { return _reg_no; }
    325 
    326 private:
    327     // disallow copying
    328     R_Opnd(const R_Opnd &): RM_Opnd(Reg) { assert(false); }
    329 };
    330 
    331 //
    332 // a memory operand with displacement
    333 // Can also serve as a full memory operand with base,index, displacement and scale.
    334 // Use n_reg to specify 'no register', say, for index.
    335 class M_Opnd: public RM_Opnd {
    336 
    337 protected:
    338     Imm_Opnd        m_disp;
    339     Imm_Opnd        m_scale;
    340     R_Opnd          m_index;
    341     R_Opnd          m_base;
    342 
    343 public:
    344     //M_Opnd(Opnd_Size sz): RM_Opnd(Mem, K_M, sz), m_disp(0), m_scale(0), m_index(n_reg), m_base(n_reg) {}
    345     M_Opnd(I_32 disp):
    346         RM_Opnd(Mem), m_disp(disp), m_scale(0), m_index(n_reg), m_base(n_reg) {}
    347     M_Opnd(Reg_No rbase, I_32 rdisp):
    348         RM_Opnd(Mem), m_disp(rdisp), m_scale(0), m_index(n_reg), m_base(rbase) {}
    349     M_Opnd(I_32 disp, Reg_No rbase, Reg_No rindex, unsigned scale):
    350         RM_Opnd(Mem), m_disp(disp), m_scale(scale), m_index(rindex), m_base(rbase) {}
    351     M_Opnd(const M_Opnd & that) : RM_Opnd(Mem),
    352         m_disp((int)that.m_disp.get_value()), m_scale((int)that.m_scale.get_value()),
    353         m_index(that.m_index.reg_no()), m_base(that.m_base.reg_no())
    354         {}
    355     //
    356     inline const R_Opnd & base(void) const { return m_base; }
    357     inline const R_Opnd & index(void) const { return m_index; }
    358     inline const Imm_Opnd & scale(void) const { return m_scale; }
    359     inline const Imm_Opnd & disp(void) const { return m_disp; }
    360 };
    361 
    362 //
    363 //  a memory operand with base register and displacement
    364 //
    365 class M_Base_Opnd: public M_Opnd {
    366 
    367 public:
    368     M_Base_Opnd(Reg_No base, I_32 disp) : M_Opnd(disp, base, n_reg, 0) {}
    369 
    370 private:
    371     // disallow copying - but it leads to ICC errors #734 in encoder.inl
    372     // M_Base_Opnd(const M_Base_Opnd &): M_Opnd(0) { assert(false); }
    373 };
    374 
    375 //
    376 //  a memory operand with base register, scaled index register
    377 //  and displacement.
    378 //
    379 class M_Index_Opnd : public M_Opnd {
    380 
    381 public:
    382     M_Index_Opnd(Reg_No base, Reg_No index, I_32 disp, unsigned scale):
    383         M_Opnd(disp, base, index, scale) {}
    384 
    385 private:
    386     // disallow copying - but it leads to ICC errors #734 in encoder.inl
    387     // M_Index_Opnd(const M_Index_Opnd &): M_Opnd(0) { assert(false); }
    388 };
    389 
    390 class XMM_Opnd : public Opnd {
    391 
    392 protected:
    393     unsigned        m_idx;
    394 
    395 public:
    396     XMM_Opnd(unsigned _idx): Opnd(XMM), m_idx(_idx) {};
    397     unsigned get_idx( void ) const { return m_idx; };
    398 
    399 private:
    400     // disallow copying
    401     XMM_Opnd(const XMM_Opnd &): Opnd(XMM) { assert(false); }
    402 };
    403 
    404 //
    405 // operand structures for ia32 registers
    406 //
    407 #ifdef _EM64T_
    408 
    409 extern R_Opnd rax_opnd;
    410 extern R_Opnd rcx_opnd;
    411 extern R_Opnd rdx_opnd;
    412 extern R_Opnd rbx_opnd;
    413 extern R_Opnd rdi_opnd;
    414 extern R_Opnd rsi_opnd;
    415 extern R_Opnd rsp_opnd;
    416 extern R_Opnd rbp_opnd;
    417 
    418 extern R_Opnd r8_opnd;
    419 extern R_Opnd r9_opnd;
    420 extern R_Opnd r10_opnd;
    421 extern R_Opnd r11_opnd;
    422 extern R_Opnd r12_opnd;
    423 extern R_Opnd r13_opnd;
    424 extern R_Opnd r14_opnd;
    425 extern R_Opnd r15_opnd;
    426 
    427 extern XMM_Opnd xmm8_opnd;
    428 extern XMM_Opnd xmm9_opnd;
    429 extern XMM_Opnd xmm10_opnd;
    430 extern XMM_Opnd xmm11_opnd;
    431 extern XMM_Opnd xmm12_opnd;
    432 extern XMM_Opnd xmm13_opnd;
    433 extern XMM_Opnd xmm14_opnd;
    434 extern XMM_Opnd xmm15_opnd;
    435 #else
    436 
    437 extern R_Opnd eax_opnd;
    438 extern R_Opnd ecx_opnd;
    439 extern R_Opnd edx_opnd;
    440 extern R_Opnd ebx_opnd;
    441 extern R_Opnd esp_opnd;
    442 extern R_Opnd ebp_opnd;
    443 extern R_Opnd esi_opnd;
    444 extern R_Opnd edi_opnd;
    445 
    446 #endif // _EM64T_
    447 
    448 extern XMM_Opnd xmm0_opnd;
    449 extern XMM_Opnd xmm1_opnd;
    450 extern XMM_Opnd xmm2_opnd;
    451 extern XMM_Opnd xmm3_opnd;
    452 extern XMM_Opnd xmm4_opnd;
    453 extern XMM_Opnd xmm5_opnd;
    454 extern XMM_Opnd xmm6_opnd;
    455 extern XMM_Opnd xmm7_opnd;
    456 
    457 #ifdef NO_ENCODER_INLINE
    458     #define ENCODER_DECLARE_EXPORT
    459 #else
    460     #define ENCODER_DECLARE_EXPORT inline
    461     #include "encoder.inl"
    462 #endif
    463 
    464 // prefix
    465 ENCODER_DECLARE_EXPORT char * prefix(char * stream, InstrPrefix p);
    466 
    467 // stack push and pop instructions
    468 ENCODER_DECLARE_EXPORT char * push(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf);
    469 ENCODER_DECLARE_EXPORT char * push(char * stream, const Imm_Opnd & imm);
    470 ENCODER_DECLARE_EXPORT char * pop(char * stream,  const RM_Opnd & rm, Opnd_Size sz = size_platf);
    471 
    472 // cmpxchg or xchg
    473 ENCODER_DECLARE_EXPORT char * cmpxchg(char * stream, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz = size_platf);
    474 ENCODER_DECLARE_EXPORT char * xchg(char * stream, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz = size_platf);
    475 
    476 // inc(rement), dec(rement), not, neg(ate) instructions
    477 ENCODER_DECLARE_EXPORT char * inc(char * stream,  const RM_Opnd & rm, Opnd_Size sz = size_platf);
    478 ENCODER_DECLARE_EXPORT char * dec(char * stream,  const RM_Opnd & rm, Opnd_Size sz = size_platf);
    479 ENCODER_DECLARE_EXPORT char * _not(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf);
    480 ENCODER_DECLARE_EXPORT char * neg(char * stream,  const RM_Opnd & rm, Opnd_Size sz = size_platf);
    481 ENCODER_DECLARE_EXPORT char * nop(char * stream);
    482 ENCODER_DECLARE_EXPORT char * int3(char * stream);
    483 
    484 // alu instructions: add, or, adc, sbb, and, sub, xor, cmp
    485 ENCODER_DECLARE_EXPORT char * alu(char * stream, ALU_Opcode opc, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf);
    486 ENCODER_DECLARE_EXPORT char * alu(char * stream, ALU_Opcode opc, const M_Opnd & m, const R_Opnd & r, Opnd_Size sz = size_platf);
    487 ENCODER_DECLARE_EXPORT char * alu(char * stream, ALU_Opcode opc, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf);
    488 
    489 // test instruction
    490 ENCODER_DECLARE_EXPORT char * test(char * stream, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf);
    491 ENCODER_DECLARE_EXPORT char * test(char * stream, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz = size_platf);
    492 
    493 // shift instructions: shl, shr, sar, shld, shrd, ror
    494 ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode opc, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf);
    495 ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode opc, const RM_Opnd & rm, Opnd_Size sz = size_platf);
    496 ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode opc, const RM_Opnd & rm, const R_Opnd & r, const Imm_Opnd & imm, Opnd_Size sz = size_platf);
    497 ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode opc, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz = size_platf);
    498 
    499 // multiply instructions: mul, imul
    500 ENCODER_DECLARE_EXPORT char * mul(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf);
    501 ENCODER_DECLARE_EXPORT char * imul(char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf);
    502 ENCODER_DECLARE_EXPORT char * imul(char * stream, const R_Opnd & r, const Imm_Opnd & imm, Opnd_Size sz = size_platf);
    503 ENCODER_DECLARE_EXPORT char * imul(char * stream, const R_Opnd & r, const RM_Opnd & rm, const Imm_Opnd& imm, Opnd_Size sz = size_platf);
    504 
    505 // divide instructions: div, idiv
    506 ENCODER_DECLARE_EXPORT char * idiv(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf);
    507 
    508 // data movement: mov
    509 ENCODER_DECLARE_EXPORT char * mov(char * stream, const M_Opnd & m,  const R_Opnd & r, Opnd_Size sz = size_platf);
    510 ENCODER_DECLARE_EXPORT char * mov(char * stream, const R_Opnd & r,  const RM_Opnd & rm, Opnd_Size sz = size_platf);
    511 ENCODER_DECLARE_EXPORT char * mov(char * stream, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf);
    512 
    513 ENCODER_DECLARE_EXPORT char * movsx( char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf);
    514 ENCODER_DECLARE_EXPORT char * movzx( char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf);
    515 
    516 ENCODER_DECLARE_EXPORT char * movd(char * stream, const RM_Opnd & rm, const XMM_Opnd & xmm);
    517 ENCODER_DECLARE_EXPORT char * movd(char * stream, const XMM_Opnd & xmm, const RM_Opnd & rm);
    518 ENCODER_DECLARE_EXPORT char * movq(char * stream, const RM_Opnd & rm, const XMM_Opnd & xmm);
    519 ENCODER_DECLARE_EXPORT char * movq(char * stream, const XMM_Opnd & xmm, const RM_Opnd & rm);
    520 
    521 // sse mov
    522 ENCODER_DECLARE_EXPORT char * sse_mov(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl);
    523 ENCODER_DECLARE_EXPORT char * sse_mov(char * stream, const M_Opnd & mem, const XMM_Opnd & xmm, bool dbl);
    524 ENCODER_DECLARE_EXPORT char * sse_mov(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
    525 
    526 // sse add, sub, mul, div
    527 ENCODER_DECLARE_EXPORT char * sse_add(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl);
    528 ENCODER_DECLARE_EXPORT char * sse_add(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
    529 
    530 ENCODER_DECLARE_EXPORT char * sse_sub(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl);
    531 ENCODER_DECLARE_EXPORT char * sse_sub(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
    532 
    533 ENCODER_DECLARE_EXPORT char * sse_mul(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl);
    534 ENCODER_DECLARE_EXPORT char * sse_mul(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
    535 
    536 ENCODER_DECLARE_EXPORT char * sse_div(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl);
    537 ENCODER_DECLARE_EXPORT char * sse_div(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
    538 
    539 // xor, compare
    540 ENCODER_DECLARE_EXPORT char * sse_xor(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1);
    541 
    542 ENCODER_DECLARE_EXPORT char * sse_compare(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
    543 ENCODER_DECLARE_EXPORT char * sse_compare(char * stream, const XMM_Opnd & xmm0, const M_Opnd & mem, bool dbl);
    544 
    545 // sse conversions
    546 ENCODER_DECLARE_EXPORT char * sse_cvt_si(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl);
    547 ENCODER_DECLARE_EXPORT char * sse_cvtt2si(char * stream, const R_Opnd & reg, const M_Opnd & mem, bool dbl);
    548 ENCODER_DECLARE_EXPORT char * sse_cvtt2si(char * stream, const R_Opnd & reg, const XMM_Opnd & xmm, bool dbl);
    549 ENCODER_DECLARE_EXPORT char * sse_cvt_fp2dq(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
    550 ENCODER_DECLARE_EXPORT char * sse_cvt_dq2fp(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
    551 ENCODER_DECLARE_EXPORT char * sse_d2s(char * stream, const XMM_Opnd & xmm0, const M_Opnd & mem64);
    552 ENCODER_DECLARE_EXPORT char * sse_d2s(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1);
    553 ENCODER_DECLARE_EXPORT char * sse_s2d(char * stream, const XMM_Opnd & xmm0, const M_Opnd & mem32);
    554 ENCODER_DECLARE_EXPORT char * sse_s2d(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1);
    555 
    556 // condition operations
    557 ENCODER_DECLARE_EXPORT char * cmov(char * stream, ConditionCode cc, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf);
    558 ENCODER_DECLARE_EXPORT char * setcc(char * stream, ConditionCode cc, const RM_Opnd & rm8);
    559 
    560 // load effective address: lea
    561 ENCODER_DECLARE_EXPORT char * lea(char * stream, const R_Opnd & r, const M_Opnd & m, Opnd_Size sz = size_platf);
    562 ENCODER_DECLARE_EXPORT char * cdq(char * stream);
    563 ENCODER_DECLARE_EXPORT char * wait(char * stream);
    564 
    565 // control-flow instructions
    566 ENCODER_DECLARE_EXPORT char * loop(char * stream, const Imm_Opnd & imm);
    567 
    568 // jump with 8-bit relative
    569 ENCODER_DECLARE_EXPORT char * jump8(char * stream, const Imm_Opnd & imm);
    570 
    571 // jump with 32-bit relative
    572 ENCODER_DECLARE_EXPORT char * jump32(char * stream, const Imm_Opnd & imm);
    573 
    574 // register indirect jump
    575 ENCODER_DECLARE_EXPORT char * jump(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf);
    576 
    577 // jump to target address
    578 ENCODER_DECLARE_EXPORT char *jump(char * stream, char *target);
    579 
    580 // jump with displacement
    581 //char * jump(char * stream, I_32 disp);
    582 
    583 // conditional branch with 8-bit branch offset
    584 ENCODER_DECLARE_EXPORT char * branch8(char * stream, ConditionCode cc, const Imm_Opnd & imm, InstrPrefix prefix = no_prefix);
    585 
    586 // conditional branch with 32-bit branch offset
    587 ENCODER_DECLARE_EXPORT char * branch32(char * stream, ConditionCode cc, const Imm_Opnd & imm, InstrPrefix prefix = no_prefix);
    588 
    589 // conditional branch with target label address
    590 //char * branch(char * stream, ConditionCode cc, const char * target, InstrPrefix prefix = no_prefix);
    591 
    592 // conditional branch with displacement immediate
    593 ENCODER_DECLARE_EXPORT char * branch(char * stream, ConditionCode cc, I_32 disp, InstrPrefix prefix = no_prefix);
    594 
    595 // call with displacement
    596 ENCODER_DECLARE_EXPORT char * call(char * stream, const Imm_Opnd & imm);
    597 
    598 // indirect call through register or memory location
    599 ENCODER_DECLARE_EXPORT char * call(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf);
    600 
    601 // call target address
    602 ENCODER_DECLARE_EXPORT char * call(char * stream, const char * target);
    603 
    604 // return instruction
    605 ENCODER_DECLARE_EXPORT char * ret(char * stream);
    606 ENCODER_DECLARE_EXPORT char * ret(char * stream, unsigned short pop);
    607 ENCODER_DECLARE_EXPORT char * ret(char * stream, const Imm_Opnd & imm);
    608 
    609 // string operations
    610 ENCODER_DECLARE_EXPORT char * set_d(char * stream, bool set);
    611 ENCODER_DECLARE_EXPORT char * scas(char * stream, unsigned char prefix);
    612 ENCODER_DECLARE_EXPORT char * stos(char * stream, unsigned char prefix);
    613 
    614 // floating-point instructions
    615 
    616 // st(0) = st(0) fp_op m{32,64}real
    617 //!char * fp_op_mem(char * stream, FP_Opcode opc,const M_Opnd& mem,int is_double);
    618 
    619 // st(0) = st(0) fp_op st(i)
    620 //!char *fp_op(char * stream, FP_Opcode opc,unsigned i);
    621 
    622 // st(i) = st(i) fp_op st(0)    ; optionally pop stack
    623 //!char * fp_op(char * stream, FP_Opcode opc,unsigned i,unsigned pop_stk);
    624 
    625 // compare st(0),st(1) and pop stack twice
    626 //!char * fcompp(char * stream);
    627 ENCODER_DECLARE_EXPORT char * fldcw(char * stream, const M_Opnd & mem);
    628 ENCODER_DECLARE_EXPORT char * fnstcw(char * stream, const M_Opnd & mem);
    629 ENCODER_DECLARE_EXPORT char * fnstsw(char * stream);
    630 //!char * fchs(char * stream);
    631 //!char * frem(char * stream);
    632 //!char * fxch(char * stream,unsigned i);
    633 //!char * fcomip(char * stream, unsigned i);
    634 
    635 // load from memory (as fp) into fp register stack
    636 ENCODER_DECLARE_EXPORT char * fld(char * stream, const M_Opnd & m, bool is_double);
    637 //!char *fld80(char * stream,const M_Opnd& mem);
    638 
    639 // load from memory (as int) into fp register stack
    640 //!char * fild(char * stream,const M_Opnd& mem,int is_long);
    641 
    642 // push st(i) onto fp register stack
    643 //!char * fld(char * stream,unsigned i);
    644 
    645 // push the constants 0.0 and 1.0 onto the fp register stack
    646 //!char * fldz(char * stream);
    647 //!char * fld1(char * stream);
    648 
    649 // store stack to memory (as int), always popping the stack
    650 ENCODER_DECLARE_EXPORT char * fist(char * stream, const M_Opnd & mem, bool is_long, bool pop_stk);
    651 // store stack to to memory (as fp), optionally popping the stack
    652 ENCODER_DECLARE_EXPORT char * fst(char * stream, const M_Opnd & m, bool is_double, bool pop_stk);
    653 // store ST(0) to ST(i), optionally popping the stack. Takes 1 clock
    654 ENCODER_DECLARE_EXPORT char * fst(char * stream, unsigned i, bool pop_stk);
    655 
    656 //!char * pushad(char * stream);
    657 //!char * pushfd(char * stream);
    658 //!char * popad(char * stream);
    659 //!char * popfd(char * stream);
    660 
    661 // stack frame allocation instructions: enter & leave
    662 //
    663 //    enter frame_size
    664 //
    665 //    is equivalent to:
    666 //
    667 //    push    ebp
    668 //    mov     ebp,esp
    669 //    sub     esp,frame_size
    670 //
    671 //!char *enter(char * stream,const Imm_Opnd& imm);
    672 
    673 // leave
    674 // is equivalent to:
    675 //
    676 // mov        esp,ebp
    677 // pop        ebp
    678 //!char *leave(char * stream);
    679 
    680 // sahf  loads SF, ZF, AF, PF, and CF flags from eax
    681 //!char *sahf(char * stream);
    682 
    683 // Intrinsic FP math functions
    684 
    685 //!char *math_fsin(char * stream);
    686 //!char *math_fcos(char * stream);
    687 //!char *math_fabs(char * stream);
    688 //!char *math_fpatan(char * stream);
    689 ENCODER_DECLARE_EXPORT char * fprem(char * stream);
    690 ENCODER_DECLARE_EXPORT char * fprem1(char * stream);
    691 //!char *math_frndint(char * stream);
    692 //!char *math_fptan(char * stream);
    693 
    694 //
    695 // Add 1-7 bytes padding, with as few instructions as possible,
    696 // with no effect on the processor state (e.g., registers, flags)
    697 //
    698 //!char *padding(char * stream, unsigned num);
    699 
    700 // prolog and epilog code generation
    701 //- char *prolog(char * stream,unsigned frame_size,unsigned reg_save_mask);
    702 //- char *epilog(char * stream,unsigned reg_save_mask);
    703 
    704 //!extern R_Opnd reg_operand_array[];
    705 
    706 // fsave and frstor
    707 //!char *fsave(char * stream);
    708 //!char *frstor(char * stream);
    709 
    710 // lahf : Load Status Flags into AH Register
    711 //!char *lahf(char * stream);
    712 
    713 // mfence : Memory Fence
    714 //!char *mfence(char * stream);
    715 
    716 #endif // _VM_ENCODER_H_
    717