145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* 245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * x86 bytecode utility functions 345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Copyright (C) 2001-2007 Peter Johnson 545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Redistribution and use in source and binary forms, with or without 745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * modification, are permitted provided that the following conditions 845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * are met: 945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 1. Redistributions of source code must retain the above copyright 1045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * notice, this list of conditions and the following disclaimer. 1145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 2. Redistributions in binary form must reproduce the above copyright 1245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * notice, this list of conditions and the following disclaimer in the 1345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * documentation and/or other materials provided with the distribution. 1445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 1545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' 1645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE 1945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * POSSIBILITY OF SUCH DAMAGE. 2645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 2745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <util.h> 2845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 2945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <libyasm.h> 3045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 3145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "x86arch.h" 3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Bytecode callback function prototypes */ 3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void x86_bc_insn_destroy(void *contents); 3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void x86_bc_insn_print(const void *contents, FILE *f, 3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int indent_level); 3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int x86_bc_insn_calc_len(yasm_bytecode *bc, 4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bc_add_span_func add_span, 4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void *add_span_data); 4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int x86_bc_insn_expand(yasm_bytecode *bc, int span, long old_val, 4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org long new_val, /*@out@*/ long *neg_thres, 4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@out@*/ long *pos_thres); 4545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int x86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, 46d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org unsigned char *bufstart, 4745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void *d, yasm_output_value_func output_value, 4845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@null@*/ yasm_output_reloc_func output_reloc); 4945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 5045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void x86_bc_jmp_destroy(void *contents); 5145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void x86_bc_jmp_print(const void *contents, FILE *f, int indent_level); 5245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int x86_bc_jmp_calc_len(yasm_bytecode *bc, 5345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bc_add_span_func add_span, 5445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void *add_span_data); 5545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int x86_bc_jmp_expand(yasm_bytecode *bc, int span, long old_val, 5645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org long new_val, /*@out@*/ long *neg_thres, 5745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@out@*/ long *pos_thres); 5845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp, 59d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org unsigned char *bufstart, 6045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void *d, yasm_output_value_func output_value, 6145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@null@*/ yasm_output_reloc_func output_reloc); 6245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 6345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void x86_bc_jmpfar_destroy(void *contents); 6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void x86_bc_jmpfar_print(const void *contents, FILE *f, 6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int indent_level); 6645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int x86_bc_jmpfar_calc_len(yasm_bytecode *bc, 6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bc_add_span_func add_span, 6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void *add_span_data); 6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int x86_bc_jmpfar_tobytes 70d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d, 7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_output_value_func output_value, 7245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@null@*/ yasm_output_reloc_func output_reloc); 7345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Bytecode callback structures */ 7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const yasm_bytecode_callback x86_bc_callback_insn = { 7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_bc_insn_destroy, 7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_bc_insn_print, 7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bc_finalize_common, 8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org NULL, 8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_bc_insn_calc_len, 8245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_bc_insn_expand, 8345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_bc_insn_tobytes, 8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 0 8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}; 8645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const yasm_bytecode_callback x86_bc_callback_jmp = { 8845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_bc_jmp_destroy, 8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_bc_jmp_print, 9045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bc_finalize_common, 9145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org NULL, 9245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_bc_jmp_calc_len, 9345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_bc_jmp_expand, 9445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_bc_jmp_tobytes, 9545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 0 9645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}; 9745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 9845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic const yasm_bytecode_callback x86_bc_callback_jmpfar = { 9945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_bc_jmpfar_destroy, 10045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_bc_jmpfar_print, 10145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bc_finalize_common, 10245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org NULL, 10345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_bc_jmpfar_calc_len, 10445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bc_expand_common, 10545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_bc_jmpfar_tobytes, 10645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 0 10745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}; 10845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 10945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgint 110a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.orgyasm_x86__set_rex_from_reg(unsigned char *rex, unsigned char *low3, 111a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org uintptr_t reg, unsigned int bits, 112a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org x86_rex_bit_pos rexbit) 11345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 11445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *low3 = (unsigned char)(reg&7); 11545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (bits == 64) { 11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_expritem_reg_size size = (x86_expritem_reg_size)(reg & ~0xFUL); 11845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (size == X86_REG8X || (reg & 0xF) >= 8) { 120a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org /* Check to make sure we can set it */ 121a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org if (*rex == 0xff) { 122a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org yasm_error_set(YASM_ERROR_TYPE, 123a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org N_("cannot use A/B/C/DH with instruction needing REX")); 124a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org return 1; 12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 126a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org *rex |= 0x40 | (((reg & 8) >> 3) << rexbit); 12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else if (size == X86_REG8 && (reg & 7) >= 4) { 12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* AH/BH/CH/DH, so no REX allowed */ 12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (*rex != 0 && *rex != 0xff) { 13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_error_set(YASM_ERROR_TYPE, 13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org N_("cannot use A/B/C/DH with instruction needing REX")); 13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *rex = 0xff; /* Flag so we can NEVER set it (see above) */ 13545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_x86__bc_transform_insn(yasm_bytecode *bc, x86_insn *insn) 14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bc_transform(bc, &x86_bc_callback_insn, insn); 14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 14845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_x86__bc_transform_jmp(yasm_bytecode *bc, x86_jmp *jmp) 14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bc_transform(bc, &x86_bc_callback_jmp, jmp); 15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 15245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 15345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 15445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_x86__bc_transform_jmpfar(yasm_bytecode *bc, x86_jmpfar *jmpfar) 15545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 15645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bc_transform(bc, &x86_bc_callback_jmpfar, jmpfar); 15745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 15845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 15945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 160a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.orgyasm_x86__ea_init(x86_effaddr *x86_ea, unsigned int spare, 161a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org yasm_bytecode *precbc) 16245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 16345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (yasm_value_finalize(&x86_ea->ea.disp, precbc)) 16445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_error_set(YASM_ERROR_TOO_COMPLEX, 16545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org N_("effective address too complex")); 16645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->modrm &= 0xC7; /* zero spare/reg bits */ 16745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->modrm |= (spare << 3) & 0x38; /* plug in provided bits */ 16845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 16945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 17045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 17145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_x86__ea_set_disponly(x86_effaddr *x86_ea) 17245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 17345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->valid_modrm = 0; 17445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->need_modrm = 0; 17545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->valid_sib = 0; 17645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->need_sib = 0; 17745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 17845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 17945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic x86_effaddr * 18045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgea_create(void) 18145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 18245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_effaddr *x86_ea = yasm_xmalloc(sizeof(x86_effaddr)); 18345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 18445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value_initialize(&x86_ea->ea.disp, NULL, 0); 18545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->ea.need_nonzero_len = 0; 18645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->ea.need_disp = 0; 18745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->ea.nosplit = 0; 18845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->ea.strong = 0; 18945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->ea.segreg = 0; 19045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->ea.pc_rel = 0; 19145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->ea.not_pc_rel = 0; 19245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->ea.data_len = 0; 193d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org x86_ea->vsib_mode = 0; 19445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->modrm = 0; 19545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->valid_modrm = 0; 19645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->need_modrm = 0; 19745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->sib = 0; 19845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->valid_sib = 0; 19945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->need_sib = 0; 20045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 20145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return x86_ea; 20245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 20345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 20445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_effaddr * 20545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_x86__ea_create_reg(x86_effaddr *x86_ea, unsigned long reg, 206a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org unsigned char *rex, unsigned int bits) 20745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 20845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned char rm; 20945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 210a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org if (yasm_x86__set_rex_from_reg(rex, &rm, reg, bits, X86_REX_B)) 21145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return NULL; 21245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 21345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!x86_ea) 21445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea = ea_create(); 21545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->modrm = 0xC0 | rm; /* Mod=11, R/M=Reg, Reg=0 */ 21645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->valid_modrm = 1; 21745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->need_modrm = 1; 21845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 21945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return x86_ea; 22045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 22145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 22245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_effaddr * 22345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_x86__ea_create_expr(yasm_arch *arch, yasm_expr *e) 22445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 22545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch; 22645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_effaddr *x86_ea; 22745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 22845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea = ea_create(); 22945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 23045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (arch_x86->parser == X86_PARSER_GAS) { 231a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org /* Need to change foo+rip into foo wrt rip (even in .intel_syntax mode). 23245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Note this assumes a particular ordering coming from the parser 23345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * to work (it's not very smart)! 23445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 23545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (e->op == YASM_EXPR_ADD && e->terms[0].type == YASM_EXPR_REG 23645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && e->terms[0].data.reg == X86_RIP) { 23745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* replace register with 0 */ 23845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[0].type = YASM_EXPR_INT; 23945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e->terms[0].data.intn = yasm_intnum_create_uint(0); 24045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* build new wrt expression */ 24145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org e = yasm_expr_create(YASM_EXPR_WRT, yasm_expr_expr(e), 24245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_reg(X86_RIP), e->line); 24345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 24445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 24545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value_initialize(&x86_ea->ea.disp, e, 0); 24645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->ea.need_disp = 1; 24745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->need_modrm = 1; 24845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* We won't know whether we need an SIB until we know more about expr and 24945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * the BITS/address override setting. 25045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 25145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->need_sib = 0xff; 25245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 25345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->ea.data_len = 0; 25445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 25545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return (yasm_effaddr *)x86_ea; 25645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 25745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 25845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*@-compmempass@*/ 25945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_effaddr * 26045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_x86__ea_create_imm(x86_effaddr *x86_ea, yasm_expr *imm, 26145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int im_len) 26245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 26345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!x86_ea) 26445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea = ea_create(); 26545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value_initialize(&x86_ea->ea.disp, imm, im_len); 26645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->ea.need_disp = 1; 26745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 26845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return x86_ea; 26945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 27045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*@=compmempass@*/ 27145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 27245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 27345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_x86__bc_apply_prefixes(x86_common *common, unsigned char *rex, 27445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int def_opersize_64, 27545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int num_prefixes, uintptr_t *prefixes) 27645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 27745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int i; 27845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int first = 1; 27945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 28045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<num_prefixes; i++) { 28145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch ((x86_parse_insn_prefix)(prefixes[i] & 0xff00)) { 28245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case X86_LOCKREP: 28345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (common->lockrep_pre != 0) 28445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_warn_set(YASM_WARN_GENERAL, 28545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org N_("multiple LOCK or REP prefixes, using leftmost")); 28645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org common->lockrep_pre = (unsigned char)prefixes[i] & 0xff; 28745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 28845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case X86_ADDRSIZE: 28945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org common->addrsize = (unsigned char)prefixes[i] & 0xff; 29045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 29145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case X86_OPERSIZE: 29245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org common->opersize = (unsigned char)prefixes[i] & 0xff; 29345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (common->mode_bits == 64 && common->opersize == 64 && 29445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org def_opersize_64 != 64) { 29545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!rex) 29645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_warn_set(YASM_WARN_GENERAL, 29745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org N_("ignoring REX prefix on jump")); 29845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else if (*rex == 0xff) 29945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_warn_set(YASM_WARN_GENERAL, 30045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org N_("REX prefix not allowed on this instruction, ignoring")); 30145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 30245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *rex = 0x48; 30345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 30445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 30545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case X86_SEGREG: 30645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* This is a hack.. we should really be putting this in the 30745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * the effective address! 30845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 30945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org common->lockrep_pre = (unsigned char)prefixes[i] & 0xff; 31045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 31145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case X86_REX: 31245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!rex) 31345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_warn_set(YASM_WARN_GENERAL, 31445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org N_("ignoring REX prefix on jump")); 31545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else if (*rex == 0xff) 31645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_warn_set(YASM_WARN_GENERAL, 31745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org N_("REX prefix not allowed on this instruction, ignoring")); 31845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else { 31945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (*rex != 0) { 32045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (first) 32145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_warn_set(YASM_WARN_GENERAL, 32245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org N_("overriding generated REX prefix")); 32345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 32445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_warn_set(YASM_WARN_GENERAL, 32545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org N_("multiple REX prefixes, using leftmost")); 32645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 32745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Here we assume that we can't get this prefix in non 32845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 64 bit mode due to checks in parse_check_prefix(). 32945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 33045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org common->mode_bits = 64; 33145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *rex = (unsigned char)prefixes[i] & 0xff; 33245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 33345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org first = 0; 33445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 33545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 33645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 33745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 33845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 33945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void 34045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_bc_insn_destroy(void *contents) 34145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 34245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_insn *insn = (x86_insn *)contents; 34345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (insn->x86_ea) 34445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_x86__ea_destroy((yasm_effaddr *)insn->x86_ea); 34545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (insn->imm) { 34645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value_delete(insn->imm); 34745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_xfree(insn->imm); 34845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 34945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_xfree(contents); 35045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 35145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 35245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void 35345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_bc_jmp_destroy(void *contents) 35445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 35545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_jmp *jmp = (x86_jmp *)contents; 35645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value_delete(&jmp->target); 35745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_xfree(contents); 35845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 35945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 36045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void 36145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_bc_jmpfar_destroy(void *contents) 36245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 36345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_jmpfar *jmpfar = (x86_jmpfar *)contents; 36445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value_delete(&jmpfar->segment); 36545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value_delete(&jmpfar->offset); 36645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_xfree(contents); 36745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 36845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 36945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 37045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_x86__ea_destroy(yasm_effaddr *ea) 37145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 37245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value_delete(&ea->disp); 37345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_xfree(ea); 37445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 37545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 37645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid 37745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_x86__ea_print(const yasm_effaddr *ea, FILE *f, int indent_level) 37845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 37945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org const x86_effaddr *x86_ea = (const x86_effaddr *)ea; 38045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sDisp:\n", indent_level, ""); 38145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value_print(&ea->disp, f, indent_level+1); 38245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sNoSplit=%u\n", indent_level, "", (unsigned int)ea->nosplit); 38345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sSegmentOv=%02x\n", indent_level, "", 38445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)x86_ea->ea.segreg); 385d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org fprintf(f, "%*sVSIBMode=%u\n", indent_level, "", 386d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org (unsigned int)x86_ea->vsib_mode); 38745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sModRM=%03o ValidRM=%u NeedRM=%u\n", indent_level, "", 38845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)x86_ea->modrm, (unsigned int)x86_ea->valid_modrm, 38945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)x86_ea->need_modrm); 39045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sSIB=%03o ValidSIB=%u NeedSIB=%u\n", indent_level, "", 39145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)x86_ea->sib, (unsigned int)x86_ea->valid_sib, 39245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)x86_ea->need_sib); 39345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 39445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 39545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void 39645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_common_print(const x86_common *common, FILE *f, int indent_level) 39745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 39845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sAddrSize=%u OperSize=%u LockRepPre=%02x BITS=%u\n", 39945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org indent_level, "", 40045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)common->addrsize, 40145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)common->opersize, 40245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)common->lockrep_pre, 40345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)common->mode_bits); 40445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 40545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 40645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void 40745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_opcode_print(const x86_opcode *opcode, FILE *f, int indent_level) 40845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 40945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sOpcode: %02x %02x %02x OpLen=%u\n", indent_level, "", 41045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)opcode->opcode[0], 41145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)opcode->opcode[1], 41245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)opcode->opcode[2], 41345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)opcode->len); 41445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 41545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 41645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void 41745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_bc_insn_print(const void *contents, FILE *f, int indent_level) 41845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 41945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org const x86_insn *insn = (const x86_insn *)contents; 42045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 42145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*s_Instruction_\n", indent_level, ""); 42245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sEffective Address:", indent_level, ""); 42345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (insn->x86_ea) { 42445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "\n"); 42545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_x86__ea_print((yasm_effaddr *)insn->x86_ea, f, indent_level+1); 42645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else 42745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, " (nil)\n"); 42845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sImmediate Value:", indent_level, ""); 42945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!insn->imm) 43045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, " (nil)\n"); 43145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else { 43245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org indent_level++; 43345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "\n"); 43445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value_print(insn->imm, f, indent_level); 43545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org indent_level--; 43645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 43745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_opcode_print(&insn->opcode, f, indent_level); 43845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_common_print(&insn->common, f, indent_level); 43945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sSpPre=%02x REX=%03o PostOp=%u\n", indent_level, "", 44045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)insn->special_prefix, 44145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)insn->rex, 44245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (unsigned int)insn->postop); 44345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 44445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 44545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void 44645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_bc_jmp_print(const void *contents, FILE *f, int indent_level) 44745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 44845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org const x86_jmp *jmp = (const x86_jmp *)contents; 44945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 45045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*s_Jump_\n", indent_level, ""); 45145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sTarget:\n", indent_level, ""); 45245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value_print(&jmp->target, f, indent_level+1); 45345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* FIXME 45445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sOrigin=\n", indent_level, ""); 45545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_symrec_print(jmp->origin, f, indent_level+1); 45645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 45745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "\n%*sShort Form:\n", indent_level, ""); 45845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (jmp->shortop.len == 0) 45945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sNone\n", indent_level+1, ""); 46045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 46145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_opcode_print(&jmp->shortop, f, indent_level+1); 46245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sNear Form:\n", indent_level, ""); 46345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (jmp->nearop.len == 0) 46445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sNone\n", indent_level+1, ""); 46545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 46645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_opcode_print(&jmp->nearop, f, indent_level+1); 46745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sOpSel=", indent_level, ""); 46845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch (jmp->op_sel) { 46945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case JMP_NONE: 47045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "None"); 47145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 47245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case JMP_SHORT: 47345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "Short"); 47445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 47545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case JMP_NEAR: 47645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "Near"); 47745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 47845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case JMP_SHORT_FORCED: 47945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "Forced Short"); 48045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 48145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case JMP_NEAR_FORCED: 48245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "Forced Near"); 48345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 48445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org default: 48545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "UNKNOWN!!"); 48645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 48745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 48845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_common_print(&jmp->common, f, indent_level); 48945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 49045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 49145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void 49245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_bc_jmpfar_print(const void *contents, FILE *f, int indent_level) 49345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 49445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org const x86_jmpfar *jmpfar = (const x86_jmpfar *)contents; 49545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 49645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*s_Far_Jump_\n", indent_level, ""); 49745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sSegment:\n", indent_level, ""); 49845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value_print(&jmpfar->segment, f, indent_level+1); 49945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fprintf(f, "%*sOffset:\n", indent_level, ""); 50045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value_print(&jmpfar->offset, f, indent_level+1); 50145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_opcode_print(&jmpfar->opcode, f, indent_level); 50245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_common_print(&jmpfar->common, f, indent_level); 50345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 50445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 50545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic unsigned int 50645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_common_calc_len(const x86_common *common) 50745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 50845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int len = 0; 50945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 51045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (common->addrsize != 0 && common->addrsize != common->mode_bits) 51145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org len++; 51245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (common->opersize != 0 && 51345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ((common->mode_bits != 64 && common->opersize != common->mode_bits) || 51445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (common->mode_bits == 64 && common->opersize == 16))) 51545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org len++; 51645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (common->lockrep_pre != 0) 51745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org len++; 51845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 51945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return len; 52045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 52145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 52245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 52345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_bc_insn_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, 52445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void *add_span_data) 52545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 52645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_insn *insn = (x86_insn *)bc->contents; 52745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_effaddr *x86_ea = insn->x86_ea; 52845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value *imm = insn->imm; 52945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 53045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (x86_ea) { 53145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Check validity of effective address and calc R/M bits of 53245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Mod/RM byte and SIB byte. We won't know the Mod field 53345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * of the Mod/RM byte until we know more about the 53445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * displacement. 53545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 53645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (yasm_x86__expr_checkea(x86_ea, &insn->common.addrsize, 53745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->common.mode_bits, insn->postop == X86_POSTOP_ADDRESS16, 53845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org &insn->rex, bc)) 53945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* failed, don't bother checking rest of insn */ 54045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return -1; 54145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 54245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (x86_ea->ea.disp.size == 0 && x86_ea->ea.need_nonzero_len) { 54345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Handle unknown case, default to byte-sized and set as 54445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * critical expression. 54545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 54645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->ea.disp.size = 8; 54745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org add_span(add_span_data, bc, 1, &x86_ea->ea.disp, -128, 127); 54845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 54945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += x86_ea->ea.disp.size/8; 55045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 55145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Handle address16 postop case */ 55245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (insn->postop == X86_POSTOP_ADDRESS16) 55345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->common.addrsize = 0; 55445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 55545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Compute length of ea and add to total */ 55645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += x86_ea->need_modrm + (x86_ea->need_sib ? 1:0); 55745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += (x86_ea->ea.segreg != 0) ? 1 : 0; 55845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 55945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 56045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (imm) { 56145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int immlen = imm->size; 56245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 56345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* TODO: check imm->len vs. sized len from expr? */ 56445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 56545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Handle signext_imm8 postop special-casing */ 56645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (insn->postop == X86_POSTOP_SIGNEXT_IMM8) { 56745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@null@*/ /*@only@*/ yasm_intnum *num; 56845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org num = yasm_value_get_intnum(imm, NULL, 0); 56945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 57045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!num) { 57145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Unknown; default to byte form and set as critical 57245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * expression. 57345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 57445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org immlen = 8; 57545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org add_span(add_span_data, bc, 2, imm, -128, 127); 57645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else { 57745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (yasm_intnum_in_range(num, -128, 127)) { 57845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* We can use the sign-extended byte form: shorten 57945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * the immediate length to 1 and make the byte form 58045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * permanent. 58145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 58245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org imm->size = 8; 58345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org imm->sign = 1; 58445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org immlen = 8; 58545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else { 58645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* We can't. Copy over the word-sized opcode. */ 58745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->opcode.opcode[0] = 58845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->opcode.opcode[insn->opcode.len]; 58945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->opcode.len = 1; 59045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 59145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->postop = X86_POSTOP_NONE; 59245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_destroy(num); 59345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 59445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 59545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 59645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += immlen/8; 59745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 59845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 599a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org /* VEX and XOP prefixes never have REX (it's embedded in the opcode). 600a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org * For VEX, we can come into this function with the three byte form, 601a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org * so we need to see if we can optimize to the two byte form. 602a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org * We can't do it earlier, as we don't know all of the REX byte until now. 60345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 60445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (insn->special_prefix == 0xC4) { 60545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* See if we can shorten the VEX prefix to its two byte form. 60645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * In order to do this, REX.X, REX.B, and REX.W/VEX.W must all be 0, 60745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * and the VEX mmmmm field must be 1. 60845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 60945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if ((insn->opcode.opcode[0] & 0x1F) == 1 && 61045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (insn->opcode.opcode[1] & 0x80) == 0 && 61145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (insn->rex == 0xff || (insn->rex & 0x0B) == 0)) { 61245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->opcode.opcode[0] = insn->opcode.opcode[1]; 61345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->opcode.opcode[1] = insn->opcode.opcode[2]; 61445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->opcode.opcode[2] = 0; /* sanity */ 61545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->opcode.len = 2; 61645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->special_prefix = 0xC5; /* mark as two-byte VEX */ 61745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 61845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else if (insn->rex != 0xff && insn->rex != 0 && 619a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org insn->special_prefix != 0xC5 && insn->special_prefix != 0x8F) 62045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len++; 62145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 62245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += insn->opcode.len; 62345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += x86_common_calc_len(&insn->common); 62445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += (insn->special_prefix != 0) ? 1:0; 62545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 62645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 62745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 62845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 62945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_bc_insn_expand(yasm_bytecode *bc, int span, long old_val, long new_val, 63045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres) 63145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 63245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_insn *insn = (x86_insn *)bc->contents; 63345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_effaddr *x86_ea = insn->x86_ea; 63445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_effaddr *ea = &x86_ea->ea; 63545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value *imm = insn->imm; 63645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 63745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (ea && span == 1) { 63845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Change displacement length into word-sized */ 63945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (ea->disp.size == 8) { 64045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ea->disp.size = (insn->common.addrsize == 16) ? 16 : 32; 64145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->modrm &= ~0300; 64245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->modrm |= 0200; 64345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len--; 64445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += ea->disp.size/8; 64545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 64645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 64745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 64845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (imm && span == 2) { 64945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (insn->postop == X86_POSTOP_SIGNEXT_IMM8) { 65045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Update bc->len for new opcode and immediate size */ 65145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len -= insn->opcode.len; 65245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += imm->size/8; 65345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 65445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Change to the word-sized opcode */ 65545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->opcode.opcode[0] = insn->opcode.opcode[insn->opcode.len]; 65645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->opcode.len = 1; 65745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->postop = X86_POSTOP_NONE; 65845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 65945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 66045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 66145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 66245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 66345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 66445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 66545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_bc_jmp_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, 66645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void *add_span_data) 66745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 66845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_jmp *jmp = (x86_jmp *)bc->contents; 66945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_bytecode *target_prevbc; 67045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned char opersize; 67145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 67245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* As opersize may be 0, figure out its "real" value. */ 67345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org opersize = (jmp->common.opersize == 0) ? 67445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->common.mode_bits : jmp->common.opersize; 67545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 67645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += x86_common_calc_len(&jmp->common); 67745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 67845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (jmp->op_sel == JMP_NEAR_FORCED || jmp->shortop.len == 0) { 67945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (jmp->nearop.len == 0) { 68045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_error_set(YASM_ERROR_TYPE, N_("near jump does not exist")); 68145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return -1; 68245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 68345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 68445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Near jump, no spans needed */ 68545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (jmp->shortop.len == 0) 68645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->op_sel = JMP_NEAR; 68745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += jmp->nearop.len; 68845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += (opersize == 16) ? 2 : 4; 68945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 69045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 69145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 69245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (jmp->op_sel == JMP_SHORT_FORCED || jmp->nearop.len == 0) { 69345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (jmp->shortop.len == 0) { 69445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_error_set(YASM_ERROR_TYPE, N_("short jump does not exist")); 69545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return -1; 69645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 69745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 69845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* We want to be sure to error if we exceed short length, so 69945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * put it in as a dependent expression (falling through). 70045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 70145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 70245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 70345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (jmp->target.rel 70445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org && (!yasm_symrec_get_label(jmp->target.rel, &target_prevbc) 70545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org || target_prevbc->section != bc->section)) { 70645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* External or out of segment, so we can't check distance. 70745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Allowing short jumps depends on the objfmt supporting 70845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * 8-bit relocs. While most don't, some might, so allow it here. 70945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * Otherwise default to word-sized. 71045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * The objfmt will error if not supported. 71145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 71245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (jmp->op_sel == JMP_SHORT_FORCED || jmp->nearop.len == 0) { 71345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (jmp->op_sel == JMP_NONE) 71445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->op_sel = JMP_SHORT; 71545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += jmp->shortop.len + 1; 71645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else { 71745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->op_sel = JMP_NEAR; 71845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += jmp->nearop.len; 71945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += (opersize == 16) ? 2 : 4; 72045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 72145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 72245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 72345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 72445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Default to short jump and generate span */ 72545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (jmp->op_sel == JMP_NONE) 72645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->op_sel = JMP_SHORT; 72745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += jmp->shortop.len + 1; 72845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org add_span(add_span_data, bc, 1, &jmp->target, -128+(long)bc->len, 72945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 127+(long)bc->len); 73045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 73145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 73245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 73345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 73445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_bc_jmp_expand(yasm_bytecode *bc, int span, long old_val, long new_val, 73545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres) 73645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 73745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_jmp *jmp = (x86_jmp *)bc->contents; 73845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned char opersize; 73945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 74045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (span != 1) 74145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_internal_error(N_("unrecognized span id")); 74245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 74345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* As opersize may be 0, figure out its "real" value. */ 74445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org opersize = (jmp->common.opersize == 0) ? 74545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->common.mode_bits : jmp->common.opersize; 74645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 74745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (jmp->op_sel == JMP_SHORT_FORCED || jmp->nearop.len == 0) { 74845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_error_set(YASM_ERROR_VALUE, N_("short jump out of range")); 74945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return -1; 75045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 75145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 75245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (jmp->op_sel == JMP_NEAR) 75345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_internal_error(N_("trying to expand an already-near jump")); 75445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 75545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Upgrade to a near jump */ 75645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->op_sel = JMP_NEAR; 75745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len -= jmp->shortop.len + 1; 75845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += jmp->nearop.len; 75945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += (opersize == 16) ? 2 : 4; 76045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 76145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 76245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 76345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 76445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 76545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_bc_jmpfar_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, 76645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void *add_span_data) 76745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 76845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_jmpfar *jmpfar = (x86_jmpfar *)bc->contents; 76945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned char opersize; 77045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 77145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org opersize = (jmpfar->common.opersize == 0) ? 77245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmpfar->common.mode_bits : jmpfar->common.opersize; 77345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 77445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += jmpfar->opcode.len; 77545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += 2; /* segment */ 77645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += (opersize == 16) ? 2 : 4; 77745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->len += x86_common_calc_len(&jmpfar->common); 77845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 77945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 78045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 78145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 78245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void 78345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_common_tobytes(const x86_common *common, unsigned char **bufp, 78445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int segreg) 78545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 78645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (segreg != 0) 78745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org YASM_WRITE_8(*bufp, (unsigned char)segreg); 78845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (common->addrsize != 0 && common->addrsize != common->mode_bits) 78945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org YASM_WRITE_8(*bufp, 0x67); 79045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (common->opersize != 0 && 79145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ((common->mode_bits != 64 && common->opersize != common->mode_bits) || 79245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org (common->mode_bits == 64 && common->opersize == 16))) 79345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org YASM_WRITE_8(*bufp, 0x66); 79445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (common->lockrep_pre != 0) 79545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org YASM_WRITE_8(*bufp, common->lockrep_pre); 79645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 79745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 79845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void 79945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgx86_opcode_tobytes(const x86_opcode *opcode, unsigned char **bufp) 80045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 80145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int i; 80245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org for (i=0; i<opcode->len; i++) 80345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org YASM_WRITE_8(*bufp, opcode->opcode[i]); 80445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 80545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 80645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 807d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.orgx86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, 808d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org unsigned char *bufstart, void *d, 80945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_output_value_func output_value, 81045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@unused@*/ yasm_output_reloc_func output_reloc) 81145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 81245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_insn *insn = (x86_insn *)bc->contents; 81345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@null@*/ x86_effaddr *x86_ea = (x86_effaddr *)insn->x86_ea; 81445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_value *imm = insn->imm; 81545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 81645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Prefixes */ 81745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_common_tobytes(&insn->common, bufp, 81845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea ? (unsigned int)(x86_ea->ea.segreg>>8) : 0); 81945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (insn->special_prefix != 0) 82045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org YASM_WRITE_8(*bufp, insn->special_prefix); 821a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org if (insn->special_prefix == 0xC4 || insn->special_prefix == 0x8F) { 822a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org /* 3-byte VEX/XOP; merge in 1s complement of REX.R, REX.X, REX.B */ 82345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->opcode.opcode[0] &= 0x1F; 82445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (insn->rex != 0xff) 82545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->opcode.opcode[0] |= ((~insn->rex) & 0x07) << 5; 82645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* merge REX.W via ORing; there should never be a case in which REX.W 82745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * is important when VEX.W is already set by the instruction. 82845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 82945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (insn->rex != 0xff && (insn->rex & 0x8) != 0) 83045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->opcode.opcode[1] |= 0x80; 83145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else if (insn->special_prefix == 0xC5) { 83245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* 2-byte VEX; merge in 1s complement of REX.R */ 83345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->opcode.opcode[0] &= 0x7F; 83445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (insn->rex != 0xff && (insn->rex & 0x4) == 0) 83545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org insn->opcode.opcode[0] |= 0x80; 83645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* No other REX bits should be set */ 83745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (insn->rex != 0xff && (insn->rex & 0xB) != 0) 83845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_internal_error(N_("x86: REX.WXB set, but 2-byte VEX")); 83945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else if (insn->rex != 0xff && insn->rex != 0) { 84045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (insn->common.mode_bits != 64) 84145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_internal_error(N_("x86: got a REX prefix in non-64-bit mode")); 84245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org YASM_WRITE_8(*bufp, insn->rex); 84345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 84445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 84545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Opcode */ 84645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_opcode_tobytes(&insn->opcode, bufp); 84745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 84845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Effective address: ModR/M (if required), SIB (if required), and 84945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * displacement (if required). 85045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 85145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (x86_ea) { 85245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (x86_ea->need_modrm) { 85345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!x86_ea->valid_modrm) 85445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_internal_error(N_("invalid Mod/RM in x86 tobytes_insn")); 85545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org YASM_WRITE_8(*bufp, x86_ea->modrm); 85645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 85745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 85845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (x86_ea->need_sib) { 85945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!x86_ea->valid_sib) 86045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_internal_error(N_("invalid SIB in x86 tobytes_insn")); 86145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org YASM_WRITE_8(*bufp, x86_ea->sib); 86245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 86345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 86445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (x86_ea->ea.need_disp) { 86545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int disp_len = x86_ea->ea.disp.size/8; 86645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 86745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (x86_ea->ea.disp.ip_rel) { 86845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Adjust relative displacement to end of bytecode */ 86945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@only@*/ yasm_intnum *delta; 87045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org delta = yasm_intnum_create_int(-(long)bc->len); 87145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!x86_ea->ea.disp.abs) 87245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->ea.disp.abs = 87345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_create_ident(yasm_expr_int(delta), bc->line); 87445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 87545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_ea->ea.disp.abs = 87645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_create(YASM_EXPR_ADD, 87745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_expr(x86_ea->ea.disp.abs), 87845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_int(delta), bc->line); 87945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 88045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (output_value(&x86_ea->ea.disp, *bufp, disp_len, 881d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org (unsigned long)(*bufp-bufstart), bc, 1, d)) 88245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 88345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *bufp += disp_len; 88445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 88545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 88645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 88745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Immediate (if required) */ 88845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (imm) { 88945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int imm_len; 89045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (insn->postop == X86_POSTOP_SIGNEXT_IMM8) { 89145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* If we got here with this postop still set, we need to force 89245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org * imm size to 8 here. 89345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org */ 89445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org imm->size = 8; 89545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org imm->sign = 1; 89645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org imm_len = 1; 89745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } else 89845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org imm_len = imm->size/8; 899d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org if (output_value(imm, *bufp, imm_len, (unsigned long)(*bufp-bufstart), 90045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc, 1, d)) 90145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 90245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *bufp += imm_len; 90345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 90445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 90545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 90645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 90745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 90845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 909d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.orgx86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp, 910d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org unsigned char *bufstart, void *d, 91145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_output_value_func output_value, 91245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@unused@*/ yasm_output_reloc_func output_reloc) 91345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 91445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_jmp *jmp = (x86_jmp *)bc->contents; 91545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned char opersize; 91645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int i; 91745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@only@*/ yasm_intnum *delta; 91845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 91945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Prefixes */ 92045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_common_tobytes(&jmp->common, bufp, 0); 92145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 92245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* As opersize may be 0, figure out its "real" value. */ 92345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org opersize = (jmp->common.opersize == 0) ? 92445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->common.mode_bits : jmp->common.opersize; 92545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 92645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Check here again to see if forms are actually legal. */ 92745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switch (jmp->op_sel) { 92845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case JMP_SHORT_FORCED: 92945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case JMP_SHORT: 93045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* 1 byte relative displacement */ 93145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (jmp->shortop.len == 0) 93245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_internal_error(N_("short jump does not exist")); 93345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 93445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Opcode */ 93545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_opcode_tobytes(&jmp->shortop, bufp); 93645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 93745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Adjust relative displacement to end of bytecode */ 93845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org delta = yasm_intnum_create_int(-(long)bc->len); 93945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!jmp->target.abs) 94045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->target.abs = yasm_expr_create_ident(yasm_expr_int(delta), 94145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->line); 94245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 94345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->target.abs = 94445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_create(YASM_EXPR_ADD, 94545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_expr(jmp->target.abs), 94645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_int(delta), bc->line); 94745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 94845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->target.size = 8; 94945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->target.sign = 1; 95045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (output_value(&jmp->target, *bufp, 1, 951d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org (unsigned long)(*bufp-bufstart), bc, 1, d)) 95245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 95345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *bufp += 1; 95445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 95545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case JMP_NEAR_FORCED: 95645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case JMP_NEAR: 95745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* 2/4 byte relative displacement (depending on operand size) */ 95845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (jmp->nearop.len == 0) { 95945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_error_set(YASM_ERROR_TYPE, 96045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org N_("near jump does not exist")); 96145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 96245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 96345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 96445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Opcode */ 96545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_opcode_tobytes(&jmp->nearop, bufp); 96645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 96745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org i = (opersize == 16) ? 2 : 4; 96845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 96945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Adjust relative displacement to end of bytecode */ 97045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org delta = yasm_intnum_create_int(-(long)bc->len); 97145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (!jmp->target.abs) 97245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->target.abs = yasm_expr_create_ident(yasm_expr_int(delta), 97345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bc->line); 97445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org else 97545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->target.abs = 97645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_create(YASM_EXPR_ADD, 97745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_expr(jmp->target.abs), 97845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_expr_int(delta), bc->line); 97945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 98045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->target.size = i*8; 98145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmp->target.sign = 1; 98245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (output_value(&jmp->target, *bufp, i, 983d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org (unsigned long)(*bufp-bufstart), bc, 1, d)) 98445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 98545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *bufp += i; 98645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org break; 98745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org case JMP_NONE: 98845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_internal_error(N_("jump op_sel cannot be JMP_NONE in tobytes")); 98945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org default: 99045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_internal_error(N_("unrecognized relative jump op_sel")); 99145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 99245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 99345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 99445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 99545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic int 996d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.orgx86_bc_jmpfar_tobytes(yasm_bytecode *bc, unsigned char **bufp, 997d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org unsigned char *bufstart, void *d, 99845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_output_value_func output_value, 99945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /*@unused@*/ yasm_output_reloc_func output_reloc) 100045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 100145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_jmpfar *jmpfar = (x86_jmpfar *)bc->contents; 100245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned int i; 100345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned char opersize; 100445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 100545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_common_tobytes(&jmpfar->common, bufp, 0); 100645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org x86_opcode_tobytes(&jmpfar->opcode, bufp); 100745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 100845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* As opersize may be 0, figure out its "real" value. */ 100945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org opersize = (jmpfar->common.opersize == 0) ? 101045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmpfar->common.mode_bits : jmpfar->common.opersize; 101145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 101245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Absolute displacement: segment and offset */ 101345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org i = (opersize == 16) ? 2 : 4; 101445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmpfar->offset.size = i*8; 101545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (output_value(&jmpfar->offset, *bufp, i, 1016d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org (unsigned long)(*bufp-bufstart), bc, 1, d)) 101745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 101845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *bufp += i; 101945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org jmpfar->segment.size = 16; 102045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (output_value(&jmpfar->segment, *bufp, 2, 1021d65182f1818d1c19e6f3866ab6e68a262fad5185hbono@chromium.org (unsigned long)(*bufp-bufstart), bc, 1, d)) 102245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 1; 102345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org *bufp += 2; 102445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 102545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 102645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 102745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 102845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgint 102945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyasm_x86__intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn, 103045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned char *buf, size_t destsize, size_t valsize, 103145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int shift, const yasm_bytecode *bc, int warn) 103245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{ 103345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org /* Write value out. */ 103445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn); 103545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return 0; 103645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 1037