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 24extern const RegName map_of_regno_2_regname[]; 25extern const OpndSize map_of_EncoderOpndSize_2_RealOpndSize[]; 26extern const Mnemonic map_of_alu_opcode_2_mnemonic[]; 27extern const Mnemonic map_of_shift_opcode_2_mnemonic[]; 28 29// S_ stands for 'Signed' 30extern const Mnemonic S_map_of_condition_code_2_branch_mnemonic[]; 31// U_ stands for 'Unsigned' 32extern const Mnemonic U_map_of_condition_code_2_branch_mnemonic[]; 33 34inline static RegName map_reg(Reg_No r) { 35 assert(r >= 0 && r <= n_reg); 36 return map_of_regno_2_regname[r]; 37} 38 39inline 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 44inline 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 49inline 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 54inline bool fit8(int64 val) { 55 return (CHAR_MIN <= val) && (val <= CHAR_MAX); 56} 57 58inline bool fit32(int64 val) { 59 return (INT_MIN <= val) && (val <= INT_MAX); 60} 61 62inline 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 73inline 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 80inline 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 84inline 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 94inline static void add_fp(EncoderBase::Operands & args, unsigned i, bool dbl) { 95 return args.add((RegName)( (dbl ? RegName_FP0D : RegName_FP0S) + i)); 96} 97 98inline 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 104ENCODER_DECLARE_EXPORT char * prefix(char * stream, InstrPrefix p) { 105 *stream = (char)p; 106 return stream + 1; 107} 108 109// stack push and pop instructions 110ENCODER_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 116ENCODER_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 127ENCODER_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 134ENCODER_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 143ENCODER_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 151ENCODER_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 157ENCODER_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 163ENCODER_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 169ENCODER_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 175ENCODER_DECLARE_EXPORT char * nop(char * stream) { 176 EncoderBase::Operands args; 177 return (char*)EncoderBase::encode(stream, Mnemonic_NOP, args); 178} 179 180ENCODER_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 186ENCODER_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 193ENCODER_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 200ENCODER_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 208ENCODER_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 216ENCODER_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 224ENCODER_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 231ENCODER_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 238ENCODER_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 248ENCODER_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 259ENCODER_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 267ENCODER_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 274ENCODER_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 281ENCODER_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 291ENCODER_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 305ENCODER_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 312ENCODER_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 319ENCODER_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 326ENCODER_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 333ENCODER_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 340ENCODER_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 347ENCODER_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 354ENCODER_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 361ENCODER_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 372ENCODER_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 379ENCODER_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 386ENCODER_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 394ENCODER_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 401ENCODER_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 408ENCODER_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 415ENCODER_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 422ENCODER_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 429ENCODER_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 436ENCODER_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 443ENCODER_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 450ENCODER_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 457ENCODER_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 464ENCODER_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 472ENCODER_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 479ENCODER_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 486ENCODER_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 493ENCODER_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 500ENCODER_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 507ENCODER_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 514ENCODER_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 521ENCODER_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 528ENCODER_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 536ENCODER_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 543ENCODER_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 550ENCODER_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 557ENCODER_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 564ENCODER_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 571ENCODER_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 580ENCODER_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 587ENCODER_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 594ENCODER_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 */ 605ENCODER_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 638ENCODER_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 653ENCODER_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/* 669ENCODER_DECLARE_EXPORT char * branch(char * stream, ConditionCode cc, const char * target, InstrPrefix prefix) { 670// sub 2 bytes for the short version 671int64 offset = stream-target-2; 672if( fit8(offset) ) { 673return branch8(stream, cc, Imm_Opnd(size_8, (char)offset), is_signed); 674} 675return branch32(stream, cc, Imm_Opnd(size_32, (int)offset), is_signed); 676} 677*/ 678 679// call 680ENCODER_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 687ENCODER_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*/ 700ENCODER_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 721ENCODER_DECLARE_EXPORT char * ret(char * stream) 722{ 723 EncoderBase::Operands args; 724 return (char*)EncoderBase::encode(stream, Mnemonic_RET, args); 725} 726 727ENCODER_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 736ENCODER_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 744ENCODER_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 753ENCODER_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 770ENCODER_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 782ENCODER_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 791ENCODER_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 797ENCODER_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 803ENCODER_DECLARE_EXPORT char * fnstsw(char * stream) 804{ 805 return (char*)EncoderBase::encode(stream, Mnemonic_FNSTCW, 806 EncoderBase::Operands()); 807} 808 809// string operations 810ENCODER_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 817ENCODER_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 828ENCODER_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 842ENCODER_DECLARE_EXPORT char * fprem(char * stream) { 843 return (char*)EncoderBase::encode(stream, Mnemonic_FPREM, 844 EncoderBase::Operands()); 845} 846 847ENCODER_DECLARE_EXPORT char * fprem1(char * stream) { 848 return (char*)EncoderBase::encode(stream, Mnemonic_FPREM1, 849 EncoderBase::Operands()); 850} 851