125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Helper routines for disassembler for x86/x86-64. 225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Copyright (C) 2007, 2008 Red Hat, Inc. 325b3c049e70834cf33790a28643ab058b507b35cBen Cheng This file is part of Red Hat elfutils. 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Written by Ulrich Drepper <drepper@redhat.com>, 2007. 525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat elfutils is free software; you can redistribute it and/or modify 725b3c049e70834cf33790a28643ab058b507b35cBen Cheng it under the terms of the GNU General Public License as published by the 825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Free Software Foundation; version 2 of the License. 925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat elfutils is distributed in the hope that it will be useful, but 1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng General Public License for more details. 1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng You should have received a copy of the GNU General Public License along 1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng with Red Hat elfutils; if not, write to the Free Software Foundation, 1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat elfutils is an included package of the Open Invention Network. 2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng An included package of the Open Invention Network is a package for which 2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Open Invention Network licensees cross-license their patents. No patent 2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng license is granted, either expressly or impliedly, by designation as an 2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng included package. Should you wish to participate in the Open Invention 2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Network licensing program, please visit www.openinventionnetwork.com 2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng <http://www.openinventionnetwork.com>. */ 2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <inttypes.h> 2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stddef.h> 2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdio.h> 3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdint.h> 3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libasm.h> 3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3325b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct instr_enc 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The mnemonic. Especially encoded for the optimized table. */ 3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int mnemonic : MNEMONIC_BITS; 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The rep/repe prefixes. */ 3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int rep : 1; 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int repe : 1; 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Mnemonic suffix. */ 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int suffix : SUFFIX_BITS; 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Nonzero if the instruction uses modr/m. */ 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int modrm : 1; 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* 1st parameter. */ 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int fct1 : FCT1_BITS; 5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef STR1_BITS 5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int str1 : STR1_BITS; 5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int off1_1 : OFF1_1_BITS; 5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int off1_2 : OFF1_2_BITS; 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int off1_3 : OFF1_3_BITS; 5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* 2nd parameter. */ 5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int fct2 : FCT2_BITS; 5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef STR2_BITS 6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int str2 : STR2_BITS; 6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int off2_1 : OFF2_1_BITS; 6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int off2_2 : OFF2_2_BITS; 6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int off2_3 : OFF2_3_BITS; 6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* 3rd parameter. */ 6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int fct3 : FCT3_BITS; 6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef STR3_BITS 6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int str3 : STR3_BITS; 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int off3_1 : OFF3_1_BITS; 7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef OFF3_2_BITS 7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int off3_2 : OFF3_2_BITS; 7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef OFF3_3_BITS 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int off3_3 : OFF3_3_BITS; 7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}; 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8125b3c049e70834cf33790a28643ab058b507b35cBen Chengtypedef int (*opfct_t) (struct output_data *); 8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 8525b3c049e70834cf33790a28643ab058b507b35cBen Chengdata_prefix (struct output_data *d) 8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng char ch = '\0'; 8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->prefixes & has_cs) 8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ch = 'c'; 9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes &= ~has_cs; 9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (*d->prefixes & has_ds) 9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ch = 'd'; 9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes &= ~has_ds; 9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (*d->prefixes & has_es) 9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ch = 'e'; 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes &= ~has_es; 10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (*d->prefixes & has_fs) 10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ch = 'f'; 10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes &= ~has_fs; 10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (*d->prefixes & has_gs) 10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ch = 'g'; 11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes &= ~has_gs; 11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (*d->prefixes & has_ss) 11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ch = 's'; 11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes &= ~has_ss; 11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->bufcntp + 4 > d->bufsize) 12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *d->bufcntp + 4 - d->bufsize; 12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng d->bufp[(*d->bufcntp)++] = '%'; 12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng d->bufp[(*d->bufcntp)++] = ch; 12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng d->bufp[(*d->bufcntp)++] = 's'; 12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng d->bufp[(*d->bufcntp)++] = ':'; 12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 13325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char hiregs[8][4] = 13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 13725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char aregs[8][4] = 13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi" 14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 14125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char dregs[8][4] = 14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" 14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 14625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char aregs[8][4] = 14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define dregs aregs 15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 15425b3c049e70834cf33790a28643ab058b507b35cBen Chenggeneral_mod$r_m (struct output_data *d) 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng int r = data_prefix (d); 15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (r != 0) 15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return r; 15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int prefixes = *d->prefixes; 16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const uint8_t *data = &d->data[d->opoff1 / 8]; 16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *bufp = d->bufp; 16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t bufsize = d->bufsize; 16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t modrm = data[0]; 16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef X86_64 16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely ((prefixes & has_addr16) != 0)) 16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int16_t disp = 0; 17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool nodisp = false; 17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80) 17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* 16 bit displacement. */ 17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng disp = read_2sbyte_unaligned (&data[1]); 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((modrm & 0xc0) == 0x40) 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* 8 bit displacement. */ 17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng disp = *(const int8_t *) &data[1]; 17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((modrm & 0xc0) == 0) 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng nodisp = true; 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng char tmpbuf[sizeof ("-0x1234(%rr,%rr)")]; 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng int n; 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc7) == 6) 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx16, disp); 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng n = 0; 18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!nodisp) 19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx16, 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng disp < 0 ? "-" : "", disp < 0 ? -disp : disp); 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0x4) == 0) 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%b%c,%%%ci)", 19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng "xp"[(modrm >> 1) & 1], "sd"[modrm & 1]); 19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%%s)", 19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ((const char [4][3]) { "si", "di", "bp", "bx" })[modrm & 3]); 19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + n + 1 > bufsize) 20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + n + 1 - bufsize; 20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&bufp[*bufcntp], tmpbuf, n + 1); 20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += n; 20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 7) != 4) 21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng int32_t disp = 0; 21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool nodisp = false; 21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80) 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* 32 bit displacement. */ 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng disp = read_4sbyte_unaligned (&data[1]); 21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((modrm & 0xc0) == 0x40) 21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* 8 bit displacement. */ 22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng disp = *(const int8_t *) &data[1]; 22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((modrm & 0xc0) == 0) 22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng nodisp = true; 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng char tmpbuf[sizeof ("-0x12345678(%rrrr)")]; 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng int n; 22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (nodisp) 22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)", 22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng (prefixes & has_rex_b) ? hiregs[modrm & 7] : 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng aregs[modrm & 7]); 23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes & has_addr16) 23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes & has_rex_b) 23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng tmpbuf[n++] = 'd'; 23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng tmpbuf[2] = 'e'; 24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((modrm & 0xc7) != 5) 24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng int p; 24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%n%s)", 24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng disp < 0 ? "-" : "", disp < 0 ? -disp : disp, &p, 24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng (prefixes & has_rex_b) ? hiregs[modrm & 7] : 25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng aregs[modrm & 7]); 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes & has_addr16) 25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes & has_rex_b) 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng tmpbuf[n++] = 'd'; 25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng tmpbuf[p] = 'e'; 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%rip)", 26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng disp < 0 ? "-" : "", disp < 0 ? -disp : disp); 26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng d->symaddr_use = addr_rel_always; 26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng d->symaddr = disp; 27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp); 27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + n + 1 > bufsize) 27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + n + 1 - bufsize; 27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&bufp[*bufcntp], tmpbuf, n + 1); 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += n; 28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* SIB */ 28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t sib = data[1]; 28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng int32_t disp = 0; 28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool nodisp = false; 28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80 28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng || ((modrm & 0xc7) == 0x4 && (sib & 0x7) == 0x5)) 29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* 32 bit displacement. */ 29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng disp = read_4sbyte_unaligned (&data[2]); 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((modrm & 0xc0) == 0x40) 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* 8 bit displacement. */ 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng disp = *(const int8_t *) &data[2]; 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng nodisp = true; 29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng char tmpbuf[sizeof ("-0x12345678(%rrrr,%rrrr,N)")]; 29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *cp = tmpbuf; 30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int n; 30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25 30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (prefixes & has_rex_x) != 0 30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ) 30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!nodisp) 30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng n = snprintf (cp, sizeof (tmpbuf), "%s0x%" PRIx32, 31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng disp < 0 ? "-" : "", disp < 0 ? -disp : disp); 31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng cp += n; 31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = '('; 31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc7) != 0x4 || (sib & 0x7) != 0x5) 31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = '%'; 31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng cp = stpcpy (cp, 32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng (prefixes & has_rex_b) ? hiregs[sib & 7] : 32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng (prefixes & has_addr16) ? dregs[sib & 7] : 32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng aregs[sib & 7]); 32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((prefixes & (has_rex_b | has_addr16)) 32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng == (has_rex_b | has_addr16)) 32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = 'd'; 32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((sib & 0x38) != 0x20 33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (prefixes & has_rex_x) != 0 33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ) 33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = ','; 33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = '%'; 34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng cp = stpcpy (cp, 34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng (prefixes & has_rex_x) 34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? hiregs[(sib >> 3) & 7] : 34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng (prefixes & has_addr16) 34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? dregs[(sib >> 3) & 7] : 34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng aregs[(sib >> 3) & 7]); 34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((prefixes & (has_rex_b | has_addr16)) 35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng == (has_rex_b | has_addr16)) 35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = 'd'; 35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = ','; 35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = '0' + (1 << (sib >> 6)); 35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = ')'; 35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (! nodisp); 36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((prefixes & has_addr16) == 0) 36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx64, 36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int64_t) disp); 36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx32, disp); 37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng cp += n; 37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + (cp - tmpbuf) > bufsize) 37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + (cp - tmpbuf) - bufsize; 37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&bufp[*bufcntp], tmpbuf, cp - tmpbuf); 37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += cp - tmpbuf; 37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 38425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 38525b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_MOD$R_M (struct output_data *d) 38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 == 0); 38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t modrm = d->data[d->opoff1 / 8]; 38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc0) == 0xc0) 39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 / 8 == d->opoff2 / 8); 39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff2 % 8 == 5); 39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng //uint_fast8_t byte = d->data[d->opoff2 / 8] & 7; 39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t byte = modrm & 7; 39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *buf = d->bufp + *bufcntp; 39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed; 40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->prefixes & (has_rep | has_repne)) 40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng needed = snprintf (buf, avail, "%%%s", dregs[byte]); 40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng needed = snprintf (buf, avail, "%%mm%" PRIxFAST8, byte); 40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return needed - avail; 40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return general_mod$r_m (d); 41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 41425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 41525b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_Mod$R_m (struct output_data *d) 41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 == 0); 41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t modrm = d->data[d->opoff1 / 8]; 41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc0) == 0xc0) 42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 / 8 == d->opoff2 / 8); 42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff2 % 8 == 5); 42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng //uint_fast8_t byte = data[opoff2 / 8] & 7; 42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t byte = modrm & 7; 42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, 42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng byte); 43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return needed - avail; 43225b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->bufcntp += needed; 43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return general_mod$r_m (d); 43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 43925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 44025b3c049e70834cf33790a28643ab058b507b35cBen Chenggeneric_abs (struct output_data *d, const char *absstring 44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng , int abslen 44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define abslen 4 44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ) 44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int r = data_prefix (d); 44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (r != 0) 45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return r; 45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 == 0); 45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 / 8 == 1); 45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->param_start + abslen > d->end) 45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->param_start += abslen; 45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef X86_64 45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint32_t absval; 45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define ABSPRIFMT PRIx32 46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint64_t absval; 46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define ABSPRIFMT PRIx64 46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (abslen == 8) 46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng absval = read_8ubyte_unaligned (&d->data[1]); 46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng absval = read_4ubyte_unaligned (&d->data[1]); 46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "%s0x%" ABSPRIFMT, 47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng absstring, absval); 47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return needed - avail; 47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 47925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 48025b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_absval (struct output_data *d) 48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return generic_abs (d, "$" 48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng , 4 48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ); 48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 48925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 49025b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_abs (struct output_data *d) 49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return generic_abs (d, "" 49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng , 8 49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ); 49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 50025b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_ax (struct output_data *d) 50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 50225b3c049e70834cf33790a28643ab058b507b35cBen Cheng int is_16bit = (*d->prefixes & has_data16) != 0; 50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *bufp = d->bufp; 50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t bufsize = d->bufsize; 50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 50825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + 4 - is_16bit > bufsize) 50925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + 4 - is_16bit - bufsize; 51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = '%'; 51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (! is_16bit) 51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = ( 51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng (*d->prefixes & has_rex_w) ? 'r' : 51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 'e'); 51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = 'a'; 51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = 'x'; 52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 52625b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_ax$w (struct output_data *d) 52725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0) 52925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return FCT_ax (d); 53025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 53225b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *bufp = d->bufp; 53325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t bufsize = d->bufsize; 53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + 3 > bufsize) 53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + 3 - bufsize; 53725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = '%'; 53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = 'a'; 54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = 'l'; 54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 54625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng__attribute__ ((noinline)) 54825b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_crdb (struct output_data *d, const char *regstr) 54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->prefixes & has_data16) 55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 55325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 55425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 55525b3c049e70834cf33790a28643ab058b507b35cBen Cheng // XXX If this assert is true, use absolute offset below 55625b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 / 8 == 2); 55725b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 == 2); 55825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "%%%s%" PRIx32, 56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng regstr, (uint32_t) (d->data[d->opoff1 / 8] >> 3) & 7); 56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return needed - avail; 56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 56825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 56925b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_ccc (struct output_data *d) 57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return FCT_crdb (d, "cr"); 57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 57525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 57625b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_ddd (struct output_data *d) 57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return FCT_crdb (d, "db"); 57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 58225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 58325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_disp8 (struct output_data *d) 58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 == 0); 58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->param_start >= d->end) 58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 58825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int32_t offset = *(const int8_t *) (*d->param_start)++; 58925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32, 59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng (uint32_t) (d->addr + (*d->param_start - d->data) 59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng + offset)); 59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return needed - avail; 59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 60225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng__attribute__ ((noinline)) 60425b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_ds_xx (struct output_data *d, const char *reg) 60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng int prefix = *d->prefixes & SEGMENT_PREFIXES; 60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefix == 0) 60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes |= prefix = has_ds; 61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Make sure only one bit is set. */ 61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((prefix - 1) & prefix) 61225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng int r = data_prefix (d); 61525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 61625b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert ((*d->prefixes & prefix) == 0); 61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (r != 0) 61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return r; 62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 62225b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "(%%%s%s)", 62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes & idx_addr16 ? "e" : "r", 62625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes & idx_addr16 ? "" : "e", 62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng reg); 63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) needed - avail; 63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 63825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 63925b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_ds_bx (struct output_data *d) 64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return FCT_ds_xx (d, "bx"); 64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 64525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 64625b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_ds_si (struct output_data *d) 64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return FCT_ds_xx (d, "si"); 64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 65225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 65325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_dx (struct output_data *d) 65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + 7 > d->bufsize) 65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + 7 - d->bufsize; 65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&d->bufp[*bufcntp], "(%dx)", 5); 66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += 5; 66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 66425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 66825b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_es_di (struct output_data *d) 66925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "%%es:(%%%sdi)", 67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes & idx_addr16 ? "e" : "r" 67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 67625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes & idx_addr16 ? "" : "e" 67725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ); 67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) needed - avail; 68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 68425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 68525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 68825b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imm (struct output_data *d) 68925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 69025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 69125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 69225b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed; 69325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->prefixes & has_data16) 69425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 69525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->param_start + 2 > d->end) 69625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 69725b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint16_t word = read_2ubyte_unaligned_inc (*d->param_start); 69825b3c049e70834cf33790a28643ab058b507b35cBen Cheng needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word); 69925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 70025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 70125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 70225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->param_start + 4 > d->end) 70325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 70425b3c049e70834cf33790a28643ab058b507b35cBen Cheng int32_t word = read_4sbyte_unaligned_inc (*d->param_start); 70525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 70625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->prefixes & has_rex_w) 70725b3c049e70834cf33790a28643ab058b507b35cBen Cheng needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, 70825b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int64_t) word); 70925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 71025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 71125b3c049e70834cf33790a28643ab058b507b35cBen Cheng needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word); 71225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 71325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 71425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) needed - avail; 71525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 71625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 71725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 71825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 71925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 72025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 72125b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imm$w (struct output_data *d) 72225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 72325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0) 72425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return FCT_imm (d); 72525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 72625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 72725b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 72825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->param_start>= d->end) 72925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 73025b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t word = *(*d->param_start)++; 73125b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIxFAST8, word); 73225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 73325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) needed - avail; 73425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 73525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 73625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 73725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 73825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 73925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 74025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 74125b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imm64$w (struct output_data *d) 74225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 74325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) == 0 74425b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (*d->prefixes & has_data16) != 0) 74525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return FCT_imm$w (d); 74625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 74725b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 74825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 74925b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed; 75025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->prefixes & has_rex_w) 75125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 75225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->param_start + 8 > d->end) 75325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 75425b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint64_t word = read_8ubyte_unaligned_inc (*d->param_start); 75525b3c049e70834cf33790a28643ab058b507b35cBen Cheng needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, word); 75625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 75725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 75825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 75925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->param_start + 4 > d->end) 76025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 76125b3c049e70834cf33790a28643ab058b507b35cBen Cheng int32_t word = read_4sbyte_unaligned_inc (*d->param_start); 76225b3c049e70834cf33790a28643ab058b507b35cBen Cheng needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word); 76325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 76425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 76525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) needed - avail; 76625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 76725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 76825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 76925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 77025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 77125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 77225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 77325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imms (struct output_data *d) 77425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 77525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 77625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 77725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->param_start>= d->end) 77825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 77925b3c049e70834cf33790a28643ab058b507b35cBen Cheng int8_t byte = *(*d->param_start)++; 78025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 78125b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, 78225b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int64_t) byte); 78325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 78425b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, 78525b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int32_t) byte); 78625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 78725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 78825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) needed - avail; 78925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 79025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 79125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 79225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 79325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 79425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 79525b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imm$s (struct output_data *d) 79625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 79725b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t opcode = d->data[d->opoff2 / 8]; 79825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 79925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 80025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((opcode & 2) != 0) 80125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return FCT_imms (d); 80225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 80325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*d->prefixes & has_data16) == 0) 80425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 80525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->param_start + 4 > d->end) 80625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 80725b3c049e70834cf33790a28643ab058b507b35cBen Cheng int32_t word = read_4sbyte_unaligned_inc (*d->param_start); 80825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 80925b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, 81025b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int64_t) word); 81125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 81225b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word); 81325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 81425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 81525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) needed - avail; 81625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 81725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 81825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 81925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 82025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->param_start + 2 > d->end) 82125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 82225b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint16_t word = read_2ubyte_unaligned_inc (*d->param_start); 82325b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word); 82425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 82525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) needed - avail; 82625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 82725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 82825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 82925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 83025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 83125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 83225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 83325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imm16 (struct output_data *d) 83425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 83525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->param_start + 2 > d->end) 83625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 83725b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint16_t word = read_2ubyte_unaligned_inc (*d->param_start); 83825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 83925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 84025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word); 84125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 84225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) needed - avail; 84325b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 84425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 84525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 84625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 84725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 84825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 84925b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imms8 (struct output_data *d) 85025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 85125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 85225b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 85325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->param_start >= d->end) 85425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 85525b3c049e70834cf33790a28643ab058b507b35cBen Cheng int_fast8_t byte = *(*d->param_start)++; 85625b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed; 85725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 85825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->prefixes & has_rex_w) 85925b3c049e70834cf33790a28643ab058b507b35cBen Cheng needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, 86025b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int64_t) byte); 86125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 86225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 86325b3c049e70834cf33790a28643ab058b507b35cBen Cheng needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, 86425b3c049e70834cf33790a28643ab058b507b35cBen Cheng (int32_t) byte); 86525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 86625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) needed - avail; 86725b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 86825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 86925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 87025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 87125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 87225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 87325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_imm8 (struct output_data *d) 87425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 87525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 87625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 87725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->param_start >= d->end) 87825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 87925b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t byte = *(*d->param_start)++; 88025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, 88125b3c049e70834cf33790a28643ab058b507b35cBen Cheng (uint32_t) byte); 88225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 88325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) needed - avail; 88425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 88525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 88625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 88725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 88825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 88925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 89025b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_rel (struct output_data *d) 89125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 89225b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 89325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 89425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->param_start + 4 > d->end) 89525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 89625b3c049e70834cf33790a28643ab058b507b35cBen Cheng int32_t rel = read_4sbyte_unaligned_inc (*d->param_start); 89725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 89825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx64, 89925b3c049e70834cf33790a28643ab058b507b35cBen Cheng (uint64_t) (d->addr + rel 90025b3c049e70834cf33790a28643ab058b507b35cBen Cheng + (*d->param_start - d->data))); 90125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 90225b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32, 90325b3c049e70834cf33790a28643ab058b507b35cBen Cheng (uint32_t) (d->addr + rel 90425b3c049e70834cf33790a28643ab058b507b35cBen Cheng + (*d->param_start - d->data))); 90525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 90625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 90725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) needed - avail; 90825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 90925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 91025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 91125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 91225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 91325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 91425b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_mmxreg (struct output_data *d) 91525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 91625b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t byte = d->data[d->opoff1 / 8]; 91725b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5); 91825b3c049e70834cf33790a28643ab058b507b35cBen Cheng byte = (byte >> (5 - d->opoff1 % 8)) & 7; 91925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 92025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 92125b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte); 92225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 92325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return needed - avail; 92425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 92525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 92625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 92725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 92825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 92925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 93025b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_mod$r_m (struct output_data *d) 93125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 93225b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 == 0); 93325b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t modrm = d->data[d->opoff1 / 8]; 93425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc0) == 0xc0) 93525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 93625b3c049e70834cf33790a28643ab058b507b35cBen Cheng int prefixes = *d->prefixes; 93725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes & has_addr16) 93825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 93925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 94025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int is_16bit = (prefixes & has_data16) != 0; 94125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 94225b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 94325b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *bufp = d->bufp; 94425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + 5 - is_16bit > d->bufsize) 94525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + 5 - is_16bit - d->bufsize; 94625b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = '%'; 94725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 94825b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *cp; 94925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 95025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((prefixes & has_rex_b) != 0 && !is_16bit) 95125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 95225b3c049e70834cf33790a28643ab058b507b35cBen Cheng cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]); 95325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((prefixes & has_rex_w) == 0) 95425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = 'd'; 95525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 95625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 95725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 95825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 95925b3c049e70834cf33790a28643ab058b507b35cBen Cheng cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit); 96025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 96125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((prefixes & has_rex_w) != 0) 96225b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[*bufcntp] = 'r'; 96325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 96425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 96525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp = cp - bufp; 96625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 96725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 96825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 96925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return general_mod$r_m (d); 97025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 97125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 97225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 97325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef X86_64 97425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 97525b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_moda$r_m (struct output_data *d) 97625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 97725b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 == 0); 97825b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t modrm = d->data[d->opoff1 / 8]; 97925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc0) == 0xc0) 98025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 98125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->prefixes & has_addr16) 98225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 98325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 98425b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 98525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + 3 > d->bufsize) 98625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + 3 - d->bufsize; 98725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 98825b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&d->bufp[*bufcntp], "???", 3); 98925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += 3; 99025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 99125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 99225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 99325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 99425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return general_mod$r_m (d); 99525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 99625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 99725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 99825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 99925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 100025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char rex_8bit[8][3] = 100125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 100225b3c049e70834cf33790a28643ab058b507b35cBen Cheng [0] = "a", [1] = "c", [2] = "d", [3] = "b", 100325b3c049e70834cf33790a28643ab058b507b35cBen Cheng [4] = "sp", [5] = "bp", [6] = "si", [7] = "di" 100425b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 100525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 100625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 100725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 100825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 100925b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_mod$r_m$w (struct output_data *d) 101025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 101125b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 == 0); 101225b3c049e70834cf33790a28643ab058b507b35cBen Cheng const uint8_t *data = d->data; 101325b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t modrm = data[d->opoff1 / 8]; 101425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc0) == 0xc0) 101525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 101625b3c049e70834cf33790a28643ab058b507b35cBen Cheng int prefixes = *d->prefixes; 101725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 101825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes & has_addr16) 101925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 102025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 102125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 102225b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *bufp = d->bufp; 102325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + 5 > d->bufsize) 102425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + 5 - d->bufsize; 102525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 102625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((data[d->opoff3 / 8] & (1 << (7 - (d->opoff3 & 7)))) == 0) 102725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 102825b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = '%'; 102925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 103025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 103125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes & has_rex) 103225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 103325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes & has_rex_r) 103425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += snprintf (bufp + *bufcntp, d->bufsize - *bufcntp, 103525b3c049e70834cf33790a28643ab058b507b35cBen Cheng "r%db", 8 + (modrm & 7)); 103625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 103725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 103825b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *cp = stpcpy (bufp + *bufcntp, hiregs[modrm & 7]); 103925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = 'l'; 104025b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp = cp - bufp; 104125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 104225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 104325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 104425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 104525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 104625b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = "acdb"[modrm & 3]; 104725b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2]; 104825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 104925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 105025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 105125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 105225b3c049e70834cf33790a28643ab058b507b35cBen Cheng int is_16bit = (prefixes & has_data16) != 0; 105325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 105425b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = '%'; 105525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 105625b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *cp; 105725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 105825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((prefixes & has_rex_b) != 0 && !is_16bit) 105925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 106025b3c049e70834cf33790a28643ab058b507b35cBen Cheng cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]); 106125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((prefixes & has_rex_w) == 0) 106225b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = 'd'; 106325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 106425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 106525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 106625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 106725b3c049e70834cf33790a28643ab058b507b35cBen Cheng cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit); 106825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 106925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((prefixes & has_rex_w) != 0) 107025b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[*bufcntp] = 'r'; 107125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 107225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 107325b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp = cp - bufp; 107425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 107525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 107625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 107725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 107825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return general_mod$r_m (d); 107925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 108025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 108125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 108225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 108325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_mod$8r_m (struct output_data *d) 108425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 108525b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 == 0); 108625b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t modrm = d->data[d->opoff1 / 8]; 108725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc0) == 0xc0) 108825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 108925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 109025b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *bufp = d->bufp; 109125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + 3 > d->bufsize) 109225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + 3 - d->bufsize; 109325b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = '%'; 109425b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = "acdb"[modrm & 3]; 109525b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2]; 109625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 109725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 109825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 109925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return general_mod$r_m (d); 110025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 110125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 110225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 110325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 110425b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_mod$16r_m (struct output_data *d) 110525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 110625b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 == 0); 110725b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t modrm = d->data[d->opoff1 / 8]; 110825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc0) == 0xc0) 110925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 111025b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 / 8 == d->opoff2 / 8); 111125b3c049e70834cf33790a28643ab058b507b35cBen Cheng //uint_fast8_t byte = data[opoff2 / 8] & 7; 111225b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t byte = modrm & 7; 111325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 111425b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 111525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + 3 > d->bufsize) 111625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + 3 - d->bufsize; 111725b3c049e70834cf33790a28643ab058b507b35cBen Cheng d->bufp[(*bufcntp)++] = '%'; 111825b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&d->bufp[*bufcntp], dregs[byte] + 1, sizeof (dregs[0]) - 1); 111925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += 2; 112025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 112125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 112225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 112325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return general_mod$r_m (d); 112425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 112525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 112625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 112725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 112825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 112925b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_mod$64r_m (struct output_data *d) 113025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 113125b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 == 0); 113225b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t modrm = d->data[d->opoff1 / 8]; 113325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc0) == 0xc0) 113425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 113525b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 / 8 == d->opoff2 / 8); 113625b3c049e70834cf33790a28643ab058b507b35cBen Cheng //uint_fast8_t byte = data[opoff2 / 8] & 7; 113725b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t byte = modrm & 7; 113825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 113925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 114025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + 4 > d->bufsize) 114125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + 4 - d->bufsize; 114225b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *cp = &d->bufp[*bufcntp]; 114325b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = '%'; 114425b3c049e70834cf33790a28643ab058b507b35cBen Cheng cp = stpcpy (cp, 114525b3c049e70834cf33790a28643ab058b507b35cBen Cheng (*d->prefixes & has_rex_b) ? hiregs[byte] : aregs[byte]); 114625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp = cp - d->bufp; 114725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 114825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 114925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 115025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return general_mod$r_m (d); 115125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 115225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 115325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic typeof (FCT_mod$r_m) FCT_mod$64r_m __attribute__ ((alias ("FCT_mod$r_m"))); 115425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 115525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 115625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 115725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 115825b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_reg (struct output_data *d) 115925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 116025b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t byte = d->data[d->opoff1 / 8]; 116125b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 + 3 <= 8); 116225b3c049e70834cf33790a28643ab058b507b35cBen Cheng byte >>= 8 - (d->opoff1 % 8 + 3); 116325b3c049e70834cf33790a28643ab058b507b35cBen Cheng byte &= 7; 116425b3c049e70834cf33790a28643ab058b507b35cBen Cheng int is_16bit = (*d->prefixes & has_data16) != 0; 116525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 116625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + 5 > d->bufsize) 116725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + 5 - d->bufsize; 116825b3c049e70834cf33790a28643ab058b507b35cBen Cheng d->bufp[(*bufcntp)++] = '%'; 116925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 117025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*d->prefixes & has_rex_r) != 0 && !is_16bit) 117125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 117225b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d", 117325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8 + byte); 117425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*d->prefixes & has_rex_w) == 0) 117525b3c049e70834cf33790a28643ab058b507b35cBen Cheng d->bufp[(*bufcntp)++] = 'd'; 117625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 117725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 117825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 117925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 118025b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&d->bufp[*bufcntp], dregs[byte] + is_16bit, 3 - is_16bit); 118125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 118225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*d->prefixes & has_rex_w) != 0 && !is_16bit) 118325b3c049e70834cf33790a28643ab058b507b35cBen Cheng d->bufp[*bufcntp] = 'r'; 118425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 118525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += 3 - is_16bit; 118625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 118725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 118825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 118925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 119025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 119125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 119225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 119325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_oreg (struct output_data *d) 119425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 119525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Special form where register comes from opcode. The rex.B bit is used, 119625b3c049e70834cf33790a28643ab058b507b35cBen Cheng rex.R and rex.X are ignored. */ 119725b3c049e70834cf33790a28643ab058b507b35cBen Cheng int save_prefixes = *d->prefixes; 119825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 119925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes = ((save_prefixes & ~has_rex_r) 120025b3c049e70834cf33790a28643ab058b507b35cBen Cheng | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b))); 120125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 120225b3c049e70834cf33790a28643ab058b507b35cBen Cheng int r = FCT_reg (d); 120325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 120425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes = save_prefixes; 120525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 120625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return r; 120725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 120825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 120925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 121025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 121125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 121225b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_reg64 (struct output_data *d) 121325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 121425b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t byte = d->data[d->opoff1 / 8]; 121525b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 + 3 <= 8); 121625b3c049e70834cf33790a28643ab058b507b35cBen Cheng byte >>= 8 - (d->opoff1 % 8 + 3); 121725b3c049e70834cf33790a28643ab058b507b35cBen Cheng byte &= 7; 121825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*d->prefixes & has_data16) != 0) 121925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 122025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 122125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + 5 > d->bufsize) 122225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + 5 - d->bufsize; 122325b3c049e70834cf33790a28643ab058b507b35cBen Cheng d->bufp[(*bufcntp)++] = '%'; 122425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 122525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*d->prefixes & has_rex_r) != 0) 122625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 122725b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d", 122825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8 + byte); 122925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*d->prefixes & has_rex_w) == 0) 123025b3c049e70834cf33790a28643ab058b507b35cBen Cheng d->bufp[(*bufcntp)++] = 'd'; 123125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 123225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 123325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 123425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 123525b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (&d->bufp[*bufcntp], aregs[byte], 3); 123625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += 3; 123725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 123825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 123925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 124025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 124125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 124225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 124325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_reg$w (struct output_data *d) 124425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 124525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) 124625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return FCT_reg (d); 124725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 124825b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t byte = d->data[d->opoff1 / 8]; 124925b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 + 3 <= 8); 125025b3c049e70834cf33790a28643ab058b507b35cBen Cheng byte >>= 8 - (d->opoff1 % 8 + 3); 125125b3c049e70834cf33790a28643ab058b507b35cBen Cheng byte &= 7; 125225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 125325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 125425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + 4 > d->bufsize) 125525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + 4 - d->bufsize; 125625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 125725b3c049e70834cf33790a28643ab058b507b35cBen Cheng d->bufp[(*bufcntp)++] = '%'; 125825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 125925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 126025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->prefixes & has_rex) 126125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 126225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->prefixes & has_rex_r) 126325b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += snprintf (d->bufp + *bufcntp, d->bufsize - *bufcntp, 126425b3c049e70834cf33790a28643ab058b507b35cBen Cheng "r%db", 8 + byte); 126525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 126625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 126725b3c049e70834cf33790a28643ab058b507b35cBen Cheng char* cp = stpcpy (d->bufp + *bufcntp, rex_8bit[byte]); 126825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = 'l'; 126925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp = cp - d->bufp; 127025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 127125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 127225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 127325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 127425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 127525b3c049e70834cf33790a28643ab058b507b35cBen Cheng d->bufp[(*bufcntp)++] = "acdb"[byte & 3]; 127625b3c049e70834cf33790a28643ab058b507b35cBen Cheng d->bufp[(*bufcntp)++] = "lh"[byte >> 2]; 127725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 127825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 127925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 128025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 128125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 128225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 128325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 128425b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_oreg$w (struct output_data *d) 128525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 128625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Special form where register comes from opcode. The rex.B bit is used, 128725b3c049e70834cf33790a28643ab058b507b35cBen Cheng rex.R and rex.X are ignored. */ 128825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int save_prefixes = *d->prefixes; 128925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 129025b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes = ((save_prefixes & ~has_rex_r) 129125b3c049e70834cf33790a28643ab058b507b35cBen Cheng | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b))); 129225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 129325b3c049e70834cf33790a28643ab058b507b35cBen Cheng int r = FCT_reg$w (d); 129425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 129525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes = save_prefixes; 129625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 129725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return r; 129825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 129925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 130025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 130125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 130225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 130325b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_freg (struct output_data *d) 130425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 130525b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 / 8 == 1); 130625b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 == 5); 130725b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 130825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 130925b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "%%st(%" PRIx32 ")", 131025b3c049e70834cf33790a28643ab058b507b35cBen Cheng (uint32_t) (d->data[1] & 7)); 131125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 131225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (size_t) needed - avail; 131325b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 131425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 131525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 131625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 131725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 131825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef X86_64 131925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 132025b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_reg16 (struct output_data *d) 132125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 132225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->prefixes & has_data16) 132325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 132425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 132525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->prefixes |= has_data16; 132625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return FCT_reg (d); 132725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 132825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 132925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 133025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 133125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 133225b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_sel (struct output_data *d) 133325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 133425b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 == 0); 133525b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 / 8 == 5); 133625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*d->param_start + 2 > d->end) 133725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 133825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *d->param_start += 2; 133925b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint16_t absval = read_2ubyte_unaligned (&d->data[5]); 134025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 134125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 134225b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 134325b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, absval); 134425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 134525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return needed - avail; 134625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 134725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 134825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 134925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 135025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 135125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 135225b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_sreg2 (struct output_data *d) 135325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 135425b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t byte = d->data[d->opoff1 / 8]; 135525b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 + 3 <= 8); 135625b3c049e70834cf33790a28643ab058b507b35cBen Cheng byte >>= 8 - (d->opoff1 % 8 + 2); 135725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 135825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 135925b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *bufp = d->bufp; 136025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + 3 > d->bufsize) 136125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + 3 - d->bufsize; 136225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 136325b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = '%'; 136425b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = "ecsd"[byte & 3]; 136525b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = 's'; 136625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 136725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 136825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 136925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 137025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 137125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 137225b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_sreg3 (struct output_data *d) 137325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 137425b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t byte = d->data[d->opoff1 / 8]; 137525b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 + 4 <= 8); 137625b3c049e70834cf33790a28643ab058b507b35cBen Cheng byte >>= 8 - (d->opoff1 % 8 + 3); 137725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 137825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((byte & 7) >= 6) 137925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 138025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 138125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 138225b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *bufp = d->bufp; 138325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*bufcntp + 3 > d->bufsize) 138425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *bufcntp + 3 - d->bufsize; 138525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 138625b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = '%'; 138725b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = "ecsdfg"[byte & 7]; 138825b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufp[(*bufcntp)++] = 's'; 138925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 139025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 139125b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 139225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 139325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 139425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 139525b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_string (struct output_data *d __attribute__ ((unused))) 139625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 139725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 139825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 139925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 140025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 140125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 140225b3c049e70834cf33790a28643ab058b507b35cBen ChengFCT_xmmreg (struct output_data *d) 140325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 140425b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t byte = d->data[d->opoff1 / 8]; 140525b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5); 140625b3c049e70834cf33790a28643ab058b507b35cBen Cheng byte = (byte >> (5 - d->opoff1 % 8)) & 7; 140725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 140825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp = d->bufcntp; 140925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = d->bufsize - *bufcntp; 141025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, byte); 141125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) needed > avail) 141225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return needed - avail; 141325b3c049e70834cf33790a28643ab058b507b35cBen Cheng *bufcntp += needed; 141425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 141525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 1416