1cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Helper routines for disassembler for x86/x86-64. 2cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Copyright (C) 2007, 2008 Red Hat, Inc. 3cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng This file is part of Red Hat elfutils. 4cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Written by Ulrich Drepper <drepper@redhat.com>, 2007. 5cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 6cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is free software; you can redistribute it and/or modify 7cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng it under the terms of the GNU General Public License as published by the 8cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Free Software Foundation; version 2 of the License. 9cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 10cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is distributed in the hope that it will be useful, but 11cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 12cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng General Public License for more details. 14cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 15cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng You should have received a copy of the GNU General Public License along 16cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng with Red Hat elfutils; if not, write to the Free Software Foundation, 17cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 18cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 19cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is an included package of the Open Invention Network. 20cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng An included package of the Open Invention Network is a package for which 21cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Open Invention Network licensees cross-license their patents. No patent 22cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng license is granted, either expressly or impliedly, by designation as an 23cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng included package. Should you wish to participate in the Open Invention 24cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Network licensing program, please visit www.openinventionnetwork.com 25cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng <http://www.openinventionnetwork.com>. */ 26cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 27cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <inttypes.h> 28cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stddef.h> 29cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdio.h> 30cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdint.h> 31cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <libasm.h> 32cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 33cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstruct instr_enc 34cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 35cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The mnemonic. Especially encoded for the optimized table. */ 36cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int mnemonic : MNEMONIC_BITS; 37cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 38cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The rep/repe prefixes. */ 39cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int rep : 1; 40cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int repe : 1; 41cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 42cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Mnemonic suffix. */ 43cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int suffix : SUFFIX_BITS; 44cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 45cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Nonzero if the instruction uses modr/m. */ 46cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int modrm : 1; 47cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 48cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* 1st parameter. */ 49cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int fct1 : FCT1_BITS; 50cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef STR1_BITS 51cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int str1 : STR1_BITS; 52cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 53cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int off1_1 : OFF1_1_BITS; 54cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int off1_2 : OFF1_2_BITS; 55cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int off1_3 : OFF1_3_BITS; 56cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 57cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* 2nd parameter. */ 58cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int fct2 : FCT2_BITS; 59cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef STR2_BITS 60cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int str2 : STR2_BITS; 61cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 62cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int off2_1 : OFF2_1_BITS; 63cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int off2_2 : OFF2_2_BITS; 64cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int off2_3 : OFF2_3_BITS; 65cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 66cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* 3rd parameter. */ 67cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int fct3 : FCT3_BITS; 68cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef STR3_BITS 69cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int str3 : STR3_BITS; 70cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 71cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int off3_1 : OFF3_1_BITS; 72cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef OFF3_2_BITS 73cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int off3_2 : OFF3_2_BITS; 74cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 75cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef OFF3_3_BITS 76cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int off3_3 : OFF3_3_BITS; 77cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 78cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}; 79cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 80cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 81cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengtypedef int (*opfct_t) (struct output_data *); 82cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 83cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 84cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 85cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdata_prefix (struct output_data *d) 86cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 87cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char ch = '\0'; 88cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->prefixes & has_cs) 89cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 90cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ch = 'c'; 91cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes &= ~has_cs; 92cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 93cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (*d->prefixes & has_ds) 94cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 95cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ch = 'd'; 96cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes &= ~has_ds; 97cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 98cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (*d->prefixes & has_es) 99cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ch = 'e'; 101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes &= ~has_es; 102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (*d->prefixes & has_fs) 104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ch = 'f'; 106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes &= ~has_fs; 107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (*d->prefixes & has_gs) 109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ch = 'g'; 111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes &= ~has_gs; 112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (*d->prefixes & has_ss) 114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ch = 's'; 116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes &= ~has_ss; 117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->bufcntp + 4 > d->bufsize) 122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *d->bufcntp + 4 - d->bufsize; 123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d->bufp[(*d->bufcntp)++] = '%'; 125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d->bufp[(*d->bufcntp)++] = ch; 126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d->bufp[(*d->bufcntp)++] = 's'; 127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d->bufp[(*d->bufcntp)++] = ':'; 128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char hiregs[8][4] = 134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char aregs[8][4] = 138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi" 140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char dregs[8][4] = 142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" 144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else 146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char aregs[8][4] = 147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" 149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define dregs aregs 151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenggeneral_mod$r_m (struct output_data *d) 155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int r = data_prefix (d); 157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (r != 0) 158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return r; 159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int prefixes = *d->prefixes; 161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const uint8_t *data = &d->data[d->opoff1 / 8]; 162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *bufp = d->bufp; 163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t bufsize = d->bufsize; 165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t modrm = data[0]; 167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifndef X86_64 168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely ((prefixes & has_addr16) != 0)) 169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int16_t disp = 0; 171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool nodisp = false; 172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80) 174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* 16 bit displacement. */ 175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng disp = read_2sbyte_unaligned (&data[1]); 176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if ((modrm & 0xc0) == 0x40) 177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* 8 bit displacement. */ 178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng disp = *(const int8_t *) &data[1]; 179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if ((modrm & 0xc0) == 0) 180cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nodisp = true; 181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 182cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char tmpbuf[sizeof ("-0x1234(%rr,%rr)")]; 183cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int n; 184cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 0xc7) == 6) 185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx16, disp); 186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 187cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 188cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng n = 0; 189cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!nodisp) 190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx16, 191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng disp < 0 ? "-" : "", disp < 0 ? -disp : disp); 192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 0x4) == 0) 194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%b%c,%%%ci)", 195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng "xp"[(modrm >> 1) & 1], "sd"[modrm & 1]); 196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%%s)", 198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ((const char [4][3]) { "si", "di", "bp", "bx" })[modrm & 3]); 199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + n + 1 > bufsize) 202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + n + 1 - bufsize; 203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memcpy (&bufp[*bufcntp], tmpbuf, n + 1); 205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += n; 206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 7) != 4) 211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int32_t disp = 0; 213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool nodisp = false; 214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80) 216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* 32 bit displacement. */ 217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng disp = read_4sbyte_unaligned (&data[1]); 218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if ((modrm & 0xc0) == 0x40) 219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* 8 bit displacement. */ 220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng disp = *(const int8_t *) &data[1]; 221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if ((modrm & 0xc0) == 0) 222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nodisp = true; 223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char tmpbuf[sizeof ("-0x12345678(%rrrr)")]; 225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int n; 226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (nodisp) 227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)", 229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (prefixes & has_rex_b) ? hiregs[modrm & 7] : 231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng aregs[modrm & 7]); 233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (prefixes & has_addr16) 235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (prefixes & has_rex_b) 237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng tmpbuf[n++] = 'd'; 238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng tmpbuf[2] = 'e'; 240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if ((modrm & 0xc7) != 5) 244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int p; 246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%n%s)", 247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng disp < 0 ? "-" : "", disp < 0 ? -disp : disp, &p, 248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (prefixes & has_rex_b) ? hiregs[modrm & 7] : 250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng aregs[modrm & 7]); 252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (prefixes & has_addr16) 254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (prefixes & has_rex_b) 256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng tmpbuf[n++] = 'd'; 257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 258cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng tmpbuf[p] = 'e'; 259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%rip)", 266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng disp < 0 ? "-" : "", disp < 0 ? -disp : disp); 267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d->symaddr_use = addr_rel_always; 269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d->symaddr = disp; 270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else 271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp); 272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + n + 1 > bufsize) 276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + n + 1 - bufsize; 277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memcpy (&bufp[*bufcntp], tmpbuf, n + 1); 279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += n; 280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* SIB */ 284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t sib = data[1]; 285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int32_t disp = 0; 286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bool nodisp = false; 287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80 289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || ((modrm & 0xc7) == 0x4 && (sib & 0x7) == 0x5)) 290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* 32 bit displacement. */ 291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng disp = read_4sbyte_unaligned (&data[2]); 292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if ((modrm & 0xc0) == 0x40) 293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* 8 bit displacement. */ 294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng disp = *(const int8_t *) &data[2]; 295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng nodisp = true; 297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char tmpbuf[sizeof ("-0x12345678(%rrrr,%rrrr,N)")]; 299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *cp = tmpbuf; 300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int n; 301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25 302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (prefixes & has_rex_x) != 0 304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ) 306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!nodisp) 308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng n = snprintf (cp, sizeof (tmpbuf), "%s0x%" PRIx32, 310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng disp < 0 ? "-" : "", disp < 0 ? -disp : disp); 311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cp += n; 312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp++ = '('; 315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 0xc7) != 0x4 || (sib & 0x7) != 0x5) 317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp++ = '%'; 319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cp = stpcpy (cp, 320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (prefixes & has_rex_b) ? hiregs[sib & 7] : 322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (prefixes & has_addr16) ? dregs[sib & 7] : 323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 324cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng aregs[sib & 7]); 325cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 326cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((prefixes & (has_rex_b | has_addr16)) 327cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng == (has_rex_b | has_addr16)) 328cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp++ = 'd'; 329cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((sib & 0x38) != 0x20 333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (prefixes & has_rex_x) != 0 335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ) 337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp++ = ','; 339cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp++ = '%'; 340cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cp = stpcpy (cp, 341cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (prefixes & has_rex_x) 343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ? hiregs[(sib >> 3) & 7] : 344cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (prefixes & has_addr16) 345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ? dregs[(sib >> 3) & 7] : 346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng aregs[(sib >> 3) & 7]); 348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((prefixes & (has_rex_b | has_addr16)) 350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng == (has_rex_b | has_addr16)) 351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp++ = 'd'; 352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp++ = ','; 355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp++ = '0' + (1 << (sib >> 6)); 356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp++ = ')'; 359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (! nodisp); 363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((prefixes & has_addr16) == 0) 365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx64, 366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int64_t) disp); 367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx32, disp); 370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cp += n; 371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + (cp - tmpbuf) > bufsize) 374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + (cp - tmpbuf) - bufsize; 375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memcpy (&bufp[*bufcntp], tmpbuf, cp - tmpbuf); 377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += cp - tmpbuf; 378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_MOD$R_M (struct output_data *d) 386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 387cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 == 0); 388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t modrm = d->data[d->opoff1 / 8]; 389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 0xc0) == 0xc0) 390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 / 8 == d->opoff2 / 8); 392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff2 % 8 == 5); 393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng //uint_fast8_t byte = d->data[d->opoff2 / 8] & 7; 394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t byte = modrm & 7; 395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *buf = d->bufp + *bufcntp; 398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed; 400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->prefixes & (has_rep | has_repne)) 401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng needed = snprintf (buf, avail, "%%%s", dregs[byte]); 402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng needed = snprintf (buf, avail, "%%mm%" PRIxFAST8, byte); 404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return needed - avail; 406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 408cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return general_mod$r_m (d); 411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_Mod$R_m (struct output_data *d) 416cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 417cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 == 0); 418cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t modrm = d->data[d->opoff1 / 8]; 419cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 0xc0) == 0xc0) 420cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 421cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 / 8 == d->opoff2 / 8); 422cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff2 % 8 == 5); 423cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng //uint_fast8_t byte = data[opoff2 / 8] & 7; 424cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t byte = modrm & 7; 425cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 426cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, 429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng byte); 430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return needed - avail; 432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->bufcntp += needed; 433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return general_mod$r_m (d); 437cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 438cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 439cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 440cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chenggeneric_abs (struct output_data *d, const char *absstring 441cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 442cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng , int abslen 443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else 444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define abslen 4 445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ) 447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int r = data_prefix (d); 449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (r != 0) 450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return r; 451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 452cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 == 0); 453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 / 8 == 1); 454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->param_start + abslen > d->end) 455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->param_start += abslen; 457cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifndef X86_64 458cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint32_t absval; 459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define ABSPRIFMT PRIx32 460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else 461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint64_t absval; 462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define ABSPRIFMT PRIx64 463cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (abslen == 8) 464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng absval = read_8ubyte_unaligned (&d->data[1]); 465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng absval = read_4ubyte_unaligned (&d->data[1]); 468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "%s0x%" ABSPRIFMT, 471cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng absstring, absval); 472cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 473cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return needed - avail; 474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 478cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 479cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 480cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_absval (struct output_data *d) 481cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 482cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return generic_abs (d, "$" 483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng , 4 485cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 486cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ); 487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 488cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 489cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 490cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_abs (struct output_data *d) 491cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 492cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return generic_abs (d, "" 493cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 494cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng , 8 495cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 496cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ); 497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 498cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 499cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 500cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_ax (struct output_data *d) 501cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 502cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int is_16bit = (*d->prefixes & has_data16) != 0; 503cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 504cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 505cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *bufp = d->bufp; 506cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t bufsize = d->bufsize; 507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 508cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + 4 - is_16bit > bufsize) 509cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + 4 - is_16bit - bufsize; 510cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 511cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = '%'; 512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (! is_16bit) 513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = ( 514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 515cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (*d->prefixes & has_rex_w) ? 'r' : 516cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 517cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 'e'); 518cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = 'a'; 519cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = 'x'; 520cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 521cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 522cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 523cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 524cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 525cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_ax$w (struct output_data *d) 527cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 528cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0) 529cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return FCT_ax (d); 530cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 532cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *bufp = d->bufp; 533cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t bufsize = d->bufsize; 534cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 535cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + 3 > bufsize) 536cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + 3 - bufsize; 537cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 538cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = '%'; 539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = 'a'; 540cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = 'l'; 541cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 543cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 544cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 545cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 546cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 547cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng__attribute__ ((noinline)) 548cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_crdb (struct output_data *d, const char *regstr) 549cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 550cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->prefixes & has_data16) 551cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 552cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 553cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 554cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng // XXX If this assert is true, use absolute offset below 556cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 / 8 == 2); 557cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 == 2); 558cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 559cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "%%%s%" PRIx32, 560cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng regstr, (uint32_t) (d->data[d->opoff1 / 8] >> 3) & 7); 561cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 562cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return needed - avail; 563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 564cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 565cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 566cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 567cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 568cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 569cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_ccc (struct output_data *d) 570cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 571cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return FCT_crdb (d, "cr"); 572cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 573cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 574cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 575cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 576cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_ddd (struct output_data *d) 577cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 578cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return FCT_crdb (d, "db"); 579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 580cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 581cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 582cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 583cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_disp8 (struct output_data *d) 584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 == 0); 586cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->param_start >= d->end) 587cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 588cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int32_t offset = *(const int8_t *) (*d->param_start)++; 589cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 590cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 591cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32, 593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (uint32_t) (d->addr + (*d->param_start - d->data) 594cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng + offset)); 595cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 596cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return needed - avail; 597cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 602cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 603cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng__attribute__ ((noinline)) 604cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_ds_xx (struct output_data *d, const char *reg) 605cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 606cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int prefix = *d->prefixes & SEGMENT_PREFIXES; 607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 608cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (prefix == 0) 609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes |= prefix = has_ds; 610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Make sure only one bit is set. */ 611cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if ((prefix - 1) & prefix) 612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 613cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 614cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int r = data_prefix (d); 615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 616cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert ((*d->prefixes & prefix) == 0); 617cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 618cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (r != 0) 619cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return r; 620cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 621cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 622cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 623cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "(%%%s%s)", 624cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 625cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes & idx_addr16 ? "e" : "r", 626cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else 627cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes & idx_addr16 ? "" : "e", 628cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 629cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng reg); 630cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 631cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (size_t) needed - avail; 632cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 633cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 634cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 635cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 636cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 637cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 638cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 639cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_ds_bx (struct output_data *d) 640cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 641cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return FCT_ds_xx (d, "bx"); 642cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 643cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 644cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 645cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 646cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_ds_si (struct output_data *d) 647cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 648cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return FCT_ds_xx (d, "si"); 649cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 650cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 651cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 652cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 653cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_dx (struct output_data *d) 654cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 655cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 656cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 657cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + 7 > d->bufsize) 658cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + 7 - d->bufsize; 659cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 660cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memcpy (&d->bufp[*bufcntp], "(%dx)", 5); 661cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += 5; 662cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 663cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 664cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 665cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 666cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 667cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 668cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_es_di (struct output_data *d) 669cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 670cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 671cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 672cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "%%es:(%%%sdi)", 673cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 674cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes & idx_addr16 ? "e" : "r" 675cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else 676cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes & idx_addr16 ? "" : "e" 677cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 678cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ); 679cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 680cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (size_t) needed - avail; 681cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 682cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 683cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 684cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 685cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 686cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 687cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 688cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imm (struct output_data *d) 689cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 690cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 691cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 692cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed; 693cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->prefixes & has_data16) 694cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 695cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->param_start + 2 > d->end) 696cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 697cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint16_t word = read_2ubyte_unaligned_inc (*d->param_start); 698cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word); 699cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 700cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 701cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 702cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->param_start + 4 > d->end) 703cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 704cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int32_t word = read_4sbyte_unaligned_inc (*d->param_start); 705cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 706cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->prefixes & has_rex_w) 707cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, 708cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int64_t) word); 709cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 710cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 711cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word); 712cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 713cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 714cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (size_t) needed - avail; 715cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 716cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 717cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 718cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 719cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 720cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 721cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imm$w (struct output_data *d) 722cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 723cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0) 724cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return FCT_imm (d); 725cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 726cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 727cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 728cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->param_start>= d->end) 729cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 730cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t word = *(*d->param_start)++; 731cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIxFAST8, word); 732cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 733cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (size_t) needed - avail; 734cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 735cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 736cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 737cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 738cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 739cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 740cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 741cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imm64$w (struct output_data *d) 742cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 743cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) == 0 744cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || (*d->prefixes & has_data16) != 0) 745cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return FCT_imm$w (d); 746cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 747cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 748cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 749cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed; 750cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->prefixes & has_rex_w) 751cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 752cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->param_start + 8 > d->end) 753cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 754cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint64_t word = read_8ubyte_unaligned_inc (*d->param_start); 755cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, word); 756cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 757cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 758cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 759cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->param_start + 4 > d->end) 760cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 761cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int32_t word = read_4sbyte_unaligned_inc (*d->param_start); 762cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word); 763cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 764cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 765cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (size_t) needed - avail; 766cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 767cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 768cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 769cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 770cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 771cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 772cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 773cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imms (struct output_data *d) 774cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 775cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 776cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 777cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->param_start>= d->end) 778cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 779cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int8_t byte = *(*d->param_start)++; 780cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 781cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, 782cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int64_t) byte); 783cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else 784cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, 785cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int32_t) byte); 786cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 787cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 788cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (size_t) needed - avail; 789cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 790cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 791cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 792cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 793cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 794cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 795cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imm$s (struct output_data *d) 796cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 797cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t opcode = d->data[d->opoff2 / 8]; 798cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 799cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 800cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((opcode & 2) != 0) 801cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return FCT_imms (d); 802cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 803cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((*d->prefixes & has_data16) == 0) 804cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 805cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->param_start + 4 > d->end) 806cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 807cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int32_t word = read_4sbyte_unaligned_inc (*d->param_start); 808cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 809cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, 810cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int64_t) word); 811cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else 812cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word); 813cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 814cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 815cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (size_t) needed - avail; 816cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 817cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 818cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 819cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 820cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->param_start + 2 > d->end) 821cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 822cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint16_t word = read_2ubyte_unaligned_inc (*d->param_start); 823cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word); 824cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 825cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (size_t) needed - avail; 826cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 827cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 828cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 829cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 830cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 831cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 832cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 833cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imm16 (struct output_data *d) 834cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 835cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->param_start + 2 > d->end) 836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 837cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint16_t word = read_2ubyte_unaligned_inc (*d->param_start); 838cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 839cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 840cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word); 841cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 842cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (size_t) needed - avail; 843cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 844cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 845cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 846cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 847cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 848cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 849cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imms8 (struct output_data *d) 850cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 851cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 852cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 853cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->param_start >= d->end) 854cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 855cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int_fast8_t byte = *(*d->param_start)++; 856cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed; 857cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 858cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->prefixes & has_rex_w) 859cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, 860cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int64_t) byte); 861cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 862cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 863cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, 864cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (int32_t) byte); 865cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 866cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (size_t) needed - avail; 867cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 868cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 869cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 870cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 871cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 872cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 873cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_imm8 (struct output_data *d) 874cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 875cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 876cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 877cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->param_start >= d->end) 878cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 879cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t byte = *(*d->param_start)++; 880cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, 881cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (uint32_t) byte); 882cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 883cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (size_t) needed - avail; 884cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 885cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 886cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 887cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 888cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 889cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 890cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_rel (struct output_data *d) 891cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 892cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 893cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 894cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->param_start + 4 > d->end) 895cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 896cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int32_t rel = read_4sbyte_unaligned_inc (*d->param_start); 897cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 898cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx64, 899cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (uint64_t) (d->addr + rel 900cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng + (*d->param_start - d->data))); 901cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else 902cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32, 903cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (uint32_t) (d->addr + rel 904cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng + (*d->param_start - d->data))); 905cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 906cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 907cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (size_t) needed - avail; 908cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 909cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 910cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 911cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 912cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 913cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 914cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_mmxreg (struct output_data *d) 915cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 916cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t byte = d->data[d->opoff1 / 8]; 917cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5); 918cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng byte = (byte >> (5 - d->opoff1 % 8)) & 7; 919cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 920cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 921cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte); 922cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 923cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return needed - avail; 924cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 925cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 926cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 927cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 928cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 929cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 930cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_mod$r_m (struct output_data *d) 931cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 932cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 == 0); 933cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t modrm = d->data[d->opoff1 / 8]; 934cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 0xc0) == 0xc0) 935cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 936cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int prefixes = *d->prefixes; 937cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (prefixes & has_addr16) 938cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 939cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 940cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int is_16bit = (prefixes & has_data16) != 0; 941cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 942cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 943cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *bufp = d->bufp; 944cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + 5 - is_16bit > d->bufsize) 945cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + 5 - is_16bit - d->bufsize; 946cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = '%'; 947cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 948cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *cp; 949cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 950cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((prefixes & has_rex_b) != 0 && !is_16bit) 951cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 952cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]); 953cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((prefixes & has_rex_w) == 0) 954cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp++ = 'd'; 955cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 956cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 957cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 958cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 959cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit); 960cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 961cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((prefixes & has_rex_w) != 0) 962cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[*bufcntp] = 'r'; 963cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 964cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 965cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp = cp - bufp; 966cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 967cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 968cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 969cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return general_mod$r_m (d); 970cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 971cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 972cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 973cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifndef X86_64 974cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 975cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_moda$r_m (struct output_data *d) 976cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 977cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 == 0); 978cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t modrm = d->data[d->opoff1 / 8]; 979cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 0xc0) == 0xc0) 980cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 981cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->prefixes & has_addr16) 982cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 983cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 984cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 985cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + 3 > d->bufsize) 986cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + 3 - d->bufsize; 987cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 988cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memcpy (&d->bufp[*bufcntp], "???", 3); 989cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += 3; 990cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 991cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 992cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 993cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 994cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return general_mod$r_m (d); 995cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 996cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 997cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 998cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 999cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 1000cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char rex_8bit[8][3] = 1001cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1002cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng [0] = "a", [1] = "c", [2] = "d", [3] = "b", 1003cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng [4] = "sp", [5] = "bp", [6] = "si", [7] = "di" 1004cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 1005cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 1006cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1007cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1008cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1009cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_mod$r_m$w (struct output_data *d) 1010cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1011cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 == 0); 1012cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const uint8_t *data = d->data; 1013cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t modrm = data[d->opoff1 / 8]; 1014cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 0xc0) == 0xc0) 1015cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1016cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int prefixes = *d->prefixes; 1017cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1018cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (prefixes & has_addr16) 1019cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 1020cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1021cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 1022cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *bufp = d->bufp; 1023cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + 5 > d->bufsize) 1024cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + 5 - d->bufsize; 1025cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1026cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((data[d->opoff3 / 8] & (1 << (7 - (d->opoff3 & 7)))) == 0) 1027cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1028cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = '%'; 1029cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1030cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 1031cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (prefixes & has_rex) 1032cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1033cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (prefixes & has_rex_r) 1034cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += snprintf (bufp + *bufcntp, d->bufsize - *bufcntp, 1035cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng "r%db", 8 + (modrm & 7)); 1036cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1037cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1038cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *cp = stpcpy (bufp + *bufcntp, hiregs[modrm & 7]); 1039cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp++ = 'l'; 1040cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp = cp - bufp; 1041cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1042cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1043cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1044cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 1045cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1046cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = "acdb"[modrm & 3]; 1047cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2]; 1048cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1049cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1050cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1051cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1052cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int is_16bit = (prefixes & has_data16) != 0; 1053cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1054cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = '%'; 1055cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1056cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *cp; 1057cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 1058cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((prefixes & has_rex_b) != 0 && !is_16bit) 1059cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1060cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]); 1061cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((prefixes & has_rex_w) == 0) 1062cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp++ = 'd'; 1063cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1064cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1065cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 1066cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1067cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit); 1068cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 1069cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((prefixes & has_rex_w) != 0) 1070cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[*bufcntp] = 'r'; 1071cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 1072cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1073cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp = cp - bufp; 1074cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1075cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 1076cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1077cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1078cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return general_mod$r_m (d); 1079cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1080cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1081cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1082cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1083cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_mod$8r_m (struct output_data *d) 1084cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1085cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 == 0); 1086cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t modrm = d->data[d->opoff1 / 8]; 1087cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 0xc0) == 0xc0) 1088cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1089cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 1090cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *bufp = d->bufp; 1091cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + 3 > d->bufsize) 1092cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + 3 - d->bufsize; 1093cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = '%'; 1094cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = "acdb"[modrm & 3]; 1095cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2]; 1096cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 1097cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1098cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1099cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return general_mod$r_m (d); 1100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_mod$16r_m (struct output_data *d) 1105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 == 0); 1107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t modrm = d->data[d->opoff1 / 8]; 1108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 0xc0) == 0xc0) 1109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 / 8 == d->opoff2 / 8); 1111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng //uint_fast8_t byte = data[opoff2 / 8] & 7; 1112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t byte = modrm & 7; 1113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 1115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + 3 > d->bufsize) 1116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + 3 - d->bufsize; 1117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d->bufp[(*bufcntp)++] = '%'; 1118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memcpy (&d->bufp[*bufcntp], dregs[byte] + 1, sizeof (dregs[0]) - 1); 1119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += 2; 1120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 1121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return general_mod$r_m (d); 1124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 1128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_mod$64r_m (struct output_data *d) 1130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 == 0); 1132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t modrm = d->data[d->opoff1 / 8]; 1133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((modrm & 0xc0) == 0xc0) 1134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 / 8 == d->opoff2 / 8); 1136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng //uint_fast8_t byte = data[opoff2 / 8] & 7; 1137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t byte = modrm & 7; 1138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 1140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + 4 > d->bufsize) 1141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + 4 - d->bufsize; 1142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *cp = &d->bufp[*bufcntp]; 1143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp++ = '%'; 1144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng cp = stpcpy (cp, 1145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (*d->prefixes & has_rex_b) ? hiregs[byte] : aregs[byte]); 1146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp = cp - d->bufp; 1147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 1148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return general_mod$r_m (d); 1151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else 1153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic typeof (FCT_mod$r_m) FCT_mod$64r_m __attribute__ ((alias ("FCT_mod$r_m"))); 1154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 1155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_reg (struct output_data *d) 1159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t byte = d->data[d->opoff1 / 8]; 1161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 + 3 <= 8); 1162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng byte >>= 8 - (d->opoff1 % 8 + 3); 1163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng byte &= 7; 1164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int is_16bit = (*d->prefixes & has_data16) != 0; 1165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 1166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + 5 > d->bufsize) 1167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + 5 - d->bufsize; 1168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d->bufp[(*bufcntp)++] = '%'; 1169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 1170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((*d->prefixes & has_rex_r) != 0 && !is_16bit) 1171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d", 1173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 8 + byte); 1174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((*d->prefixes & has_rex_w) == 0) 1175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d->bufp[(*bufcntp)++] = 'd'; 1176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 1179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1180cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memcpy (&d->bufp[*bufcntp], dregs[byte] + is_16bit, 3 - is_16bit); 1181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 1182cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((*d->prefixes & has_rex_w) != 0 && !is_16bit) 1183cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d->bufp[*bufcntp] = 'r'; 1184cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 1185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += 3 - is_16bit; 1186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1187cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 1188cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1189cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 1192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_oreg (struct output_data *d) 1194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Special form where register comes from opcode. The rex.B bit is used, 1196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng rex.R and rex.X are ignored. */ 1197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int save_prefixes = *d->prefixes; 1198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes = ((save_prefixes & ~has_rex_r) 1200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b))); 1201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int r = FCT_reg (d); 1203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes = save_prefixes; 1205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return r; 1207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 1209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_reg64 (struct output_data *d) 1213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t byte = d->data[d->opoff1 / 8]; 1215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 + 3 <= 8); 1216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng byte >>= 8 - (d->opoff1 % 8 + 3); 1217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng byte &= 7; 1218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((*d->prefixes & has_data16) != 0) 1219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 1220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 1221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + 5 > d->bufsize) 1222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + 5 - d->bufsize; 1223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d->bufp[(*bufcntp)++] = '%'; 1224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 1225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((*d->prefixes & has_rex_r) != 0) 1226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d", 1228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 8 + byte); 1229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((*d->prefixes & has_rex_w) == 0) 1230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d->bufp[(*bufcntp)++] = 'd'; 1231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 1234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memcpy (&d->bufp[*bufcntp], aregs[byte], 3); 1236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += 3; 1237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 1239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_reg$w (struct output_data *d) 1244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) 1246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return FCT_reg (d); 1247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t byte = d->data[d->opoff1 / 8]; 1249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 + 3 <= 8); 1250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng byte >>= 8 - (d->opoff1 % 8 + 3); 1251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng byte &= 7; 1252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 1254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + 4 > d->bufsize) 1255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + 4 - d->bufsize; 1256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d->bufp[(*bufcntp)++] = '%'; 1258cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 1260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->prefixes & has_rex) 1261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->prefixes & has_rex_r) 1263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += snprintf (d->bufp + *bufcntp, d->bufsize - *bufcntp, 1264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng "r%db", 8 + byte); 1265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char* cp = stpcpy (d->bufp + *bufcntp, rex_8bit[byte]); 1268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *cp++ = 'l'; 1269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp = cp - d->bufp; 1270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 1273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 1274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 1275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d->bufp[(*bufcntp)++] = "acdb"[byte & 3]; 1276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d->bufp[(*bufcntp)++] = "lh"[byte >> 2]; 1277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 1278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 1279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef X86_64 1283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_oreg$w (struct output_data *d) 1285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Special form where register comes from opcode. The rex.B bit is used, 1287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng rex.R and rex.X are ignored. */ 1288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int save_prefixes = *d->prefixes; 1289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes = ((save_prefixes & ~has_rex_r) 1291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b))); 1292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int r = FCT_reg$w (d); 1294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes = save_prefixes; 1296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return r; 1298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 1300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_freg (struct output_data *d) 1304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 / 8 == 1); 1306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 == 5); 1307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 1308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 1309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "%%st(%" PRIx32 ")", 1310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (uint32_t) (d->data[1] & 7)); 1311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 1312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (size_t) needed - avail; 1313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 1314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 1315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifndef X86_64 1319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_reg16 (struct output_data *d) 1321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->prefixes & has_data16) 1323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 1324cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1325cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->prefixes |= has_data16; 1326cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return FCT_reg (d); 1327cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1328cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 1329cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_sel (struct output_data *d) 1333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 == 0); 1335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 / 8 == 5); 1336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*d->param_start + 2 > d->end) 1337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 1338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *d->param_start += 2; 1339cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint16_t absval = read_2ubyte_unaligned (&d->data[5]); 1340cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1341cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 1342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 1343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, absval); 1344cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 1345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return needed - avail; 1346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 1347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 1348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_sreg2 (struct output_data *d) 1353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t byte = d->data[d->opoff1 / 8]; 1355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 + 3 <= 8); 1356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng byte >>= 8 - (d->opoff1 % 8 + 2); 1357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 1359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *bufp = d->bufp; 1360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + 3 > d->bufsize) 1361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + 3 - d->bufsize; 1362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = '%'; 1364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = "ecsd"[byte & 3]; 1365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = 's'; 1366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 1368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_sreg3 (struct output_data *d) 1373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t byte = d->data[d->opoff1 / 8]; 1375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 + 4 <= 8); 1376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng byte >>= 8 - (d->opoff1 % 8 + 3); 1377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((byte & 7) >= 6) 1379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 1380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 1382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *bufp = d->bufp; 1383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*bufcntp + 3 > d->bufsize) 1384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return *bufcntp + 3 - d->bufsize; 1385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = '%'; 1387cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = "ecsdfg"[byte & 7]; 1388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng bufp[(*bufcntp)++] = 's'; 1389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 1391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_string (struct output_data *d __attribute__ ((unused))) 1396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 1398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 1402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengFCT_xmmreg (struct output_data *d) 1403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 1404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t byte = d->data[d->opoff1 / 8]; 1405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5); 1406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng byte = (byte >> (5 - d->opoff1 % 8)) & 7; 1407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 1408cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t *bufcntp = d->bufcntp; 1409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = d->bufsize - *bufcntp; 1410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, byte); 1411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((size_t) needed > avail) 1412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return needed - avail; 1413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *bufcntp += needed; 1414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 1415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 1416