encoder.h revision 0c2dc522d0e120f346cf0a40c8cf0c93346131c2
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
72const int MAX_GR = 0;
73// maximum number of FP registers for inputs
74const int MAX_FR = 0;
75#endif
76
77typedef 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//
102typedef 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//
118typedef 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//
127typedef 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
132typedef 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//
170typedef 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//
192class Opnd {
193
194protected:
195    enum Tag { SignedImm, UnsignedImm, Reg, Mem, FP, XMM };
196
197    const Tag  tag;
198
199    Opnd(Tag t): tag(t) {}
200
201public:
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
210private:
211    // disallow copying
212    Opnd(const Opnd &): tag(Mem) { assert(false); }
213    Opnd& operator=(const Opnd &) { assert(false); return *this; }
214};
215typedef int I_32;
216class Imm_Opnd: public Opnd {
217
218protected:
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
230public:
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
304class RM_Opnd: public Opnd {
305
306public:
307    bool is_reg() const { return tag != SignedImm && tag != UnsignedImm && tag != Mem; }
308
309protected:
310    RM_Opnd(Tag t): Opnd(t) {}
311
312private:
313    // disallow copying
314    RM_Opnd(const RM_Opnd &): Opnd(Reg) { assert(false); }
315};
316
317class R_Opnd: public RM_Opnd {
318
319protected:
320    Reg_No      _reg_no;
321
322public:
323    R_Opnd(Reg_No r): RM_Opnd(Reg), _reg_no(r) {}
324    Reg_No  reg_no() const { return _reg_no; }
325
326private:
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.
335class M_Opnd: public RM_Opnd {
336
337protected:
338    Imm_Opnd        m_disp;
339    Imm_Opnd        m_scale;
340    R_Opnd          m_index;
341    R_Opnd          m_base;
342
343public:
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//
365class M_Base_Opnd: public M_Opnd {
366
367public:
368    M_Base_Opnd(Reg_No base, I_32 disp) : M_Opnd(disp, base, n_reg, 0) {}
369
370private:
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//
379class M_Index_Opnd : public M_Opnd {
380
381public:
382    M_Index_Opnd(Reg_No base, Reg_No index, I_32 disp, unsigned scale):
383        M_Opnd(disp, base, index, scale) {}
384
385private:
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
390class XMM_Opnd : public Opnd {
391
392protected:
393    unsigned        m_idx;
394
395public:
396    XMM_Opnd(unsigned _idx): Opnd(XMM), m_idx(_idx) {};
397    unsigned get_idx( void ) const { return m_idx; };
398
399private:
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
409extern R_Opnd rax_opnd;
410extern R_Opnd rcx_opnd;
411extern R_Opnd rdx_opnd;
412extern R_Opnd rbx_opnd;
413extern R_Opnd rdi_opnd;
414extern R_Opnd rsi_opnd;
415extern R_Opnd rsp_opnd;
416extern R_Opnd rbp_opnd;
417
418extern R_Opnd r8_opnd;
419extern R_Opnd r9_opnd;
420extern R_Opnd r10_opnd;
421extern R_Opnd r11_opnd;
422extern R_Opnd r12_opnd;
423extern R_Opnd r13_opnd;
424extern R_Opnd r14_opnd;
425extern R_Opnd r15_opnd;
426
427extern XMM_Opnd xmm8_opnd;
428extern XMM_Opnd xmm9_opnd;
429extern XMM_Opnd xmm10_opnd;
430extern XMM_Opnd xmm11_opnd;
431extern XMM_Opnd xmm12_opnd;
432extern XMM_Opnd xmm13_opnd;
433extern XMM_Opnd xmm14_opnd;
434extern XMM_Opnd xmm15_opnd;
435#else
436
437extern R_Opnd eax_opnd;
438extern R_Opnd ecx_opnd;
439extern R_Opnd edx_opnd;
440extern R_Opnd ebx_opnd;
441extern R_Opnd esp_opnd;
442extern R_Opnd ebp_opnd;
443extern R_Opnd esi_opnd;
444extern R_Opnd edi_opnd;
445
446#endif // _EM64T_
447
448extern XMM_Opnd xmm0_opnd;
449extern XMM_Opnd xmm1_opnd;
450extern XMM_Opnd xmm2_opnd;
451extern XMM_Opnd xmm3_opnd;
452extern XMM_Opnd xmm4_opnd;
453extern XMM_Opnd xmm5_opnd;
454extern XMM_Opnd xmm6_opnd;
455extern 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
465ENCODER_DECLARE_EXPORT char * prefix(char * stream, InstrPrefix p);
466
467// stack push and pop instructions
468ENCODER_DECLARE_EXPORT char * push(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf);
469ENCODER_DECLARE_EXPORT char * push(char * stream, const Imm_Opnd & imm);
470ENCODER_DECLARE_EXPORT char * pop(char * stream,  const RM_Opnd & rm, Opnd_Size sz = size_platf);
471
472// cmpxchg or xchg
473ENCODER_DECLARE_EXPORT char * cmpxchg(char * stream, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz = size_platf);
474ENCODER_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
477ENCODER_DECLARE_EXPORT char * inc(char * stream,  const RM_Opnd & rm, Opnd_Size sz = size_platf);
478ENCODER_DECLARE_EXPORT char * dec(char * stream,  const RM_Opnd & rm, Opnd_Size sz = size_platf);
479ENCODER_DECLARE_EXPORT char * _not(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf);
480ENCODER_DECLARE_EXPORT char * neg(char * stream,  const RM_Opnd & rm, Opnd_Size sz = size_platf);
481ENCODER_DECLARE_EXPORT char * nop(char * stream);
482ENCODER_DECLARE_EXPORT char * int3(char * stream);
483
484// alu instructions: add, or, adc, sbb, and, sub, xor, cmp
485ENCODER_DECLARE_EXPORT char * alu(char * stream, ALU_Opcode opc, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf);
486ENCODER_DECLARE_EXPORT char * alu(char * stream, ALU_Opcode opc, const M_Opnd & m, const R_Opnd & r, Opnd_Size sz = size_platf);
487ENCODER_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
490ENCODER_DECLARE_EXPORT char * test(char * stream, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf);
491ENCODER_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
494ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode opc, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf);
495ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode opc, const RM_Opnd & rm, Opnd_Size sz = size_platf);
496ENCODER_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);
497ENCODER_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
500ENCODER_DECLARE_EXPORT char * mul(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf);
501ENCODER_DECLARE_EXPORT char * imul(char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf);
502ENCODER_DECLARE_EXPORT char * imul(char * stream, const R_Opnd & r, const Imm_Opnd & imm, Opnd_Size sz = size_platf);
503ENCODER_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
506ENCODER_DECLARE_EXPORT char * idiv(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf);
507
508// data movement: mov
509ENCODER_DECLARE_EXPORT char * mov(char * stream, const M_Opnd & m,  const R_Opnd & r, Opnd_Size sz = size_platf);
510ENCODER_DECLARE_EXPORT char * mov(char * stream, const R_Opnd & r,  const RM_Opnd & rm, Opnd_Size sz = size_platf);
511ENCODER_DECLARE_EXPORT char * mov(char * stream, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf);
512
513ENCODER_DECLARE_EXPORT char * movsx( char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf);
514ENCODER_DECLARE_EXPORT char * movzx( char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf);
515
516ENCODER_DECLARE_EXPORT char * movd(char * stream, const RM_Opnd & rm, const XMM_Opnd & xmm);
517ENCODER_DECLARE_EXPORT char * movd(char * stream, const XMM_Opnd & xmm, const RM_Opnd & rm);
518ENCODER_DECLARE_EXPORT char * movq(char * stream, const RM_Opnd & rm, const XMM_Opnd & xmm);
519ENCODER_DECLARE_EXPORT char * movq(char * stream, const XMM_Opnd & xmm, const RM_Opnd & rm);
520
521// sse mov
522ENCODER_DECLARE_EXPORT char * sse_mov(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl);
523ENCODER_DECLARE_EXPORT char * sse_mov(char * stream, const M_Opnd & mem, const XMM_Opnd & xmm, bool dbl);
524ENCODER_DECLARE_EXPORT char * sse_mov(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
525
526// sse add, sub, mul, div
527ENCODER_DECLARE_EXPORT char * sse_add(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl);
528ENCODER_DECLARE_EXPORT char * sse_add(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
529
530ENCODER_DECLARE_EXPORT char * sse_sub(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl);
531ENCODER_DECLARE_EXPORT char * sse_sub(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
532
533ENCODER_DECLARE_EXPORT char * sse_mul(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl);
534ENCODER_DECLARE_EXPORT char * sse_mul(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
535
536ENCODER_DECLARE_EXPORT char * sse_div(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl);
537ENCODER_DECLARE_EXPORT char * sse_div(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
538
539// xor, compare
540ENCODER_DECLARE_EXPORT char * sse_xor(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1);
541
542ENCODER_DECLARE_EXPORT char * sse_compare(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
543ENCODER_DECLARE_EXPORT char * sse_compare(char * stream, const XMM_Opnd & xmm0, const M_Opnd & mem, bool dbl);
544
545// sse conversions
546ENCODER_DECLARE_EXPORT char * sse_cvt_si(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl);
547ENCODER_DECLARE_EXPORT char * sse_cvtt2si(char * stream, const R_Opnd & reg, const M_Opnd & mem, bool dbl);
548ENCODER_DECLARE_EXPORT char * sse_cvtt2si(char * stream, const R_Opnd & reg, const XMM_Opnd & xmm, bool dbl);
549ENCODER_DECLARE_EXPORT char * sse_cvt_fp2dq(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
550ENCODER_DECLARE_EXPORT char * sse_cvt_dq2fp(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl);
551ENCODER_DECLARE_EXPORT char * sse_d2s(char * stream, const XMM_Opnd & xmm0, const M_Opnd & mem64);
552ENCODER_DECLARE_EXPORT char * sse_d2s(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1);
553ENCODER_DECLARE_EXPORT char * sse_s2d(char * stream, const XMM_Opnd & xmm0, const M_Opnd & mem32);
554ENCODER_DECLARE_EXPORT char * sse_s2d(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1);
555
556// condition operations
557ENCODER_DECLARE_EXPORT char * cmov(char * stream, ConditionCode cc, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf);
558ENCODER_DECLARE_EXPORT char * setcc(char * stream, ConditionCode cc, const RM_Opnd & rm8);
559
560// load effective address: lea
561ENCODER_DECLARE_EXPORT char * lea(char * stream, const R_Opnd & r, const M_Opnd & m, Opnd_Size sz = size_platf);
562ENCODER_DECLARE_EXPORT char * cdq(char * stream);
563ENCODER_DECLARE_EXPORT char * wait(char * stream);
564
565// control-flow instructions
566ENCODER_DECLARE_EXPORT char * loop(char * stream, const Imm_Opnd & imm);
567
568// jump with 8-bit relative
569ENCODER_DECLARE_EXPORT char * jump8(char * stream, const Imm_Opnd & imm);
570
571// jump with 32-bit relative
572ENCODER_DECLARE_EXPORT char * jump32(char * stream, const Imm_Opnd & imm);
573
574// register indirect jump
575ENCODER_DECLARE_EXPORT char * jump(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf);
576
577// jump to target address
578ENCODER_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
584ENCODER_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
587ENCODER_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
593ENCODER_DECLARE_EXPORT char * branch(char * stream, ConditionCode cc, I_32 disp, InstrPrefix prefix = no_prefix);
594
595// call with displacement
596ENCODER_DECLARE_EXPORT char * call(char * stream, const Imm_Opnd & imm);
597
598// indirect call through register or memory location
599ENCODER_DECLARE_EXPORT char * call(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf);
600
601// call target address
602ENCODER_DECLARE_EXPORT char * call(char * stream, const char * target);
603
604// return instruction
605ENCODER_DECLARE_EXPORT char * ret(char * stream);
606ENCODER_DECLARE_EXPORT char * ret(char * stream, unsigned short pop);
607ENCODER_DECLARE_EXPORT char * ret(char * stream, const Imm_Opnd & imm);
608
609// string operations
610ENCODER_DECLARE_EXPORT char * set_d(char * stream, bool set);
611ENCODER_DECLARE_EXPORT char * scas(char * stream, unsigned char prefix);
612ENCODER_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);
627ENCODER_DECLARE_EXPORT char * fldcw(char * stream, const M_Opnd & mem);
628ENCODER_DECLARE_EXPORT char * fnstcw(char * stream, const M_Opnd & mem);
629ENCODER_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
636ENCODER_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
650ENCODER_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
652ENCODER_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
654ENCODER_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);
689ENCODER_DECLARE_EXPORT char * fprem(char * stream);
690ENCODER_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