• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Opnd(Tag t)199     Opnd(Tag t): tag(t) {}
200 
201 public:
new(size_t,void * mem)202     void * operator new(size_t, void * mem) {
203         return mem;
204     }
205 
delete(void *)206     void operator delete(void *) {}
207 
delete(void *,void *)208     void operator delete(void *, void *) {}
209 
210 private:
211     // disallow copying
Opnd(const Opnd &)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     }
Imm_Opnd(const Imm_Opnd & that)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 
get_value()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 
get_value()297     I_32 get_value() const { return value; }
298 
299 #endif
get_size()300     Opnd_Size get_size() const { return size; }
is_signed()301     bool      is_signed() const { return tag == SignedImm; }
302 };
303 
304 class RM_Opnd: public Opnd {
305 
306 public:
is_reg()307     bool is_reg() const { return tag != SignedImm && tag != UnsignedImm && tag != Mem; }
308 
309 protected:
RM_Opnd(Tag t)310     RM_Opnd(Tag t): Opnd(t) {}
311 
312 private:
313     // disallow copying
RM_Opnd(const RM_Opnd &)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:
R_Opnd(Reg_No r)323     R_Opnd(Reg_No r): RM_Opnd(Reg), _reg_no(r) {}
reg_no()324     Reg_No  reg_no() const { return _reg_no; }
325 
326 private:
327     // disallow copying
R_Opnd(const R_Opnd &)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) {}
M_Opnd(I_32 disp)345     M_Opnd(I_32 disp):
346         RM_Opnd(Mem), m_disp(disp), m_scale(0), m_index(n_reg), m_base(n_reg) {}
M_Opnd(Reg_No rbase,I_32 rdisp)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) {}
M_Opnd(I_32 disp,Reg_No rbase,Reg_No rindex,unsigned scale)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) {}
M_Opnd(const M_Opnd & that)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     //
base(void)356     inline const R_Opnd & base(void) const { return m_base; }
index(void)357     inline const R_Opnd & index(void) const { return m_index; }
scale(void)358     inline const Imm_Opnd & scale(void) const { return m_scale; }
disp(void)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:
M_Base_Opnd(Reg_No base,I_32 disp)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:
M_Index_Opnd(Reg_No base,Reg_No index,I_32 disp,unsigned scale)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:
XMM_Opnd(unsigned _idx)396     XMM_Opnd(unsigned _idx): Opnd(XMM), m_idx(_idx) {};
get_idx(void)397     unsigned get_idx( void ) const { return m_idx; };
398 
399 private:
400     // disallow copying
XMM_Opnd(const XMM_Opnd &)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