diff options
Diffstat (limited to 'libpixelflinger/codeflinger/x86/libenc/encoder.h')
-rw-r--r-- | libpixelflinger/codeflinger/x86/libenc/encoder.h | 717 |
1 files changed, 717 insertions, 0 deletions
diff --git a/libpixelflinger/codeflinger/x86/libenc/encoder.h b/libpixelflinger/codeflinger/x86/libenc/encoder.h new file mode 100644 index 0000000..9ac0219 --- /dev/null +++ b/libpixelflinger/codeflinger/x86/libenc/encoder.h @@ -0,0 +1,717 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @author Alexander V. Astapchuk + */ +/** + * @file + * @brief Simple interface for generating processor instructions. + * + * The interface works for both IA32 and EM64T. By default, only IA32 + * capabilities are presented. To enable EM64T feature, the _EM64T_ macro + * must be defined (and, of course, a proper library version to be used). + * + * The interface is based on the original ia32.h encoder interface, + * with some simplifications and add-ons - EM64T-specific, SSE and SSE2. + * + * The interface mostly intended for existing legacy code like LIL code + * generator. From the implementation point of view, it's just a wrapper + * around the EncoderBase functionality. + */ + +#ifndef _VM_ENCODER_H_ +#define _VM_ENCODER_H_ + +#include <limits.h> +#include "enc_base.h" +//#include "open/types.h" + +#ifdef _EM64T_ +// size of general-purpose value on the stack in bytes +#define GR_STACK_SIZE 8 +// size of floating-point value on the stack in bytes +#define FR_STACK_SIZE 8 + +#if defined(WIN32) || defined(_WIN64) + // maximum number of GP registers for inputs + const int MAX_GR = 4; + // maximum number of FP registers for inputs + const int MAX_FR = 4; + // WIN64 reserves 4 words for shadow space + const int SHADOW = 4 * GR_STACK_SIZE; +#else + // maximum number of GP registers for inputs + const int MAX_GR = 6; + // maximum number of FP registers for inputs + const int MAX_FR = 8; + // Linux x64 doesn't reserve shadow space + const int SHADOW = 0; +#endif + +#else +// size of general-purpose value on the stack in bytes +#define GR_STACK_SIZE 4 +// size of general-purpose value on the stack in bytes +#define FR_STACK_SIZE 8 + +// maximum number of GP registers for inputs +const int MAX_GR = 0; +// maximum number of FP registers for inputs +const int MAX_FR = 0; +#endif + +typedef enum Reg_No { +#ifdef _EM64T_ + rax_reg = 0,rbx_reg, rcx_reg, rdx_reg, + rdi_reg, rsi_reg, rsp_reg, rbp_reg, + r8_reg, r9_reg, r10_reg, r11_reg, + r12_reg, r13_reg, r14_reg, r15_reg, + xmm0_reg, xmm1_reg, xmm2_reg, xmm3_reg, + xmm4_reg, xmm5_reg, xmm6_reg, xmm7_reg, + xmm8_reg, xmm9_reg, xmm10_reg, xmm11_reg, + xmm12_reg, xmm13_reg, xmm14_reg, xmm15_reg, + +#else // !defined(_EM64T_) + + eax_reg = 0,ebx_reg, ecx_reg, edx_reg, + edi_reg, esi_reg, esp_reg, ebp_reg, + xmm0_reg, xmm1_reg, xmm2_reg, xmm3_reg, + xmm4_reg, xmm5_reg, xmm6_reg, xmm7_reg, + fs_reg, +#endif + /** @brief Total number of registers.*/ + n_reg +} Reg_No; +// +// instruction operand sizes: 8,16,32,64 bits +// +typedef enum Opnd_Size { + size_8 = 0, + size_16, + size_32, + size_64, + n_size, +#ifdef _EM64T_ + size_platf = size_64 +#else + size_platf = size_32 +#endif +} Opnd_Size; + +// +// opcodes for alu instructions +// +typedef enum ALU_Opcode { + add_opc = 0,or_opc, adc_opc, sbb_opc, + and_opc, sub_opc, xor_opc, cmp_opc, + n_alu +} ALU_Opcode; + +// +// opcodes for shift instructions +// +typedef enum Shift_Opcode { + shld_opc, shrd_opc, shl_opc, shr_opc, + sar_opc, ror_opc, max_shift_opcode=6, n_shift = 6 +} Shift_Opcode; + +typedef enum ConditionCode { + Condition_O = 0, + Condition_NO = 1, + Condition_B = 2, + Condition_NAE = Condition_B, + Condition_C = Condition_B, + Condition_NB = 3, + Condition_AE = Condition_NB, + Condition_NC = Condition_NB, + Condition_Z = 4, + Condition_E = Condition_Z, + Condition_NZ = 5, + Condition_NE = Condition_NZ, + Condition_BE = 6, + Condition_NA = Condition_BE, + Condition_NBE = 7, + Condition_A = Condition_NBE, + + Condition_S = 8, + Condition_NS = 9, + Condition_P = 10, + Condition_PE = Condition_P, + Condition_NP = 11, + Condition_PO = Condition_NP, + Condition_L = 12, + Condition_NGE = Condition_L, + Condition_NL = 13, + Condition_GE = Condition_NL, + Condition_LE = 14, + Condition_NG = Condition_LE, + Condition_NLE = 15, + Condition_G = Condition_NLE, + Condition_Count = 16 +} ConditionCode; + +// +// prefix code +// +typedef enum InstrPrefix { + no_prefix, + lock_prefix = 0xF0, + hint_branch_taken_prefix = 0x2E, + hint_branch_not_taken_prefix = 0x3E, + prefix_repne = 0xF2, + prefix_repnz = prefix_repne, + prefix_repe = 0xF3, + prefix_repz = prefix_repe, + prefix_rep = 0xF3, + prefix_cs = 0x2E, + prefix_ss = 0x36, + prefix_ds = 0x3E, + prefix_es = 0x26, + prefix_fs = 0x64, + prefix_gs = 0x65 +} InstrPrefix; + + +// +// an instruction operand +// +class Opnd { + +protected: + enum Tag { SignedImm, UnsignedImm, Reg, Mem, FP, XMM }; + + const Tag tag; + + Opnd(Tag t): tag(t) {} + +public: + void * operator new(size_t, void * mem) { + return mem; + } + + void operator delete(void *) {} + + void operator delete(void *, void *) {} + +private: + // disallow copying + Opnd(const Opnd &): tag(Mem) { assert(false); } + Opnd& operator=(const Opnd &) { assert(false); return *this; } +}; +typedef int I_32; +class Imm_Opnd: public Opnd { + +protected: + union { +#ifdef _EM64T_ + int64 value; + unsigned char bytes[8]; +#else + I_32 value; + unsigned char bytes[4]; +#endif + }; + Opnd_Size size; + +public: + Imm_Opnd(I_32 val, bool isSigned = true): + Opnd(isSigned ? SignedImm : UnsignedImm), value(val), size(size_32) { + if (isSigned) { + if (CHAR_MIN <= val && val <= CHAR_MAX) { + size = size_8; + } else if (SHRT_MIN <= val && val <= SHRT_MAX) { + size = size_16; + } + } else { + assert(val >= 0); + if (val <= UCHAR_MAX) { + size = size_8; + } else if (val <= USHRT_MAX) { + size = size_16; + } + } + } + Imm_Opnd(const Imm_Opnd& that): Opnd(that.tag), value(that.value), size(that.size) {}; + +#ifdef _EM64T_ + Imm_Opnd(Opnd_Size sz, int64 val, bool isSigned = true): + Opnd(isSigned ? SignedImm : UnsignedImm), value(val), size(sz) { +#ifndef NDEBUG + switch (size) { + case size_8: + assert(val == (int64)(I_8)val); + break; + case size_16: + assert(val == (int64)(int16)val); + break; + case size_32: + assert(val == (int64)(I_32)val); + break; + case size_64: + break; + case n_size: + assert(false); + break; + } +#endif // NDEBUG + } + + int64 get_value() const { return value; } + +#else + + Imm_Opnd(Opnd_Size sz, I_32 val, int isSigned = true): + Opnd(isSigned ? SignedImm : UnsignedImm), value(val), size(sz) { +#ifndef NDEBUG + switch (size) { + case size_8: + assert((I_32)val == (I_32)(I_8)val); + break; + case size_16: + assert((I_32)val == (I_32)(int16)val); + break; + case size_32: + break; + case size_64: + case n_size: + assert(false); + break; + } +#endif // NDEBUG + } + + I_32 get_value() const { return value; } + +#endif + Opnd_Size get_size() const { return size; } + bool is_signed() const { return tag == SignedImm; } +}; + +class RM_Opnd: public Opnd { + +public: + bool is_reg() const { return tag != SignedImm && tag != UnsignedImm && tag != Mem; } + +protected: + RM_Opnd(Tag t): Opnd(t) {} + +private: + // disallow copying + RM_Opnd(const RM_Opnd &): Opnd(Reg) { assert(false); } +}; + +class R_Opnd: public RM_Opnd { + +protected: + Reg_No _reg_no; + +public: + R_Opnd(Reg_No r): RM_Opnd(Reg), _reg_no(r) {} + Reg_No reg_no() const { return _reg_no; } + +private: + // disallow copying + R_Opnd(const R_Opnd &): RM_Opnd(Reg) { assert(false); } +}; + +// +// a memory operand with displacement +// Can also serve as a full memory operand with base,index, displacement and scale. +// Use n_reg to specify 'no register', say, for index. +class M_Opnd: public RM_Opnd { + +protected: + Imm_Opnd m_disp; + Imm_Opnd m_scale; + R_Opnd m_index; + R_Opnd m_base; + +public: + //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): + 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): + 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): + RM_Opnd(Mem), m_disp(disp), m_scale(scale), m_index(rindex), m_base(rbase) {} + M_Opnd(const M_Opnd & that) : RM_Opnd(Mem), + m_disp((int)that.m_disp.get_value()), m_scale((int)that.m_scale.get_value()), + m_index(that.m_index.reg_no()), m_base(that.m_base.reg_no()) + {} + // + inline const R_Opnd & base(void) const { return m_base; } + inline const R_Opnd & index(void) const { return m_index; } + inline const Imm_Opnd & scale(void) const { return m_scale; } + inline const Imm_Opnd & disp(void) const { return m_disp; } +}; + +// +// a memory operand with base register and displacement +// +class M_Base_Opnd: public M_Opnd { + +public: + M_Base_Opnd(Reg_No base, I_32 disp) : M_Opnd(disp, base, n_reg, 0) {} + +private: + // disallow copying - but it leads to ICC errors #734 in encoder.inl + // M_Base_Opnd(const M_Base_Opnd &): M_Opnd(0) { assert(false); } +}; + +// +// a memory operand with base register, scaled index register +// and displacement. +// +class M_Index_Opnd : public M_Opnd { + +public: + M_Index_Opnd(Reg_No base, Reg_No index, I_32 disp, unsigned scale): + M_Opnd(disp, base, index, scale) {} + +private: + // disallow copying - but it leads to ICC errors #734 in encoder.inl + // M_Index_Opnd(const M_Index_Opnd &): M_Opnd(0) { assert(false); } +}; + +class XMM_Opnd : public Opnd { + +protected: + unsigned m_idx; + +public: + XMM_Opnd(unsigned _idx): Opnd(XMM), m_idx(_idx) {}; + unsigned get_idx( void ) const { return m_idx; }; + +private: + // disallow copying + XMM_Opnd(const XMM_Opnd &): Opnd(XMM) { assert(false); } +}; + +// +// operand structures for ia32 registers +// +#ifdef _EM64T_ + +extern R_Opnd rax_opnd; +extern R_Opnd rcx_opnd; +extern R_Opnd rdx_opnd; +extern R_Opnd rbx_opnd; +extern R_Opnd rdi_opnd; +extern R_Opnd rsi_opnd; +extern R_Opnd rsp_opnd; +extern R_Opnd rbp_opnd; + +extern R_Opnd r8_opnd; +extern R_Opnd r9_opnd; +extern R_Opnd r10_opnd; +extern R_Opnd r11_opnd; +extern R_Opnd r12_opnd; +extern R_Opnd r13_opnd; +extern R_Opnd r14_opnd; +extern R_Opnd r15_opnd; + +extern XMM_Opnd xmm8_opnd; +extern XMM_Opnd xmm9_opnd; +extern XMM_Opnd xmm10_opnd; +extern XMM_Opnd xmm11_opnd; +extern XMM_Opnd xmm12_opnd; +extern XMM_Opnd xmm13_opnd; +extern XMM_Opnd xmm14_opnd; +extern XMM_Opnd xmm15_opnd; +#else + +extern R_Opnd eax_opnd; +extern R_Opnd ecx_opnd; +extern R_Opnd edx_opnd; +extern R_Opnd ebx_opnd; +extern R_Opnd esp_opnd; +extern R_Opnd ebp_opnd; +extern R_Opnd esi_opnd; +extern R_Opnd edi_opnd; + +#endif // _EM64T_ + +extern XMM_Opnd xmm0_opnd; +extern XMM_Opnd xmm1_opnd; +extern XMM_Opnd xmm2_opnd; +extern XMM_Opnd xmm3_opnd; +extern XMM_Opnd xmm4_opnd; +extern XMM_Opnd xmm5_opnd; +extern XMM_Opnd xmm6_opnd; +extern XMM_Opnd xmm7_opnd; + +#ifdef NO_ENCODER_INLINE + #define ENCODER_DECLARE_EXPORT +#else + #define ENCODER_DECLARE_EXPORT inline + #include "encoder.inl" +#endif + +// prefix +ENCODER_DECLARE_EXPORT char * prefix(char * stream, InstrPrefix p); + +// stack push and pop instructions +ENCODER_DECLARE_EXPORT char * push(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * push(char * stream, const Imm_Opnd & imm); +ENCODER_DECLARE_EXPORT char * pop(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); + +// cmpxchg or xchg +ENCODER_DECLARE_EXPORT char * cmpxchg(char * stream, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * xchg(char * stream, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz = size_platf); + +// inc(rement), dec(rement), not, neg(ate) instructions +ENCODER_DECLARE_EXPORT char * inc(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * dec(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * _not(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * neg(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * nop(char * stream); +ENCODER_DECLARE_EXPORT char * int3(char * stream); + +// alu instructions: add, or, adc, sbb, and, sub, xor, cmp +ENCODER_DECLARE_EXPORT char * alu(char * stream, ALU_Opcode opc, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * alu(char * stream, ALU_Opcode opc, const M_Opnd & m, const R_Opnd & r, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * alu(char * stream, ALU_Opcode opc, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf); + +// test instruction +ENCODER_DECLARE_EXPORT char * test(char * stream, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * test(char * stream, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz = size_platf); + +// shift instructions: shl, shr, sar, shld, shrd, ror +ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode opc, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode opc, const RM_Opnd & rm, Opnd_Size sz = size_platf); +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); +ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode opc, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz = size_platf); + +// multiply instructions: mul, imul +ENCODER_DECLARE_EXPORT char * mul(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * imul(char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * imul(char * stream, const R_Opnd & r, const Imm_Opnd & imm, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * imul(char * stream, const R_Opnd & r, const RM_Opnd & rm, const Imm_Opnd& imm, Opnd_Size sz = size_platf); + +// divide instructions: div, idiv +ENCODER_DECLARE_EXPORT char * idiv(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * div(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); + +// data movement: mov +ENCODER_DECLARE_EXPORT char * mov(char * stream, const M_Opnd & m, const R_Opnd & r, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * mov(char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * mov(char * stream, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz = size_platf); + +ENCODER_DECLARE_EXPORT char * movsx( char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * movzx( char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf); + +ENCODER_DECLARE_EXPORT char * movd(char * stream, const RM_Opnd & rm, const XMM_Opnd & xmm); +ENCODER_DECLARE_EXPORT char * movd(char * stream, const XMM_Opnd & xmm, const RM_Opnd & rm); +ENCODER_DECLARE_EXPORT char * movq(char * stream, const RM_Opnd & rm, const XMM_Opnd & xmm); +ENCODER_DECLARE_EXPORT char * movq(char * stream, const XMM_Opnd & xmm, const RM_Opnd & rm); + +// sse mov +ENCODER_DECLARE_EXPORT char * sse_mov(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl); +ENCODER_DECLARE_EXPORT char * sse_mov(char * stream, const M_Opnd & mem, const XMM_Opnd & xmm, bool dbl); +ENCODER_DECLARE_EXPORT char * sse_mov(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); + +// sse add, sub, mul, div +ENCODER_DECLARE_EXPORT char * sse_add(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl); +ENCODER_DECLARE_EXPORT char * sse_add(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); + +ENCODER_DECLARE_EXPORT char * sse_sub(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl); +ENCODER_DECLARE_EXPORT char * sse_sub(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); + +ENCODER_DECLARE_EXPORT char * sse_mul(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl); +ENCODER_DECLARE_EXPORT char * sse_mul(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); + +ENCODER_DECLARE_EXPORT char * sse_div(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl); +ENCODER_DECLARE_EXPORT char * sse_div(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); + +// xor, compare +ENCODER_DECLARE_EXPORT char * sse_xor(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1); + +ENCODER_DECLARE_EXPORT char * sse_compare(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); +ENCODER_DECLARE_EXPORT char * sse_compare(char * stream, const XMM_Opnd & xmm0, const M_Opnd & mem, bool dbl); + +// sse conversions +ENCODER_DECLARE_EXPORT char * sse_cvt_si(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl); +ENCODER_DECLARE_EXPORT char * sse_cvtt2si(char * stream, const R_Opnd & reg, const M_Opnd & mem, bool dbl); +ENCODER_DECLARE_EXPORT char * sse_cvtt2si(char * stream, const R_Opnd & reg, const XMM_Opnd & xmm, bool dbl); +ENCODER_DECLARE_EXPORT char * sse_cvt_fp2dq(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); +ENCODER_DECLARE_EXPORT char * sse_cvt_dq2fp(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl); +ENCODER_DECLARE_EXPORT char * sse_d2s(char * stream, const XMM_Opnd & xmm0, const M_Opnd & mem64); +ENCODER_DECLARE_EXPORT char * sse_d2s(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1); +ENCODER_DECLARE_EXPORT char * sse_s2d(char * stream, const XMM_Opnd & xmm0, const M_Opnd & mem32); +ENCODER_DECLARE_EXPORT char * sse_s2d(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1); + +// condition operations +ENCODER_DECLARE_EXPORT char * cmov(char * stream, ConditionCode cc, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * setcc(char * stream, ConditionCode cc, const RM_Opnd & rm8); + +// load effective address: lea +ENCODER_DECLARE_EXPORT char * lea(char * stream, const R_Opnd & r, const M_Opnd & m, Opnd_Size sz = size_platf); +ENCODER_DECLARE_EXPORT char * cdq(char * stream); +ENCODER_DECLARE_EXPORT char * wait(char * stream); + +// control-flow instructions +ENCODER_DECLARE_EXPORT char * loop(char * stream, const Imm_Opnd & imm); + +// jump with 8-bit relative +ENCODER_DECLARE_EXPORT char * jump8(char * stream, const Imm_Opnd & imm); + +// jump with 32-bit relative +ENCODER_DECLARE_EXPORT char * jump32(char * stream, const Imm_Opnd & imm); + +// register indirect jump +ENCODER_DECLARE_EXPORT char * jump(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); + +// jump to target address +ENCODER_DECLARE_EXPORT char *jump(char * stream, char *target); + +// jump with displacement +//char * jump(char * stream, I_32 disp); + +// conditional branch with 8-bit branch offset +ENCODER_DECLARE_EXPORT char * branch8(char * stream, ConditionCode cc, const Imm_Opnd & imm, InstrPrefix prefix = no_prefix); + +// conditional branch with 32-bit branch offset +ENCODER_DECLARE_EXPORT char * branch32(char * stream, ConditionCode cc, const Imm_Opnd & imm, InstrPrefix prefix = no_prefix); + +// conditional branch with target label address +//char * branch(char * stream, ConditionCode cc, const char * target, InstrPrefix prefix = no_prefix); + +// conditional branch with displacement immediate +ENCODER_DECLARE_EXPORT char * branch(char * stream, ConditionCode cc, I_32 disp, InstrPrefix prefix = no_prefix); + +// call with displacement +ENCODER_DECLARE_EXPORT char * call(char * stream, const Imm_Opnd & imm); + +// indirect call through register or memory location +ENCODER_DECLARE_EXPORT char * call(char * stream, const RM_Opnd & rm, Opnd_Size sz = size_platf); + +// call target address +ENCODER_DECLARE_EXPORT char * call(char * stream, const char * target); + +// return instruction +ENCODER_DECLARE_EXPORT char * ret(char * stream); +ENCODER_DECLARE_EXPORT char * ret(char * stream, unsigned short pop); +ENCODER_DECLARE_EXPORT char * ret(char * stream, const Imm_Opnd & imm); + +// string operations +ENCODER_DECLARE_EXPORT char * set_d(char * stream, bool set); +ENCODER_DECLARE_EXPORT char * scas(char * stream, unsigned char prefix); +ENCODER_DECLARE_EXPORT char * stos(char * stream, unsigned char prefix); + +// floating-point instructions + +// st(0) = st(0) fp_op m{32,64}real +//!char * fp_op_mem(char * stream, FP_Opcode opc,const M_Opnd& mem,int is_double); + +// st(0) = st(0) fp_op st(i) +//!char *fp_op(char * stream, FP_Opcode opc,unsigned i); + +// st(i) = st(i) fp_op st(0) ; optionally pop stack +//!char * fp_op(char * stream, FP_Opcode opc,unsigned i,unsigned pop_stk); + +// compare st(0),st(1) and pop stack twice +//!char * fcompp(char * stream); +ENCODER_DECLARE_EXPORT char * fldcw(char * stream, const M_Opnd & mem); +ENCODER_DECLARE_EXPORT char * fnstcw(char * stream, const M_Opnd & mem); +ENCODER_DECLARE_EXPORT char * fnstsw(char * stream); +//!char * fchs(char * stream); +//!char * frem(char * stream); +//!char * fxch(char * stream,unsigned i); +//!char * fcomip(char * stream, unsigned i); + +// load from memory (as fp) into fp register stack +ENCODER_DECLARE_EXPORT char * fld(char * stream, const M_Opnd & m, bool is_double); +//!char *fld80(char * stream,const M_Opnd& mem); + +// load from memory (as int) into fp register stack +//!char * fild(char * stream,const M_Opnd& mem,int is_long); + +// push st(i) onto fp register stack +//!char * fld(char * stream,unsigned i); + +// push the constants 0.0 and 1.0 onto the fp register stack +//!char * fldz(char * stream); +//!char * fld1(char * stream); + +// store stack to memory (as int), always popping the stack +ENCODER_DECLARE_EXPORT char * fist(char * stream, const M_Opnd & mem, bool is_long, bool pop_stk); +// store stack to to memory (as fp), optionally popping the stack +ENCODER_DECLARE_EXPORT char * fst(char * stream, const M_Opnd & m, bool is_double, bool pop_stk); +// store ST(0) to ST(i), optionally popping the stack. Takes 1 clock +ENCODER_DECLARE_EXPORT char * fst(char * stream, unsigned i, bool pop_stk); + +//!char * pushad(char * stream); +//!char * pushfd(char * stream); +//!char * popad(char * stream); +//!char * popfd(char * stream); + +// stack frame allocation instructions: enter & leave +// +// enter frame_size +// +// is equivalent to: +// +// push ebp +// mov ebp,esp +// sub esp,frame_size +// +//!char *enter(char * stream,const Imm_Opnd& imm); + +// leave +// is equivalent to: +// +// mov esp,ebp +// pop ebp +//!char *leave(char * stream); + +// sahf loads SF, ZF, AF, PF, and CF flags from eax +//!char *sahf(char * stream); + +// Intrinsic FP math functions + +//!char *math_fsin(char * stream); +//!char *math_fcos(char * stream); +//!char *math_fabs(char * stream); +//!char *math_fpatan(char * stream); +ENCODER_DECLARE_EXPORT char * fprem(char * stream); +ENCODER_DECLARE_EXPORT char * fprem1(char * stream); +//!char *math_frndint(char * stream); +//!char *math_fptan(char * stream); + +// +// Add 1-7 bytes padding, with as few instructions as possible, +// with no effect on the processor state (e.g., registers, flags) +// +//!char *padding(char * stream, unsigned num); + +// prolog and epilog code generation +//- char *prolog(char * stream,unsigned frame_size,unsigned reg_save_mask); +//- char *epilog(char * stream,unsigned reg_save_mask); + +//!extern R_Opnd reg_operand_array[]; + +// fsave and frstor +//!char *fsave(char * stream); +//!char *frstor(char * stream); + +// lahf : Load Status Flags into AH Register +//!char *lahf(char * stream); + +// mfence : Memory Fence +//!char *mfence(char * stream); + +#endif // _VM_ENCODER_H_ |