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 #include <stdio.h>
     21 #include <assert.h>
     22 #include <limits.h>
     23 
     24 extern const RegName map_of_regno_2_regname[];
     25 extern const OpndSize map_of_EncoderOpndSize_2_RealOpndSize[];
     26 extern const Mnemonic map_of_alu_opcode_2_mnemonic[];
     27 extern const Mnemonic map_of_shift_opcode_2_mnemonic[];
     28 
     29 // S_ stands for 'Signed'
     30 extern const Mnemonic S_map_of_condition_code_2_branch_mnemonic[];
     31 // U_ stands for 'Unsigned'
     32 extern const Mnemonic U_map_of_condition_code_2_branch_mnemonic[];
     33 
     34 inline static RegName map_reg(Reg_No r) {
     35     assert(r >= 0 && r <= n_reg);
     36     return map_of_regno_2_regname[r];
     37 }
     38 
     39 inline static OpndSize map_size(Opnd_Size o_size) {
     40     assert(o_size >= 0 && o_size <= n_size);
     41     return map_of_EncoderOpndSize_2_RealOpndSize[o_size];
     42 }
     43 
     44 inline static Mnemonic map_alu(ALU_Opcode alu) {
     45     assert(alu >= 0 && alu < n_alu);
     46     return map_of_alu_opcode_2_mnemonic[alu];
     47 }
     48 
     49 inline static Mnemonic map_shift(Shift_Opcode shc) {
     50     assert(shc >= 0 && shc < n_shift);
     51     return map_of_shift_opcode_2_mnemonic[shc];
     52 }
     53 
     54 inline bool fit8(int64 val) {
     55     return (CHAR_MIN <= val) && (val <= CHAR_MAX);
     56 }
     57 
     58 inline bool fit32(int64 val) {
     59     return (INT_MIN <= val) && (val <= INT_MAX);
     60 }
     61 
     62 inline static void add_r(EncoderBase::Operands & args, const R_Opnd & r, Opnd_Size sz, OpndExt ext = OpndExt_None) {
     63     RegName reg = map_reg(r.reg_no());
     64     if (sz != n_size) {
     65         OpndSize size = map_size(sz);
     66         if (size != getRegSize(reg)) {
     67             reg = getAliasReg(reg, size);
     68         }
     69     }
     70     args.add(EncoderBase::Operand(reg, ext));
     71 }
     72 
     73 inline static void add_m(EncoderBase::Operands & args, const M_Opnd & m, Opnd_Size sz, OpndExt ext = OpndExt_None) {
     74         assert(n_size != sz);
     75         args.add(EncoderBase::Operand(map_size(sz),
     76             map_reg(m.base().reg_no()), map_reg(m.index().reg_no()),
     77             (unsigned)m.scale().get_value(), (int)m.disp().get_value(), ext));
     78 }
     79 
     80 inline static void add_rm(EncoderBase::Operands & args, const RM_Opnd & rm, Opnd_Size sz, OpndExt ext = OpndExt_None) {
     81     rm.is_reg() ? add_r(args, (R_Opnd &)rm, sz, ext) : add_m(args, (M_Opnd &)rm, sz, ext);
     82 }
     83 
     84 inline static void add_xmm(EncoderBase::Operands & args, const XMM_Opnd & xmm, bool dbl) {
     85     // Gregory -
     86     // XMM registers indexes in Reg_No enum are shifted by xmm0_reg, their indexes
     87     // don't start with 0, so it is necessary to subtract xmm0_reg index from
     88     // xmm.get_idx() value
     89     assert(xmm.get_idx() >= xmm0_reg);
     90     return args.add((RegName)( (dbl ? RegName_XMM0D : RegName_XMM0S) + xmm.get_idx() -
     91             xmm0_reg));
     92 }
     93 
     94 inline static void add_fp(EncoderBase::Operands & args, unsigned i, bool dbl) {
     95     return args.add((RegName)( (dbl ? RegName_FP0D : RegName_FP0S) + i));
     96 }
     97 
     98 inline static void add_imm(EncoderBase::Operands & args, const Imm_Opnd & imm) {
     99     assert(n_size != imm.get_size());
    100     args.add(EncoderBase::Operand(map_size(imm.get_size()), imm.get_value(),
    101         imm.is_signed() ? OpndExt_Signed : OpndExt_Zero));
    102 }
    103 
    104 ENCODER_DECLARE_EXPORT char * prefix(char * stream, InstrPrefix p) {
    105     *stream = (char)p;
    106     return stream + 1;
    107 }
    108 
    109 // stack push and pop instructions
    110 ENCODER_DECLARE_EXPORT char * push(char * stream, const RM_Opnd & rm, Opnd_Size sz) {
    111     EncoderBase::Operands args;
    112     add_rm(args, rm, sz);
    113     return (char*)EncoderBase::encode(stream, Mnemonic_PUSH, args);
    114 }
    115 
    116 ENCODER_DECLARE_EXPORT char * push(char * stream, const Imm_Opnd & imm) {
    117     EncoderBase::Operands args;
    118 #ifdef _EM64T_
    119     add_imm(args, imm);
    120 #else
    121     // we need this workaround to be compatible with the former ia32 encoder implementation
    122     add_imm(args, Imm_Opnd(size_32, imm.get_value()));
    123 #endif
    124     return EncoderBase::encode(stream, Mnemonic_PUSH, args);
    125 }
    126 
    127 ENCODER_DECLARE_EXPORT char * pop(char * stream, const RM_Opnd & rm, Opnd_Size sz) {
    128     EncoderBase::Operands args;
    129     add_rm(args, rm, sz);
    130     return (char*)EncoderBase::encode(stream, Mnemonic_POP, args);
    131 }
    132 
    133 // cmpxchg or xchg
    134 ENCODER_DECLARE_EXPORT char * cmpxchg(char * stream, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz) {
    135     EncoderBase::Operands args;
    136     add_rm(args, rm, sz);
    137     add_r(args, r, sz);
    138     RegName implicitReg = getAliasReg(RegName_EAX, map_size(sz));
    139     args.add(implicitReg);
    140     return (char*)EncoderBase::encode(stream, Mnemonic_CMPXCHG, args);
    141 }
    142 
    143 ENCODER_DECLARE_EXPORT char * xchg(char * stream, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz) {
    144     EncoderBase::Operands args;
    145     add_rm(args, rm, sz);
    146     add_r(args, r, sz);
    147     return (char*)EncoderBase::encode(stream, Mnemonic_XCHG, args);
    148 }
    149 
    150 // inc(rement), dec(rement), not, neg(ate) instructions
    151 ENCODER_DECLARE_EXPORT char * inc(char * stream, const RM_Opnd & rm, Opnd_Size sz) {
    152     EncoderBase::Operands args;
    153     add_rm(args, rm, sz);
    154     return (char*)EncoderBase::encode(stream, Mnemonic_INC, args);
    155 }
    156 
    157 ENCODER_DECLARE_EXPORT char * dec(char * stream, const RM_Opnd & rm, Opnd_Size sz) {
    158     EncoderBase::Operands args;
    159     add_rm(args, rm, sz);
    160     return (char*)EncoderBase::encode(stream, Mnemonic_DEC, args);
    161 }
    162 
    163 ENCODER_DECLARE_EXPORT char * _not(char * stream, const RM_Opnd & rm, Opnd_Size sz) {
    164     EncoderBase::Operands args;
    165     add_rm(args, rm, sz);
    166     return (char*)EncoderBase::encode(stream, Mnemonic_NOT, args);
    167 }
    168 
    169 ENCODER_DECLARE_EXPORT char * neg(char * stream, const RM_Opnd & rm, Opnd_Size sz) {
    170     EncoderBase::Operands args;
    171     add_rm(args, rm, sz);
    172     return (char*)EncoderBase::encode(stream, Mnemonic_NEG, args);
    173 }
    174 
    175 ENCODER_DECLARE_EXPORT char * nop(char * stream) {
    176     EncoderBase::Operands args;
    177     return (char*)EncoderBase::encode(stream, Mnemonic_NOP, args);
    178 }
    179 
    180 ENCODER_DECLARE_EXPORT char * int3(char * stream) {
    181     EncoderBase::Operands args;
    182     return (char*)EncoderBase::encode(stream, Mnemonic_INT3, args);
    183 }
    184 
    185 // alu instructions: add, or, adc, sbb, and, sub, xor, cmp
    186 ENCODER_DECLARE_EXPORT char * alu(char * stream, ALU_Opcode opc, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz) {
    187     EncoderBase::Operands args;
    188     add_rm(args, rm, sz);
    189     add_imm(args, imm);
    190     return (char*)EncoderBase::encode(stream, map_alu(opc), args);
    191 };
    192 
    193 ENCODER_DECLARE_EXPORT char * alu(char * stream, ALU_Opcode opc, const M_Opnd & m, const R_Opnd & r, Opnd_Size sz) {
    194     EncoderBase::Operands args;
    195     add_rm(args, m, sz);
    196     add_rm(args, r, sz);
    197     return (char*)EncoderBase::encode(stream, map_alu(opc), args);
    198 }
    199 
    200 ENCODER_DECLARE_EXPORT char * alu(char * stream, ALU_Opcode opc, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz) {
    201     EncoderBase::Operands args;
    202     add_rm(args, r, sz);
    203     add_rm(args, rm, sz);
    204     return (char*)EncoderBase::encode(stream, map_alu(opc), args);
    205 }
    206 
    207 // test instruction
    208 ENCODER_DECLARE_EXPORT char * test(char * stream, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz) {
    209     EncoderBase::Operands args;
    210     add_rm(args, rm, sz);
    211     assert(imm.get_size() <= sz);
    212     add_imm(args, imm);
    213     return (char*)EncoderBase::encode(stream, Mnemonic_TEST, args);
    214 }
    215 
    216 ENCODER_DECLARE_EXPORT char * test(char * stream, const RM_Opnd & rm, const R_Opnd & r, Opnd_Size sz) {
    217     EncoderBase::Operands args;
    218     add_rm(args, rm, sz);
    219     add_r(args, r, sz);
    220     return (char*)EncoderBase::encode(stream, Mnemonic_TEST, args);
    221 }
    222 
    223 // shift instructions: shl, shr, sar, shld, shrd
    224 ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode shc, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz) {
    225     EncoderBase::Operands args;
    226     add_rm(args, rm, sz);
    227     add_imm(args, imm);
    228     return (char*)EncoderBase::encode(stream, map_shift(shc), args);
    229 }
    230 
    231 ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode shc, const RM_Opnd & rm, Opnd_Size sz) {
    232     EncoderBase::Operands args;
    233     add_rm(args, rm, sz);
    234     args.add(RegName_CL);
    235     return (char*)EncoderBase::encode(stream, map_shift(shc), args);
    236 }
    237 
    238 ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode shc, const RM_Opnd & rm,
    239                             const R_Opnd & r, const Imm_Opnd & imm, Opnd_Size sz) {
    240     EncoderBase::Operands args;
    241     assert(shc == shld_opc || shc == shrd_opc);
    242     add_rm(args, rm, sz);
    243     add_r(args, r, sz);
    244     add_imm(args, imm);
    245     return (char*)EncoderBase::encode(stream, map_shift(shc), args);
    246 }
    247 
    248 ENCODER_DECLARE_EXPORT char * shift(char * stream, Shift_Opcode shc, const RM_Opnd & rm,
    249                             const R_Opnd & r, Opnd_Size sz) {
    250     EncoderBase::Operands args;
    251     assert(shc == shld_opc || shc == shrd_opc);
    252     add_rm(args, rm, sz);
    253     add_r(args, r, sz);
    254     args.add(RegName_CL);
    255     return (char*)EncoderBase::encode(stream, map_shift(shc), args);
    256 }
    257 
    258 // multiply instructions: mul, imul
    259 ENCODER_DECLARE_EXPORT char * mul(char * stream, const RM_Opnd & rm, Opnd_Size sz) {
    260     EncoderBase::Operands args;
    261     args.add(RegName_EDX);
    262     args.add(RegName_EAX);
    263     add_rm(args, rm, sz);
    264     return (char*)EncoderBase::encode(stream, Mnemonic_MUL, args);
    265 }
    266 
    267 ENCODER_DECLARE_EXPORT char * imul(char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz) {
    268     EncoderBase::Operands args;
    269     add_r(args, r, sz);
    270     add_rm(args, rm, sz);
    271     return (char*)EncoderBase::encode(stream, Mnemonic_IMUL, args);
    272 }
    273 
    274 ENCODER_DECLARE_EXPORT char * imul(char * stream, const R_Opnd & r, const Imm_Opnd & imm, Opnd_Size sz) {
    275     EncoderBase::Operands args;
    276     add_r(args, r, sz);
    277     add_imm(args, imm);
    278     return (char*)EncoderBase::encode(stream, Mnemonic_IMUL, args);
    279 }
    280 
    281 ENCODER_DECLARE_EXPORT char * imul(char * stream, const R_Opnd & r, const RM_Opnd & rm,
    282                            const Imm_Opnd & imm, Opnd_Size sz) {
    283     EncoderBase::Operands args;
    284     add_r(args, r, sz);
    285     add_rm(args, rm, sz);
    286     add_imm(args, imm);
    287     return (char*)EncoderBase::encode(stream, Mnemonic_IMUL, args);
    288 }
    289 
    290 // divide instructions: div, idiv
    291 ENCODER_DECLARE_EXPORT char * idiv(char * stream, const RM_Opnd & rm, Opnd_Size sz) {
    292     EncoderBase::Operands args;
    293 #ifdef _EM64T_
    294     add_r(args, rdx_opnd, sz);
    295     add_r(args, rax_opnd, sz);
    296 #else
    297     add_r(args, edx_opnd, sz);
    298     add_r(args, eax_opnd, sz);
    299 #endif
    300     add_rm(args, rm, sz);
    301     return (char*)EncoderBase::encode(stream, Mnemonic_IDIV, args);
    302 }
    303 
    304 // data movement: mov
    305 ENCODER_DECLARE_EXPORT char * mov(char * stream, const M_Opnd & m, const R_Opnd & r, Opnd_Size sz) {
    306     EncoderBase::Operands args;
    307     add_m(args, m, sz);
    308     add_r(args, r, sz);
    309     return (char*)EncoderBase::encode(stream, Mnemonic_MOV, args);
    310 }
    311 
    312 ENCODER_DECLARE_EXPORT char * mov(char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz) {
    313     EncoderBase::Operands args;
    314     add_r(args, r, sz);
    315     add_rm(args, rm, sz);
    316     return (char*)EncoderBase::encode(stream, Mnemonic_MOV, args);
    317 }
    318 
    319 ENCODER_DECLARE_EXPORT char * mov(char * stream, const RM_Opnd & rm, const Imm_Opnd & imm, Opnd_Size sz) {
    320     EncoderBase::Operands args;
    321     add_rm(args, rm, sz);
    322     add_imm(args, imm);
    323     return (char*)EncoderBase::encode(stream, Mnemonic_MOV, args);
    324 }
    325 
    326 ENCODER_DECLARE_EXPORT char * movd(char * stream, const RM_Opnd & rm, const XMM_Opnd & xmm) {
    327     EncoderBase::Operands args;
    328     add_rm(args, rm, size_32);
    329     add_xmm(args, xmm, false);
    330     return (char*)EncoderBase::encode(stream, Mnemonic_MOVD, args);
    331 }
    332 
    333 ENCODER_DECLARE_EXPORT char * movd(char * stream, const XMM_Opnd & xmm, const RM_Opnd & rm) {
    334     EncoderBase::Operands args;
    335     add_xmm(args, xmm, false);
    336     add_rm(args, rm, size_32);
    337     return (char*)EncoderBase::encode(stream, Mnemonic_MOVD, args);
    338 }
    339 
    340 ENCODER_DECLARE_EXPORT char * movq(char * stream, const RM_Opnd & rm, const XMM_Opnd & xmm) {
    341     EncoderBase::Operands args;
    342     add_rm(args, rm, size_64);
    343     add_xmm(args, xmm, true);
    344     return (char*)EncoderBase::encode(stream, Mnemonic_MOVQ, args);
    345 }
    346 
    347 ENCODER_DECLARE_EXPORT char * movq(char * stream, const XMM_Opnd & xmm, const RM_Opnd & rm) {
    348     EncoderBase::Operands args;
    349     add_xmm(args, xmm, true);
    350     add_rm(args, rm, size_64);
    351     return (char*)EncoderBase::encode(stream, Mnemonic_MOVQ, args);
    352 }
    353 
    354 ENCODER_DECLARE_EXPORT char * movsx(char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz) {
    355     EncoderBase::Operands args;
    356     add_r(args, r, n_size);
    357     add_rm(args, rm, sz, OpndExt_Signed);
    358     return (char*)EncoderBase::encode(stream, Mnemonic_MOVSX, args);
    359 }
    360 
    361 ENCODER_DECLARE_EXPORT char * movzx(char * stream, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz) {
    362     EncoderBase::Operands args;
    363     add_r(args, r, n_size);
    364     // movzx r64, r/m32 is not available on em64t
    365     // mov r32, r/m32 should zero out upper bytes
    366     assert(sz <= size_16);
    367     add_rm(args, rm, sz, OpndExt_Zero);
    368     return (char*)EncoderBase::encode(stream, Mnemonic_MOVZX, args);
    369 }
    370 
    371 // sse mov
    372 ENCODER_DECLARE_EXPORT char * sse_mov(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl) {
    373     EncoderBase::Operands args;
    374     add_xmm(args, xmm, dbl);
    375     add_m(args, mem, dbl ? size_64 : size_32);
    376     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_MOVSD : Mnemonic_MOVSS, args);
    377 }
    378 
    379 ENCODER_DECLARE_EXPORT char * sse_mov(char * stream, const M_Opnd &  mem, const XMM_Opnd & xmm, bool dbl) {
    380     EncoderBase::Operands args;
    381     add_m(args, mem, dbl ? size_64 : size_32);
    382     add_xmm(args, xmm, dbl);
    383     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_MOVSD : Mnemonic_MOVSS, args);
    384 }
    385 
    386 ENCODER_DECLARE_EXPORT char * sse_mov(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl) {
    387     EncoderBase::Operands args;
    388     add_xmm(args, xmm0, dbl);
    389     add_xmm(args, xmm1, dbl);
    390     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_MOVSD : Mnemonic_MOVSS, args );
    391 }
    392 
    393 // sse add, sub, mul, div
    394 ENCODER_DECLARE_EXPORT char * sse_add(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl) {
    395     EncoderBase::Operands args;
    396     add_xmm(args, xmm, dbl);
    397     add_m(args, mem, dbl ? size_64 : size_32);
    398     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_ADDSD : Mnemonic_ADDSS, args);
    399 }
    400 
    401 ENCODER_DECLARE_EXPORT char * sse_add(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl) {
    402     EncoderBase::Operands args;
    403     add_xmm(args, xmm0, dbl);
    404     add_xmm(args, xmm1, dbl);
    405     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_ADDSD : Mnemonic_ADDSS, args);
    406 }
    407 
    408 ENCODER_DECLARE_EXPORT char * sse_sub(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl) {
    409     EncoderBase::Operands args;
    410     add_xmm(args, xmm, dbl);
    411     add_m(args, mem, dbl ? size_64 : size_32);
    412     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_SUBSD : Mnemonic_SUBSS, args);
    413 }
    414 
    415 ENCODER_DECLARE_EXPORT char * sse_sub(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl) {
    416     EncoderBase::Operands args;
    417     add_xmm(args, xmm0, dbl);
    418     add_xmm(args, xmm1, dbl);
    419     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_SUBSD : Mnemonic_SUBSS, args);
    420 }
    421 
    422 ENCODER_DECLARE_EXPORT char * sse_mul( char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl) {
    423     EncoderBase::Operands args;
    424     add_xmm(args, xmm, dbl);
    425     add_m(args, mem, dbl ? size_64 : size_32);
    426     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_MULSD : Mnemonic_MULSS, args);
    427 }
    428 
    429 ENCODER_DECLARE_EXPORT char * sse_mul(char * stream, const XMM_Opnd& xmm0, const XMM_Opnd& xmm1, bool dbl) {
    430     EncoderBase::Operands args;
    431     add_xmm(args,  xmm0, dbl);
    432     add_xmm(args,  xmm1, dbl);
    433     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_MULSD : Mnemonic_MULSS, args);
    434 }
    435 
    436 ENCODER_DECLARE_EXPORT char * sse_div(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl) {
    437     EncoderBase::Operands args;
    438     add_xmm(args, xmm, dbl);
    439     add_m(args, mem, dbl ? size_64 : size_32);
    440     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_DIVSD : Mnemonic_DIVSS, args);
    441 }
    442 
    443 ENCODER_DECLARE_EXPORT char * sse_div(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl) {
    444     EncoderBase::Operands args;
    445     add_xmm(args, xmm0, dbl);
    446     add_xmm(args, xmm1, dbl);
    447     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_DIVSD : Mnemonic_DIVSS, args);
    448 }
    449 
    450 ENCODER_DECLARE_EXPORT char * sse_xor(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1) {
    451     EncoderBase::Operands args;
    452     add_xmm(args, xmm0, true);
    453     add_xmm(args, xmm1, true);
    454     return (char*)EncoderBase::encode(stream, Mnemonic_PXOR, args);
    455 }
    456 
    457 ENCODER_DECLARE_EXPORT char * sse_compare(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl) {
    458     EncoderBase::Operands args;
    459     add_xmm(args, xmm0, true);
    460     add_xmm(args, xmm1, true);
    461     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_COMISD : Mnemonic_COMISS, args);
    462 }
    463 
    464 ENCODER_DECLARE_EXPORT char * sse_compare(char * stream, const XMM_Opnd & xmm0, const M_Opnd & mem, bool dbl) {
    465     EncoderBase::Operands args;
    466     add_xmm(args, xmm0, dbl);
    467     add_m(args, mem, dbl ? size_64 : size_32);
    468     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_COMISD : Mnemonic_COMISS, args);
    469 }
    470 
    471 // sse conversions
    472 ENCODER_DECLARE_EXPORT char * sse_cvt_si(char * stream, const XMM_Opnd & xmm, const M_Opnd & mem, bool dbl) {
    473     EncoderBase::Operands args;
    474     add_xmm(args, xmm, dbl);
    475     add_m(args, mem, size_32);
    476     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_CVTSI2SD : Mnemonic_CVTSI2SS, args);
    477 }
    478 
    479 ENCODER_DECLARE_EXPORT char * sse_cvtt2si(char * stream, const R_Opnd & reg, const M_Opnd & mem, bool dbl) {
    480     EncoderBase::Operands args;
    481     add_rm(args, reg, size_32);
    482     add_m(args, mem, dbl ? size_64 : size_32);
    483     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_CVTTSD2SI : Mnemonic_CVTTSS2SI, args);
    484 }
    485 
    486 ENCODER_DECLARE_EXPORT char * sse_cvtt2si(char * stream, const R_Opnd & reg, const XMM_Opnd & xmm, bool dbl) {
    487     EncoderBase::Operands args;
    488     add_rm(args, reg, size_32);
    489     add_xmm(args, xmm, dbl);
    490     return (char*)EncoderBase::encode(stream, dbl ? Mnemonic_CVTTSD2SI : Mnemonic_CVTTSS2SI, args);
    491 }
    492 
    493 ENCODER_DECLARE_EXPORT char * sse_cvt_fp2dq(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl) {
    494     EncoderBase::Operands args;
    495     add_xmm(args, xmm0, dbl);
    496     add_xmm(args, xmm1, dbl);
    497     return (char*)EncoderBase::encode(stream, dbl ?  Mnemonic_CVTTPD2DQ : Mnemonic_CVTTPS2DQ, args);
    498 }
    499 
    500 ENCODER_DECLARE_EXPORT char * sse_cvt_dq2fp(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1, bool dbl) {
    501     EncoderBase::Operands args;
    502     add_xmm(args, xmm0, dbl);
    503     add_xmm(args, xmm1, dbl);
    504     return (char*)EncoderBase::encode(stream, dbl ?  Mnemonic_CVTDQ2PD : Mnemonic_CVTDQ2PS, args);
    505 }
    506 
    507 ENCODER_DECLARE_EXPORT char * sse_d2s(char * stream, const XMM_Opnd & xmm0, const M_Opnd & mem64) {
    508     EncoderBase::Operands args;
    509     add_xmm(args, xmm0, false);
    510     add_m(args, mem64, size_64);
    511     return (char*)EncoderBase::encode(stream, Mnemonic_CVTSD2SS, args);
    512 }
    513 
    514 ENCODER_DECLARE_EXPORT char * sse_d2s(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1) {
    515     EncoderBase::Operands args;
    516     add_xmm(args, xmm0, false);
    517     add_xmm(args, xmm1, true);
    518     return (char*)EncoderBase::encode(stream, Mnemonic_CVTSD2SS, args);
    519 }
    520 
    521 ENCODER_DECLARE_EXPORT char * sse_s2d(char * stream, const XMM_Opnd & xmm0, const M_Opnd & mem32) {
    522     EncoderBase::Operands args;
    523     add_xmm(args, xmm0, true);
    524     add_m(args, mem32, size_32);
    525     return (char*)EncoderBase::encode(stream, Mnemonic_CVTSS2SD, args);
    526 }
    527 
    528 ENCODER_DECLARE_EXPORT char * sse_s2d(char * stream, const XMM_Opnd & xmm0, const XMM_Opnd & xmm1) {
    529     EncoderBase::Operands args;
    530     add_xmm(args, xmm0, true);
    531     add_xmm(args, xmm1, false);
    532     return (char*)EncoderBase::encode(stream, Mnemonic_CVTSS2SD, args);
    533 }
    534 
    535 // condition operations
    536 ENCODER_DECLARE_EXPORT char *cmov(char * stream, ConditionCode cc, const R_Opnd & r, const RM_Opnd & rm, Opnd_Size sz) {
    537     EncoderBase::Operands args;
    538     add_r(args, r, sz);
    539     add_rm(args, rm, sz);
    540     return (char*)EncoderBase::encode(stream, (Mnemonic)(Mnemonic_CMOVcc + cc), args);
    541 }
    542 
    543 ENCODER_DECLARE_EXPORT char * setcc(char * stream, ConditionCode cc, const RM_Opnd & rm8) {
    544     EncoderBase::Operands args;
    545     add_rm(args, rm8, size_8);
    546     return (char*)EncoderBase::encode(stream, (Mnemonic)(Mnemonic_SETcc + cc), args);
    547 }
    548 
    549 // load effective address: lea
    550 ENCODER_DECLARE_EXPORT char * lea(char * stream, const R_Opnd & r, const M_Opnd & m, Opnd_Size sz) {
    551     EncoderBase::Operands args;
    552     add_r(args, r, sz);
    553     add_m(args, m, sz);
    554     return (char*)EncoderBase::encode(stream, Mnemonic_LEA, args);
    555 }
    556 
    557 ENCODER_DECLARE_EXPORT char * cdq(char * stream) {
    558     EncoderBase::Operands args;
    559     args.add(RegName_EDX);
    560     args.add(RegName_EAX);
    561     return (char*)EncoderBase::encode(stream, Mnemonic_CDQ, args);
    562 }
    563 
    564 ENCODER_DECLARE_EXPORT char * wait(char * stream) {
    565     return (char*)EncoderBase::encode(stream, Mnemonic_WAIT, EncoderBase::Operands());
    566 }
    567 
    568 // control-flow instructions
    569 
    570 // loop
    571 ENCODER_DECLARE_EXPORT char * loop(char * stream, const Imm_Opnd & imm) {
    572     EncoderBase::Operands args;
    573     assert(imm.get_size() == size_8);
    574     args.add(RegName_ECX);
    575     add_imm(args, imm);
    576     return (char*)EncoderBase::encode(stream, Mnemonic_LOOP, args);
    577 }
    578 
    579 // jump
    580 ENCODER_DECLARE_EXPORT char * jump8(char * stream, const Imm_Opnd & imm) {
    581     EncoderBase::Operands args;
    582     assert(imm.get_size() == size_8);
    583     add_imm(args, imm);
    584     return (char*)EncoderBase::encode(stream, Mnemonic_JMP, args);
    585 }
    586 
    587 ENCODER_DECLARE_EXPORT char * jump32(char * stream, const Imm_Opnd & imm) {
    588     EncoderBase::Operands args;
    589     assert(imm.get_size() == size_32);
    590     add_imm(args, imm);
    591     return (char*)EncoderBase::encode(stream, Mnemonic_JMP, args);
    592 }
    593 
    594 ENCODER_DECLARE_EXPORT char * jump(char * stream, const RM_Opnd & rm, Opnd_Size sz) {
    595     EncoderBase::Operands args;
    596     add_rm(args, rm, sz);
    597     return (char*)EncoderBase::encode(stream, Mnemonic_JMP, args);
    598 }
    599 
    600 /**
    601  * @note On EM64T: if target lies beyond 2G (does not fit into 32 bit
    602  *       offset) then generates indirect jump using RAX (whose content is
    603  *       destroyed).
    604  */
    605 ENCODER_DECLARE_EXPORT char * jump(char * stream, char * target) {
    606 #ifdef _EM64T_
    607     int64 offset = target - stream;
    608     // sub 2 bytes for the short version
    609     offset -= 2;
    610     if (fit8(offset)) {
    611         // use 8-bit signed relative form
    612         return jump8(stream, Imm_Opnd(size_8, offset));
    613     } else if (fit32(offset)) {
    614         // sub 5 (3 + 2)bytes for the long version
    615         offset -= 3;
    616         // use 32-bit signed relative form
    617         return jump32(stream, Imm_Opnd(size_32, offset));
    618     }
    619     // need to use absolute indirect jump
    620     stream = mov(stream, rax_opnd, Imm_Opnd(size_64, (int64)target), size_64);
    621     return jump(stream, rax_opnd, size_64);
    622 #else
    623     I_32 offset = target - stream;
    624     // sub 2 bytes for the short version
    625     offset -= 2;
    626     if (fit8(offset)) {
    627         // use 8-bit signed relative form
    628         return jump8(stream, Imm_Opnd(size_8, offset));
    629     }
    630     // sub 5 (3 + 2) bytes for the long version
    631     offset -= 3;
    632     // use 32-bit signed relative form
    633     return jump32(stream, Imm_Opnd(size_32, offset));
    634 #endif
    635 }
    636 
    637 // branch
    638 ENCODER_DECLARE_EXPORT char * branch8(char * stream, ConditionCode cond,
    639                                       const Imm_Opnd & imm,
    640                                       InstrPrefix pref)
    641 {
    642     if (pref != no_prefix) {
    643         assert(pref == hint_branch_taken_prefix || pref == hint_branch_taken_prefix);
    644         stream = prefix(stream, pref);
    645     }
    646     Mnemonic m = (Mnemonic)(Mnemonic_Jcc + cond);
    647     EncoderBase::Operands args;
    648     assert(imm.get_size() == size_8);
    649     add_imm(args, imm);
    650     return (char*)EncoderBase::encode(stream, m, args);
    651 }
    652 
    653 ENCODER_DECLARE_EXPORT char * branch32(char * stream, ConditionCode cond,
    654                                        const Imm_Opnd & imm,
    655                                        InstrPrefix pref)
    656 {
    657     if (pref != no_prefix) {
    658         assert(pref == hint_branch_taken_prefix || pref == hint_branch_taken_prefix);
    659         stream = prefix(stream, pref);
    660     }
    661     Mnemonic m = (Mnemonic)(Mnemonic_Jcc + cond);
    662     EncoderBase::Operands args;
    663     assert(imm.get_size() == size_32);
    664     add_imm(args, imm);
    665     return (char*)EncoderBase::encode(stream, m, args);
    666 }
    667 
    668 /*
    669 ENCODER_DECLARE_EXPORT char * branch(char * stream, ConditionCode cc, const char * target, InstrPrefix prefix) {
    670 // sub 2 bytes for the short version
    671 int64 offset = stream-target-2;
    672 if( fit8(offset) ) {
    673 return branch8(stream, cc, Imm_Opnd(size_8, (char)offset), is_signed);
    674 }
    675 return branch32(stream, cc, Imm_Opnd(size_32, (int)offset), is_signed);
    676 }
    677 */
    678 
    679 // call
    680 ENCODER_DECLARE_EXPORT char * call(char * stream, const Imm_Opnd & imm)
    681 {
    682     EncoderBase::Operands args;
    683     add_imm(args, imm);
    684     return (char*)EncoderBase::encode(stream, Mnemonic_CALL, args);
    685 }
    686 
    687 ENCODER_DECLARE_EXPORT char * call(char * stream, const RM_Opnd & rm,
    688                                    Opnd_Size sz)
    689 {
    690     EncoderBase::Operands args;
    691     add_rm(args, rm, sz);
    692     return (char*)EncoderBase::encode(stream, Mnemonic_CALL, args);
    693 }
    694 
    695 /**
    696 * @note On EM64T: if target lies beyond 2G (does not fit into 32 bit
    697 *       offset) then generates indirect jump using RAX (whose content is
    698 *       destroyed).
    699 */
    700 ENCODER_DECLARE_EXPORT char * call(char * stream, const char * target)
    701 {
    702 #ifdef _EM64T_
    703     int64 offset = target - stream;
    704     if (fit32(offset)) {
    705         offset -= 5; // sub 5 bytes for this instruction
    706         Imm_Opnd imm(size_32, offset);
    707         return call(stream, imm);
    708     }
    709     // need to use absolute indirect call
    710     stream = mov(stream, rax_opnd, Imm_Opnd(size_64, (int64)target), size_64);
    711     return call(stream, rax_opnd, size_64);
    712 #else
    713     I_32 offset = target - stream;
    714     offset -= 5; // sub 5 bytes for this instruction
    715     Imm_Opnd imm(size_32, offset);
    716     return call(stream, imm);
    717 #endif
    718 }
    719 
    720 // return instruction
    721 ENCODER_DECLARE_EXPORT char * ret(char * stream)
    722 {
    723     EncoderBase::Operands args;
    724     return (char*)EncoderBase::encode(stream, Mnemonic_RET, args);
    725 }
    726 
    727 ENCODER_DECLARE_EXPORT char * ret(char * stream, const Imm_Opnd & imm)
    728 {
    729     EncoderBase::Operands args;
    730     // TheManual says imm can be 16-bit only
    731     //assert(imm.get_size() <= size_16);
    732     args.add(EncoderBase::Operand(map_size(size_16), imm.get_value()));
    733     return (char*)EncoderBase::encode(stream, Mnemonic_RET, args);
    734 }
    735 
    736 ENCODER_DECLARE_EXPORT char * ret(char * stream, unsigned short pop)
    737 {
    738     // TheManual says it can only be imm16
    739     EncoderBase::Operands args(EncoderBase::Operand(OpndSize_16, pop, OpndExt_Zero));
    740     return (char*)EncoderBase::encode(stream, Mnemonic_RET, args);
    741 }
    742 
    743 // floating-point instructions
    744 ENCODER_DECLARE_EXPORT char * fld(char * stream, const M_Opnd & m,
    745                                   bool is_double) {
    746     EncoderBase::Operands args;
    747     // a fake FP register as operand
    748     add_fp(args, 0, is_double);
    749     add_m(args, m, is_double ? size_64 : size_32);
    750     return (char*)EncoderBase::encode(stream, Mnemonic_FLD, args);
    751 }
    752 
    753 ENCODER_DECLARE_EXPORT char * fist(char * stream, const M_Opnd & mem,
    754                                    bool is_long, bool pop_stk)
    755 {
    756     EncoderBase::Operands args;
    757     if (pop_stk) {
    758         add_m(args, mem, is_long ? size_64 : size_32);
    759         // a fake FP register as operand
    760         add_fp(args, 0, is_long);
    761         return (char*)EncoderBase::encode(stream,  Mnemonic_FISTP, args);
    762     }
    763     // only 32-bit operands are supported
    764     assert(is_long == false);
    765     add_m(args, mem, size_32);
    766     add_fp(args, 0, false);
    767     return (char*)EncoderBase::encode(stream,  Mnemonic_FIST, args);
    768 }
    769 
    770 ENCODER_DECLARE_EXPORT char * fst(char * stream, const M_Opnd & m,
    771                                   bool is_double, bool pop_stk)
    772 {
    773     EncoderBase::Operands args;
    774     add_m(args, m, is_double ? size_64 : size_32);
    775     // a fake FP register as operand
    776     add_fp(args, 0, is_double);
    777     return (char*)EncoderBase::encode(stream,
    778                                     pop_stk ? Mnemonic_FSTP : Mnemonic_FST,
    779                                     args);
    780 }
    781 
    782 ENCODER_DECLARE_EXPORT char * fst(char * stream, unsigned i, bool pop_stk)
    783 {
    784     EncoderBase::Operands args;
    785     add_fp(args, i, true);
    786     return (char*)EncoderBase::encode(stream,
    787                                     pop_stk ? Mnemonic_FSTP : Mnemonic_FST,
    788                                     args);
    789 }
    790 
    791 ENCODER_DECLARE_EXPORT char * fldcw(char * stream, const M_Opnd & mem) {
    792     EncoderBase::Operands args;
    793     add_m(args, mem, size_16);
    794     return (char*)EncoderBase::encode(stream, Mnemonic_FLDCW, args);
    795 }
    796 
    797 ENCODER_DECLARE_EXPORT char * fnstcw(char * stream, const M_Opnd & mem) {
    798     EncoderBase::Operands args;
    799     add_m(args, mem, size_16);
    800     return (char*)EncoderBase::encode(stream, Mnemonic_FNSTCW, args);
    801 }
    802 
    803 ENCODER_DECLARE_EXPORT char * fnstsw(char * stream)
    804 {
    805     return (char*)EncoderBase::encode(stream, Mnemonic_FNSTCW,
    806                                       EncoderBase::Operands());
    807 }
    808 
    809 // string operations
    810 ENCODER_DECLARE_EXPORT char * set_d(char * stream, bool set) {
    811     EncoderBase::Operands args;
    812     return (char*)EncoderBase::encode(stream,
    813                                       set ? Mnemonic_STD : Mnemonic_CLD,
    814                                       args);
    815 }
    816 
    817 ENCODER_DECLARE_EXPORT char * scas(char * stream, unsigned char prefix)
    818 {
    819 	EncoderBase::Operands args;
    820     if (prefix != no_prefix) {
    821         assert(prefix == prefix_repnz || prefix == prefix_repz);
    822         *stream = prefix;
    823         ++stream;
    824     }
    825     return (char*)EncoderBase::encode(stream, Mnemonic_SCAS, args);
    826 }
    827 
    828 ENCODER_DECLARE_EXPORT char * stos(char * stream, unsigned char prefix)
    829 {
    830     if (prefix != no_prefix) {
    831         assert(prefix == prefix_rep);
    832         *stream = prefix;
    833         ++stream;
    834     }
    835 
    836 	EncoderBase::Operands args;
    837 	return (char*)EncoderBase::encode(stream, Mnemonic_STOS, args);
    838 }
    839 
    840 // Intrinsic FP math functions
    841 
    842 ENCODER_DECLARE_EXPORT char * fprem(char * stream) {
    843     return (char*)EncoderBase::encode(stream, Mnemonic_FPREM,
    844                                       EncoderBase::Operands());
    845 }
    846 
    847 ENCODER_DECLARE_EXPORT char * fprem1(char * stream) {
    848     return (char*)EncoderBase::encode(stream, Mnemonic_FPREM1,
    849                                       EncoderBase::Operands());
    850 }
    851