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