1 /* 2 * x86 bytecode utility functions 3 * 4 * Copyright (C) 2001-2007 Peter Johnson 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 #include <util.h> 28 29 #include <libyasm.h> 30 31 #include "x86arch.h" 32 33 34 /* Bytecode callback function prototypes */ 35 36 static void x86_bc_insn_destroy(void *contents); 37 static void x86_bc_insn_print(const void *contents, FILE *f, 38 int indent_level); 39 static int x86_bc_insn_calc_len(yasm_bytecode *bc, 40 yasm_bc_add_span_func add_span, 41 void *add_span_data); 42 static int x86_bc_insn_expand(yasm_bytecode *bc, int span, long old_val, 43 long new_val, /*@out@*/ long *neg_thres, 44 /*@out@*/ long *pos_thres); 45 static int x86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, 46 unsigned char *bufstart, 47 void *d, yasm_output_value_func output_value, 48 /*@null@*/ yasm_output_reloc_func output_reloc); 49 50 static void x86_bc_jmp_destroy(void *contents); 51 static void x86_bc_jmp_print(const void *contents, FILE *f, int indent_level); 52 static int x86_bc_jmp_calc_len(yasm_bytecode *bc, 53 yasm_bc_add_span_func add_span, 54 void *add_span_data); 55 static int x86_bc_jmp_expand(yasm_bytecode *bc, int span, long old_val, 56 long new_val, /*@out@*/ long *neg_thres, 57 /*@out@*/ long *pos_thres); 58 static int x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp, 59 unsigned char *bufstart, 60 void *d, yasm_output_value_func output_value, 61 /*@null@*/ yasm_output_reloc_func output_reloc); 62 63 static void x86_bc_jmpfar_destroy(void *contents); 64 static void x86_bc_jmpfar_print(const void *contents, FILE *f, 65 int indent_level); 66 static int x86_bc_jmpfar_calc_len(yasm_bytecode *bc, 67 yasm_bc_add_span_func add_span, 68 void *add_span_data); 69 static int x86_bc_jmpfar_tobytes 70 (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, 71 yasm_output_value_func output_value, 72 /*@null@*/ yasm_output_reloc_func output_reloc); 73 74 /* Bytecode callback structures */ 75 76 static const yasm_bytecode_callback x86_bc_callback_insn = { 77 x86_bc_insn_destroy, 78 x86_bc_insn_print, 79 yasm_bc_finalize_common, 80 NULL, 81 x86_bc_insn_calc_len, 82 x86_bc_insn_expand, 83 x86_bc_insn_tobytes, 84 0 85 }; 86 87 static const yasm_bytecode_callback x86_bc_callback_jmp = { 88 x86_bc_jmp_destroy, 89 x86_bc_jmp_print, 90 yasm_bc_finalize_common, 91 NULL, 92 x86_bc_jmp_calc_len, 93 x86_bc_jmp_expand, 94 x86_bc_jmp_tobytes, 95 0 96 }; 97 98 static const yasm_bytecode_callback x86_bc_callback_jmpfar = { 99 x86_bc_jmpfar_destroy, 100 x86_bc_jmpfar_print, 101 yasm_bc_finalize_common, 102 NULL, 103 x86_bc_jmpfar_calc_len, 104 yasm_bc_expand_common, 105 x86_bc_jmpfar_tobytes, 106 0 107 }; 108 109 int 110 yasm_x86__set_rex_from_reg(unsigned char *rex, unsigned char *low3, 111 uintptr_t reg, unsigned int bits, 112 x86_rex_bit_pos rexbit) 113 { 114 *low3 = (unsigned char)(reg&7); 115 116 if (bits == 64) { 117 x86_expritem_reg_size size = (x86_expritem_reg_size)(reg & ~0xFUL); 118 119 if (size == X86_REG8X || (reg & 0xF) >= 8) { 120 /* Check to make sure we can set it */ 121 if (*rex == 0xff) { 122 yasm_error_set(YASM_ERROR_TYPE, 123 N_("cannot use A/B/C/DH with instruction needing REX")); 124 return 1; 125 } 126 *rex |= 0x40 | (((reg & 8) >> 3) << rexbit); 127 } else if (size == X86_REG8 && (reg & 7) >= 4) { 128 /* AH/BH/CH/DH, so no REX allowed */ 129 if (*rex != 0 && *rex != 0xff) { 130 yasm_error_set(YASM_ERROR_TYPE, 131 N_("cannot use A/B/C/DH with instruction needing REX")); 132 return 1; 133 } 134 *rex = 0xff; /* Flag so we can NEVER set it (see above) */ 135 } 136 } 137 138 return 0; 139 } 140 141 void 142 yasm_x86__bc_transform_insn(yasm_bytecode *bc, x86_insn *insn) 143 { 144 yasm_bc_transform(bc, &x86_bc_callback_insn, insn); 145 } 146 147 void 148 yasm_x86__bc_transform_jmp(yasm_bytecode *bc, x86_jmp *jmp) 149 { 150 yasm_bc_transform(bc, &x86_bc_callback_jmp, jmp); 151 } 152 153 void 154 yasm_x86__bc_transform_jmpfar(yasm_bytecode *bc, x86_jmpfar *jmpfar) 155 { 156 yasm_bc_transform(bc, &x86_bc_callback_jmpfar, jmpfar); 157 } 158 159 void 160 yasm_x86__ea_init(x86_effaddr *x86_ea, unsigned int spare, 161 yasm_bytecode *precbc) 162 { 163 if (yasm_value_finalize(&x86_ea->ea.disp, precbc)) 164 yasm_error_set(YASM_ERROR_TOO_COMPLEX, 165 N_("effective address too complex")); 166 x86_ea->modrm &= 0xC7; /* zero spare/reg bits */ 167 x86_ea->modrm |= (spare << 3) & 0x38; /* plug in provided bits */ 168 } 169 170 void 171 yasm_x86__ea_set_disponly(x86_effaddr *x86_ea) 172 { 173 x86_ea->valid_modrm = 0; 174 x86_ea->need_modrm = 0; 175 x86_ea->valid_sib = 0; 176 x86_ea->need_sib = 0; 177 } 178 179 static x86_effaddr * 180 ea_create(void) 181 { 182 x86_effaddr *x86_ea = yasm_xmalloc(sizeof(x86_effaddr)); 183 184 yasm_value_initialize(&x86_ea->ea.disp, NULL, 0); 185 x86_ea->ea.need_nonzero_len = 0; 186 x86_ea->ea.need_disp = 0; 187 x86_ea->ea.nosplit = 0; 188 x86_ea->ea.strong = 0; 189 x86_ea->ea.segreg = 0; 190 x86_ea->ea.pc_rel = 0; 191 x86_ea->ea.not_pc_rel = 0; 192 x86_ea->ea.data_len = 0; 193 x86_ea->vsib_mode = 0; 194 x86_ea->modrm = 0; 195 x86_ea->valid_modrm = 0; 196 x86_ea->need_modrm = 0; 197 x86_ea->sib = 0; 198 x86_ea->valid_sib = 0; 199 x86_ea->need_sib = 0; 200 201 return x86_ea; 202 } 203 204 x86_effaddr * 205 yasm_x86__ea_create_reg(x86_effaddr *x86_ea, unsigned long reg, 206 unsigned char *rex, unsigned int bits) 207 { 208 unsigned char rm; 209 210 if (yasm_x86__set_rex_from_reg(rex, &rm, reg, bits, X86_REX_B)) 211 return NULL; 212 213 if (!x86_ea) 214 x86_ea = ea_create(); 215 x86_ea->modrm = 0xC0 | rm; /* Mod=11, R/M=Reg, Reg=0 */ 216 x86_ea->valid_modrm = 1; 217 x86_ea->need_modrm = 1; 218 219 return x86_ea; 220 } 221 222 yasm_effaddr * 223 yasm_x86__ea_create_expr(yasm_arch *arch, yasm_expr *e) 224 { 225 yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch; 226 x86_effaddr *x86_ea; 227 228 x86_ea = ea_create(); 229 230 if (arch_x86->parser == X86_PARSER_GAS) { 231 /* Need to change foo+rip into foo wrt rip (even in .intel_syntax mode). 232 * Note this assumes a particular ordering coming from the parser 233 * to work (it's not very smart)! 234 */ 235 if (e->op == YASM_EXPR_ADD && e->terms[0].type == YASM_EXPR_REG 236 && e->terms[0].data.reg == X86_RIP) { 237 /* replace register with 0 */ 238 e->terms[0].type = YASM_EXPR_INT; 239 e->terms[0].data.intn = yasm_intnum_create_uint(0); 240 /* build new wrt expression */ 241 e = yasm_expr_create(YASM_EXPR_WRT, yasm_expr_expr(e), 242 yasm_expr_reg(X86_RIP), e->line); 243 } 244 } 245 yasm_value_initialize(&x86_ea->ea.disp, e, 0); 246 x86_ea->ea.need_disp = 1; 247 x86_ea->need_modrm = 1; 248 /* We won't know whether we need an SIB until we know more about expr and 249 * the BITS/address override setting. 250 */ 251 x86_ea->need_sib = 0xff; 252 253 x86_ea->ea.data_len = 0; 254 255 return (yasm_effaddr *)x86_ea; 256 } 257 258 /*@-compmempass@*/ 259 x86_effaddr * 260 yasm_x86__ea_create_imm(x86_effaddr *x86_ea, yasm_expr *imm, 261 unsigned int im_len) 262 { 263 if (!x86_ea) 264 x86_ea = ea_create(); 265 yasm_value_initialize(&x86_ea->ea.disp, imm, im_len); 266 x86_ea->ea.need_disp = 1; 267 268 return x86_ea; 269 } 270 /*@=compmempass@*/ 271 272 void 273 yasm_x86__bc_apply_prefixes(x86_common *common, unsigned char *rex, 274 unsigned int def_opersize_64, 275 unsigned int num_prefixes, uintptr_t *prefixes) 276 { 277 unsigned int i; 278 int first = 1; 279 280 for (i=0; i<num_prefixes; i++) { 281 switch ((x86_parse_insn_prefix)(prefixes[i] & 0xff00)) { 282 case X86_LOCKREP: 283 if (common->lockrep_pre != 0) 284 yasm_warn_set(YASM_WARN_GENERAL, 285 N_("multiple LOCK or REP prefixes, using leftmost")); 286 common->lockrep_pre = (unsigned char)prefixes[i] & 0xff; 287 break; 288 case X86_ADDRSIZE: 289 common->addrsize = (unsigned char)prefixes[i] & 0xff; 290 break; 291 case X86_OPERSIZE: 292 common->opersize = (unsigned char)prefixes[i] & 0xff; 293 if (common->mode_bits == 64 && common->opersize == 64 && 294 def_opersize_64 != 64) { 295 if (!rex) 296 yasm_warn_set(YASM_WARN_GENERAL, 297 N_("ignoring REX prefix on jump")); 298 else if (*rex == 0xff) 299 yasm_warn_set(YASM_WARN_GENERAL, 300 N_("REX prefix not allowed on this instruction, ignoring")); 301 else 302 *rex = 0x48; 303 } 304 break; 305 case X86_SEGREG: 306 /* This is a hack.. we should really be putting this in the 307 * the effective address! 308 */ 309 common->lockrep_pre = (unsigned char)prefixes[i] & 0xff; 310 break; 311 case X86_REX: 312 if (!rex) 313 yasm_warn_set(YASM_WARN_GENERAL, 314 N_("ignoring REX prefix on jump")); 315 else if (*rex == 0xff) 316 yasm_warn_set(YASM_WARN_GENERAL, 317 N_("REX prefix not allowed on this instruction, ignoring")); 318 else { 319 if (*rex != 0) { 320 if (first) 321 yasm_warn_set(YASM_WARN_GENERAL, 322 N_("overriding generated REX prefix")); 323 else 324 yasm_warn_set(YASM_WARN_GENERAL, 325 N_("multiple REX prefixes, using leftmost")); 326 } 327 /* Here we assume that we can't get this prefix in non 328 * 64 bit mode due to checks in parse_check_prefix(). 329 */ 330 common->mode_bits = 64; 331 *rex = (unsigned char)prefixes[i] & 0xff; 332 } 333 first = 0; 334 break; 335 } 336 } 337 } 338 339 static void 340 x86_bc_insn_destroy(void *contents) 341 { 342 x86_insn *insn = (x86_insn *)contents; 343 if (insn->x86_ea) 344 yasm_x86__ea_destroy((yasm_effaddr *)insn->x86_ea); 345 if (insn->imm) { 346 yasm_value_delete(insn->imm); 347 yasm_xfree(insn->imm); 348 } 349 yasm_xfree(contents); 350 } 351 352 static void 353 x86_bc_jmp_destroy(void *contents) 354 { 355 x86_jmp *jmp = (x86_jmp *)contents; 356 yasm_value_delete(&jmp->target); 357 yasm_xfree(contents); 358 } 359 360 static void 361 x86_bc_jmpfar_destroy(void *contents) 362 { 363 x86_jmpfar *jmpfar = (x86_jmpfar *)contents; 364 yasm_value_delete(&jmpfar->segment); 365 yasm_value_delete(&jmpfar->offset); 366 yasm_xfree(contents); 367 } 368 369 void 370 yasm_x86__ea_destroy(yasm_effaddr *ea) 371 { 372 yasm_value_delete(&ea->disp); 373 yasm_xfree(ea); 374 } 375 376 void 377 yasm_x86__ea_print(const yasm_effaddr *ea, FILE *f, int indent_level) 378 { 379 const x86_effaddr *x86_ea = (const x86_effaddr *)ea; 380 fprintf(f, "%*sDisp:\n", indent_level, ""); 381 yasm_value_print(&ea->disp, f, indent_level+1); 382 fprintf(f, "%*sNoSplit=%u\n", indent_level, "", (unsigned int)ea->nosplit); 383 fprintf(f, "%*sSegmentOv=%02x\n", indent_level, "", 384 (unsigned int)x86_ea->ea.segreg); 385 fprintf(f, "%*sVSIBMode=%u\n", indent_level, "", 386 (unsigned int)x86_ea->vsib_mode); 387 fprintf(f, "%*sModRM=%03o ValidRM=%u NeedRM=%u\n", indent_level, "", 388 (unsigned int)x86_ea->modrm, (unsigned int)x86_ea->valid_modrm, 389 (unsigned int)x86_ea->need_modrm); 390 fprintf(f, "%*sSIB=%03o ValidSIB=%u NeedSIB=%u\n", indent_level, "", 391 (unsigned int)x86_ea->sib, (unsigned int)x86_ea->valid_sib, 392 (unsigned int)x86_ea->need_sib); 393 } 394 395 static void 396 x86_common_print(const x86_common *common, FILE *f, int indent_level) 397 { 398 fprintf(f, "%*sAddrSize=%u OperSize=%u LockRepPre=%02x BITS=%u\n", 399 indent_level, "", 400 (unsigned int)common->addrsize, 401 (unsigned int)common->opersize, 402 (unsigned int)common->lockrep_pre, 403 (unsigned int)common->mode_bits); 404 } 405 406 static void 407 x86_opcode_print(const x86_opcode *opcode, FILE *f, int indent_level) 408 { 409 fprintf(f, "%*sOpcode: %02x %02x %02x OpLen=%u\n", indent_level, "", 410 (unsigned int)opcode->opcode[0], 411 (unsigned int)opcode->opcode[1], 412 (unsigned int)opcode->opcode[2], 413 (unsigned int)opcode->len); 414 } 415 416 static void 417 x86_bc_insn_print(const void *contents, FILE *f, int indent_level) 418 { 419 const x86_insn *insn = (const x86_insn *)contents; 420 421 fprintf(f, "%*s_Instruction_\n", indent_level, ""); 422 fprintf(f, "%*sEffective Address:", indent_level, ""); 423 if (insn->x86_ea) { 424 fprintf(f, "\n"); 425 yasm_x86__ea_print((yasm_effaddr *)insn->x86_ea, f, indent_level+1); 426 } else 427 fprintf(f, " (nil)\n"); 428 fprintf(f, "%*sImmediate Value:", indent_level, ""); 429 if (!insn->imm) 430 fprintf(f, " (nil)\n"); 431 else { 432 indent_level++; 433 fprintf(f, "\n"); 434 yasm_value_print(insn->imm, f, indent_level); 435 indent_level--; 436 } 437 x86_opcode_print(&insn->opcode, f, indent_level); 438 x86_common_print(&insn->common, f, indent_level); 439 fprintf(f, "%*sSpPre=%02x REX=%03o PostOp=%u\n", indent_level, "", 440 (unsigned int)insn->special_prefix, 441 (unsigned int)insn->rex, 442 (unsigned int)insn->postop); 443 } 444 445 static void 446 x86_bc_jmp_print(const void *contents, FILE *f, int indent_level) 447 { 448 const x86_jmp *jmp = (const x86_jmp *)contents; 449 450 fprintf(f, "%*s_Jump_\n", indent_level, ""); 451 fprintf(f, "%*sTarget:\n", indent_level, ""); 452 yasm_value_print(&jmp->target, f, indent_level+1); 453 /* FIXME 454 fprintf(f, "%*sOrigin=\n", indent_level, ""); 455 yasm_symrec_print(jmp->origin, f, indent_level+1); 456 */ 457 fprintf(f, "\n%*sShort Form:\n", indent_level, ""); 458 if (jmp->shortop.len == 0) 459 fprintf(f, "%*sNone\n", indent_level+1, ""); 460 else 461 x86_opcode_print(&jmp->shortop, f, indent_level+1); 462 fprintf(f, "%*sNear Form:\n", indent_level, ""); 463 if (jmp->nearop.len == 0) 464 fprintf(f, "%*sNone\n", indent_level+1, ""); 465 else 466 x86_opcode_print(&jmp->nearop, f, indent_level+1); 467 fprintf(f, "%*sOpSel=", indent_level, ""); 468 switch (jmp->op_sel) { 469 case JMP_NONE: 470 fprintf(f, "None"); 471 break; 472 case JMP_SHORT: 473 fprintf(f, "Short"); 474 break; 475 case JMP_NEAR: 476 fprintf(f, "Near"); 477 break; 478 case JMP_SHORT_FORCED: 479 fprintf(f, "Forced Short"); 480 break; 481 case JMP_NEAR_FORCED: 482 fprintf(f, "Forced Near"); 483 break; 484 default: 485 fprintf(f, "UNKNOWN!!"); 486 break; 487 } 488 x86_common_print(&jmp->common, f, indent_level); 489 } 490 491 static void 492 x86_bc_jmpfar_print(const void *contents, FILE *f, int indent_level) 493 { 494 const x86_jmpfar *jmpfar = (const x86_jmpfar *)contents; 495 496 fprintf(f, "%*s_Far_Jump_\n", indent_level, ""); 497 fprintf(f, "%*sSegment:\n", indent_level, ""); 498 yasm_value_print(&jmpfar->segment, f, indent_level+1); 499 fprintf(f, "%*sOffset:\n", indent_level, ""); 500 yasm_value_print(&jmpfar->offset, f, indent_level+1); 501 x86_opcode_print(&jmpfar->opcode, f, indent_level); 502 x86_common_print(&jmpfar->common, f, indent_level); 503 } 504 505 static unsigned int 506 x86_common_calc_len(const x86_common *common) 507 { 508 unsigned int len = 0; 509 510 if (common->addrsize != 0 && common->addrsize != common->mode_bits) 511 len++; 512 if (common->opersize != 0 && 513 ((common->mode_bits != 64 && common->opersize != common->mode_bits) || 514 (common->mode_bits == 64 && common->opersize == 16))) 515 len++; 516 if (common->lockrep_pre != 0) 517 len++; 518 519 return len; 520 } 521 522 static int 523 x86_bc_insn_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, 524 void *add_span_data) 525 { 526 x86_insn *insn = (x86_insn *)bc->contents; 527 x86_effaddr *x86_ea = insn->x86_ea; 528 yasm_value *imm = insn->imm; 529 530 if (x86_ea) { 531 /* Check validity of effective address and calc R/M bits of 532 * Mod/RM byte and SIB byte. We won't know the Mod field 533 * of the Mod/RM byte until we know more about the 534 * displacement. 535 */ 536 if (yasm_x86__expr_checkea(x86_ea, &insn->common.addrsize, 537 insn->common.mode_bits, insn->postop == X86_POSTOP_ADDRESS16, 538 &insn->rex, bc)) 539 /* failed, don't bother checking rest of insn */ 540 return -1; 541 542 if (x86_ea->ea.disp.size == 0 && x86_ea->ea.need_nonzero_len) { 543 /* Handle unknown case, default to byte-sized and set as 544 * critical expression. 545 */ 546 x86_ea->ea.disp.size = 8; 547 add_span(add_span_data, bc, 1, &x86_ea->ea.disp, -128, 127); 548 } 549 bc->len += x86_ea->ea.disp.size/8; 550 551 /* Handle address16 postop case */ 552 if (insn->postop == X86_POSTOP_ADDRESS16) 553 insn->common.addrsize = 0; 554 555 /* Compute length of ea and add to total */ 556 bc->len += x86_ea->need_modrm + (x86_ea->need_sib ? 1:0); 557 bc->len += (x86_ea->ea.segreg != 0) ? 1 : 0; 558 } 559 560 if (imm) { 561 unsigned int immlen = imm->size; 562 563 /* TODO: check imm->len vs. sized len from expr? */ 564 565 /* Handle signext_imm8 postop special-casing */ 566 if (insn->postop == X86_POSTOP_SIGNEXT_IMM8) { 567 /*@null@*/ /*@only@*/ yasm_intnum *num; 568 num = yasm_value_get_intnum(imm, NULL, 0); 569 570 if (!num) { 571 /* Unknown; default to byte form and set as critical 572 * expression. 573 */ 574 immlen = 8; 575 add_span(add_span_data, bc, 2, imm, -128, 127); 576 } else { 577 if (yasm_intnum_in_range(num, -128, 127)) { 578 /* We can use the sign-extended byte form: shorten 579 * the immediate length to 1 and make the byte form 580 * permanent. 581 */ 582 imm->size = 8; 583 imm->sign = 1; 584 immlen = 8; 585 } else { 586 /* We can't. Copy over the word-sized opcode. */ 587 insn->opcode.opcode[0] = 588 insn->opcode.opcode[insn->opcode.len]; 589 insn->opcode.len = 1; 590 } 591 insn->postop = X86_POSTOP_NONE; 592 yasm_intnum_destroy(num); 593 } 594 } 595 596 bc->len += immlen/8; 597 } 598 599 /* VEX and XOP prefixes never have REX (it's embedded in the opcode). 600 * For VEX, we can come into this function with the three byte form, 601 * so we need to see if we can optimize to the two byte form. 602 * We can't do it earlier, as we don't know all of the REX byte until now. 603 */ 604 if (insn->special_prefix == 0xC4) { 605 /* See if we can shorten the VEX prefix to its two byte form. 606 * In order to do this, REX.X, REX.B, and REX.W/VEX.W must all be 0, 607 * and the VEX mmmmm field must be 1. 608 */ 609 if ((insn->opcode.opcode[0] & 0x1F) == 1 && 610 (insn->opcode.opcode[1] & 0x80) == 0 && 611 (insn->rex == 0xff || (insn->rex & 0x0B) == 0)) { 612 insn->opcode.opcode[0] = insn->opcode.opcode[1]; 613 insn->opcode.opcode[1] = insn->opcode.opcode[2]; 614 insn->opcode.opcode[2] = 0; /* sanity */ 615 insn->opcode.len = 2; 616 insn->special_prefix = 0xC5; /* mark as two-byte VEX */ 617 } 618 } else if (insn->rex != 0xff && insn->rex != 0 && 619 insn->special_prefix != 0xC5 && insn->special_prefix != 0x8F) 620 bc->len++; 621 622 bc->len += insn->opcode.len; 623 bc->len += x86_common_calc_len(&insn->common); 624 bc->len += (insn->special_prefix != 0) ? 1:0; 625 return 0; 626 } 627 628 static int 629 x86_bc_insn_expand(yasm_bytecode *bc, int span, long old_val, long new_val, 630 /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres) 631 { 632 x86_insn *insn = (x86_insn *)bc->contents; 633 x86_effaddr *x86_ea = insn->x86_ea; 634 yasm_effaddr *ea = &x86_ea->ea; 635 yasm_value *imm = insn->imm; 636 637 if (ea && span == 1) { 638 /* Change displacement length into word-sized */ 639 if (ea->disp.size == 8) { 640 ea->disp.size = (insn->common.addrsize == 16) ? 16 : 32; 641 x86_ea->modrm &= ~0300; 642 x86_ea->modrm |= 0200; 643 bc->len--; 644 bc->len += ea->disp.size/8; 645 } 646 } 647 648 if (imm && span == 2) { 649 if (insn->postop == X86_POSTOP_SIGNEXT_IMM8) { 650 /* Update bc->len for new opcode and immediate size */ 651 bc->len -= insn->opcode.len; 652 bc->len += imm->size/8; 653 654 /* Change to the word-sized opcode */ 655 insn->opcode.opcode[0] = insn->opcode.opcode[insn->opcode.len]; 656 insn->opcode.len = 1; 657 insn->postop = X86_POSTOP_NONE; 658 } 659 } 660 661 return 0; 662 } 663 664 static int 665 x86_bc_jmp_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, 666 void *add_span_data) 667 { 668 x86_jmp *jmp = (x86_jmp *)bc->contents; 669 yasm_bytecode *target_prevbc; 670 unsigned char opersize; 671 672 /* As opersize may be 0, figure out its "real" value. */ 673 opersize = (jmp->common.opersize == 0) ? 674 jmp->common.mode_bits : jmp->common.opersize; 675 676 bc->len += x86_common_calc_len(&jmp->common); 677 678 if (jmp->op_sel == JMP_NEAR_FORCED || jmp->shortop.len == 0) { 679 if (jmp->nearop.len == 0) { 680 yasm_error_set(YASM_ERROR_TYPE, N_("near jump does not exist")); 681 return -1; 682 } 683 684 /* Near jump, no spans needed */ 685 if (jmp->shortop.len == 0) 686 jmp->op_sel = JMP_NEAR; 687 bc->len += jmp->nearop.len; 688 bc->len += (opersize == 16) ? 2 : 4; 689 return 0; 690 } 691 692 if (jmp->op_sel == JMP_SHORT_FORCED || jmp->nearop.len == 0) { 693 if (jmp->shortop.len == 0) { 694 yasm_error_set(YASM_ERROR_TYPE, N_("short jump does not exist")); 695 return -1; 696 } 697 698 /* We want to be sure to error if we exceed short length, so 699 * put it in as a dependent expression (falling through). 700 */ 701 } 702 703 if (jmp->target.rel 704 && (!yasm_symrec_get_label(jmp->target.rel, &target_prevbc) 705 || target_prevbc->section != bc->section)) { 706 /* External or out of segment, so we can't check distance. 707 * Allowing short jumps depends on the objfmt supporting 708 * 8-bit relocs. While most don't, some might, so allow it here. 709 * Otherwise default to word-sized. 710 * The objfmt will error if not supported. 711 */ 712 if (jmp->op_sel == JMP_SHORT_FORCED || jmp->nearop.len == 0) { 713 if (jmp->op_sel == JMP_NONE) 714 jmp->op_sel = JMP_SHORT; 715 bc->len += jmp->shortop.len + 1; 716 } else { 717 jmp->op_sel = JMP_NEAR; 718 bc->len += jmp->nearop.len; 719 bc->len += (opersize == 16) ? 2 : 4; 720 } 721 return 0; 722 } 723 724 /* Default to short jump and generate span */ 725 if (jmp->op_sel == JMP_NONE) 726 jmp->op_sel = JMP_SHORT; 727 bc->len += jmp->shortop.len + 1; 728 add_span(add_span_data, bc, 1, &jmp->target, -128+(long)bc->len, 729 127+(long)bc->len); 730 return 0; 731 } 732 733 static int 734 x86_bc_jmp_expand(yasm_bytecode *bc, int span, long old_val, long new_val, 735 /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres) 736 { 737 x86_jmp *jmp = (x86_jmp *)bc->contents; 738 unsigned char opersize; 739 740 if (span != 1) 741 yasm_internal_error(N_("unrecognized span id")); 742 743 /* As opersize may be 0, figure out its "real" value. */ 744 opersize = (jmp->common.opersize == 0) ? 745 jmp->common.mode_bits : jmp->common.opersize; 746 747 if (jmp->op_sel == JMP_SHORT_FORCED || jmp->nearop.len == 0) { 748 yasm_error_set(YASM_ERROR_VALUE, N_("short jump out of range")); 749 return -1; 750 } 751 752 if (jmp->op_sel == JMP_NEAR) 753 yasm_internal_error(N_("trying to expand an already-near jump")); 754 755 /* Upgrade to a near jump */ 756 jmp->op_sel = JMP_NEAR; 757 bc->len -= jmp->shortop.len + 1; 758 bc->len += jmp->nearop.len; 759 bc->len += (opersize == 16) ? 2 : 4; 760 761 return 0; 762 } 763 764 static int 765 x86_bc_jmpfar_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, 766 void *add_span_data) 767 { 768 x86_jmpfar *jmpfar = (x86_jmpfar *)bc->contents; 769 unsigned char opersize; 770 771 opersize = (jmpfar->common.opersize == 0) ? 772 jmpfar->common.mode_bits : jmpfar->common.opersize; 773 774 bc->len += jmpfar->opcode.len; 775 bc->len += 2; /* segment */ 776 bc->len += (opersize == 16) ? 2 : 4; 777 bc->len += x86_common_calc_len(&jmpfar->common); 778 779 return 0; 780 } 781 782 static void 783 x86_common_tobytes(const x86_common *common, unsigned char **bufp, 784 unsigned int segreg) 785 { 786 if (segreg != 0) 787 YASM_WRITE_8(*bufp, (unsigned char)segreg); 788 if (common->addrsize != 0 && common->addrsize != common->mode_bits) 789 YASM_WRITE_8(*bufp, 0x67); 790 if (common->opersize != 0 && 791 ((common->mode_bits != 64 && common->opersize != common->mode_bits) || 792 (common->mode_bits == 64 && common->opersize == 16))) 793 YASM_WRITE_8(*bufp, 0x66); 794 if (common->lockrep_pre != 0) 795 YASM_WRITE_8(*bufp, common->lockrep_pre); 796 } 797 798 static void 799 x86_opcode_tobytes(const x86_opcode *opcode, unsigned char **bufp) 800 { 801 unsigned int i; 802 for (i=0; i<opcode->len; i++) 803 YASM_WRITE_8(*bufp, opcode->opcode[i]); 804 } 805 806 static int 807 x86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, 808 unsigned char *bufstart, void *d, 809 yasm_output_value_func output_value, 810 /*@unused@*/ yasm_output_reloc_func output_reloc) 811 { 812 x86_insn *insn = (x86_insn *)bc->contents; 813 /*@null@*/ x86_effaddr *x86_ea = (x86_effaddr *)insn->x86_ea; 814 yasm_value *imm = insn->imm; 815 816 /* Prefixes */ 817 x86_common_tobytes(&insn->common, bufp, 818 x86_ea ? (unsigned int)(x86_ea->ea.segreg>>8) : 0); 819 if (insn->special_prefix != 0) 820 YASM_WRITE_8(*bufp, insn->special_prefix); 821 if (insn->special_prefix == 0xC4 || insn->special_prefix == 0x8F) { 822 /* 3-byte VEX/XOP; merge in 1s complement of REX.R, REX.X, REX.B */ 823 insn->opcode.opcode[0] &= 0x1F; 824 if (insn->rex != 0xff) 825 insn->opcode.opcode[0] |= ((~insn->rex) & 0x07) << 5; 826 /* merge REX.W via ORing; there should never be a case in which REX.W 827 * is important when VEX.W is already set by the instruction. 828 */ 829 if (insn->rex != 0xff && (insn->rex & 0x8) != 0) 830 insn->opcode.opcode[1] |= 0x80; 831 } else if (insn->special_prefix == 0xC5) { 832 /* 2-byte VEX; merge in 1s complement of REX.R */ 833 insn->opcode.opcode[0] &= 0x7F; 834 if (insn->rex != 0xff && (insn->rex & 0x4) == 0) 835 insn->opcode.opcode[0] |= 0x80; 836 /* No other REX bits should be set */ 837 if (insn->rex != 0xff && (insn->rex & 0xB) != 0) 838 yasm_internal_error(N_("x86: REX.WXB set, but 2-byte VEX")); 839 } else if (insn->rex != 0xff && insn->rex != 0) { 840 if (insn->common.mode_bits != 64) 841 yasm_internal_error(N_("x86: got a REX prefix in non-64-bit mode")); 842 YASM_WRITE_8(*bufp, insn->rex); 843 } 844 845 /* Opcode */ 846 x86_opcode_tobytes(&insn->opcode, bufp); 847 848 /* Effective address: ModR/M (if required), SIB (if required), and 849 * displacement (if required). 850 */ 851 if (x86_ea) { 852 if (x86_ea->need_modrm) { 853 if (!x86_ea->valid_modrm) 854 yasm_internal_error(N_("invalid Mod/RM in x86 tobytes_insn")); 855 YASM_WRITE_8(*bufp, x86_ea->modrm); 856 } 857 858 if (x86_ea->need_sib) { 859 if (!x86_ea->valid_sib) 860 yasm_internal_error(N_("invalid SIB in x86 tobytes_insn")); 861 YASM_WRITE_8(*bufp, x86_ea->sib); 862 } 863 864 if (x86_ea->ea.need_disp) { 865 unsigned int disp_len = x86_ea->ea.disp.size/8; 866 867 if (x86_ea->ea.disp.ip_rel) { 868 /* Adjust relative displacement to end of bytecode */ 869 /*@only@*/ yasm_intnum *delta; 870 delta = yasm_intnum_create_int(-(long)bc->len); 871 if (!x86_ea->ea.disp.abs) 872 x86_ea->ea.disp.abs = 873 yasm_expr_create_ident(yasm_expr_int(delta), bc->line); 874 else 875 x86_ea->ea.disp.abs = 876 yasm_expr_create(YASM_EXPR_ADD, 877 yasm_expr_expr(x86_ea->ea.disp.abs), 878 yasm_expr_int(delta), bc->line); 879 } 880 if (output_value(&x86_ea->ea.disp, *bufp, disp_len, 881 (unsigned long)(*bufp-bufstart), bc, 1, d)) 882 return 1; 883 *bufp += disp_len; 884 } 885 } 886 887 /* Immediate (if required) */ 888 if (imm) { 889 unsigned int imm_len; 890 if (insn->postop == X86_POSTOP_SIGNEXT_IMM8) { 891 /* If we got here with this postop still set, we need to force 892 * imm size to 8 here. 893 */ 894 imm->size = 8; 895 imm->sign = 1; 896 imm_len = 1; 897 } else 898 imm_len = imm->size/8; 899 if (output_value(imm, *bufp, imm_len, (unsigned long)(*bufp-bufstart), 900 bc, 1, d)) 901 return 1; 902 *bufp += imm_len; 903 } 904 905 return 0; 906 } 907 908 static int 909 x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp, 910 unsigned char *bufstart, void *d, 911 yasm_output_value_func output_value, 912 /*@unused@*/ yasm_output_reloc_func output_reloc) 913 { 914 x86_jmp *jmp = (x86_jmp *)bc->contents; 915 unsigned char opersize; 916 unsigned int i; 917 /*@only@*/ yasm_intnum *delta; 918 919 /* Prefixes */ 920 x86_common_tobytes(&jmp->common, bufp, 0); 921 922 /* As opersize may be 0, figure out its "real" value. */ 923 opersize = (jmp->common.opersize == 0) ? 924 jmp->common.mode_bits : jmp->common.opersize; 925 926 /* Check here again to see if forms are actually legal. */ 927 switch (jmp->op_sel) { 928 case JMP_SHORT_FORCED: 929 case JMP_SHORT: 930 /* 1 byte relative displacement */ 931 if (jmp->shortop.len == 0) 932 yasm_internal_error(N_("short jump does not exist")); 933 934 /* Opcode */ 935 x86_opcode_tobytes(&jmp->shortop, bufp); 936 937 /* Adjust relative displacement to end of bytecode */ 938 delta = yasm_intnum_create_int(-(long)bc->len); 939 if (!jmp->target.abs) 940 jmp->target.abs = yasm_expr_create_ident(yasm_expr_int(delta), 941 bc->line); 942 else 943 jmp->target.abs = 944 yasm_expr_create(YASM_EXPR_ADD, 945 yasm_expr_expr(jmp->target.abs), 946 yasm_expr_int(delta), bc->line); 947 948 jmp->target.size = 8; 949 jmp->target.sign = 1; 950 if (output_value(&jmp->target, *bufp, 1, 951 (unsigned long)(*bufp-bufstart), bc, 1, d)) 952 return 1; 953 *bufp += 1; 954 break; 955 case JMP_NEAR_FORCED: 956 case JMP_NEAR: 957 /* 2/4 byte relative displacement (depending on operand size) */ 958 if (jmp->nearop.len == 0) { 959 yasm_error_set(YASM_ERROR_TYPE, 960 N_("near jump does not exist")); 961 return 1; 962 } 963 964 /* Opcode */ 965 x86_opcode_tobytes(&jmp->nearop, bufp); 966 967 i = (opersize == 16) ? 2 : 4; 968 969 /* Adjust relative displacement to end of bytecode */ 970 delta = yasm_intnum_create_int(-(long)bc->len); 971 if (!jmp->target.abs) 972 jmp->target.abs = yasm_expr_create_ident(yasm_expr_int(delta), 973 bc->line); 974 else 975 jmp->target.abs = 976 yasm_expr_create(YASM_EXPR_ADD, 977 yasm_expr_expr(jmp->target.abs), 978 yasm_expr_int(delta), bc->line); 979 980 jmp->target.size = i*8; 981 jmp->target.sign = 1; 982 if (output_value(&jmp->target, *bufp, i, 983 (unsigned long)(*bufp-bufstart), bc, 1, d)) 984 return 1; 985 *bufp += i; 986 break; 987 case JMP_NONE: 988 yasm_internal_error(N_("jump op_sel cannot be JMP_NONE in tobytes")); 989 default: 990 yasm_internal_error(N_("unrecognized relative jump op_sel")); 991 } 992 return 0; 993 } 994 995 static int 996 x86_bc_jmpfar_tobytes(yasm_bytecode *bc, unsigned char **bufp, 997 unsigned char *bufstart, void *d, 998 yasm_output_value_func output_value, 999 /*@unused@*/ yasm_output_reloc_func output_reloc) 1000 { 1001 x86_jmpfar *jmpfar = (x86_jmpfar *)bc->contents; 1002 unsigned int i; 1003 unsigned char opersize; 1004 1005 x86_common_tobytes(&jmpfar->common, bufp, 0); 1006 x86_opcode_tobytes(&jmpfar->opcode, bufp); 1007 1008 /* As opersize may be 0, figure out its "real" value. */ 1009 opersize = (jmpfar->common.opersize == 0) ? 1010 jmpfar->common.mode_bits : jmpfar->common.opersize; 1011 1012 /* Absolute displacement: segment and offset */ 1013 i = (opersize == 16) ? 2 : 4; 1014 jmpfar->offset.size = i*8; 1015 if (output_value(&jmpfar->offset, *bufp, i, 1016 (unsigned long)(*bufp-bufstart), bc, 1, d)) 1017 return 1; 1018 *bufp += i; 1019 jmpfar->segment.size = 16; 1020 if (output_value(&jmpfar->segment, *bufp, 2, 1021 (unsigned long)(*bufp-bufstart), bc, 1, d)) 1022 return 1; 1023 *bufp += 2; 1024 1025 return 0; 1026 } 1027 1028 int 1029 yasm_x86__intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn, 1030 unsigned char *buf, size_t destsize, size_t valsize, 1031 int shift, const yasm_bytecode *bc, int warn) 1032 { 1033 /* Write value out. */ 1034 yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn); 1035 return 0; 1036 } 1037