125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Disassembler for x86. 225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Copyright (C) 2007, 2008, 2009, 2011 Red Hat, Inc. 303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is part of elfutils. 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Written by Ulrich Drepper <drepper@redhat.com>, 2007. 525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is free software; you can redistribute it and/or modify 703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes it under the terms of either 825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU Lesser General Public License as published by the Free 1003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 3 of the License, or (at 1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or 1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU General Public License as published by the Free 1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 2 of the License, or (at 1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or both in parallel, as here. 2003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 2103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elfutils is distributed in the hope that it will be useful, but 2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng General Public License for more details. 2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes You should have received copies of the GNU General Public License and 2703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes the GNU Lesser General Public License along with this program. If 2803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes not, see <http://www.gnu.org/licenses/>. */ 2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H 3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h> 3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h> 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <config.h> 3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <ctype.h> 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <endian.h> 3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <errno.h> 3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <gelf.h> 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stddef.h> 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdint.h> 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h> 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h> 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/param.h> 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libebl/libeblP.h" 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MACHINE_ENCODING __LITTLE_ENDIAN 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "memory-access.h" 5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef MNEFILE 5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define MNEFILE "i386.mnemonics" 5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNESTRFIELD(line) MNESTRFIELD1 (line) 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNESTRFIELD1(line) str##line 5825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const union mnestr_t 5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct 6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE(name) char MNESTRFIELD (__LINE__)[sizeof (#name)]; 6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include MNEFILE 6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef MNE 6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng char str[0]; 6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} mnestr = 6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE(name) #name, 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include MNEFILE 7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef MNE 7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* The index can be stored in the instrtab. */ 7725b3c049e70834cf33790a28643ab058b507b35cBen Chengenum 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE(name) MNE_##name, 8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include MNEFILE 8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef MNE 8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng MNE_INVALID 8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const unsigned short int mneidx[] = 8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE(name) \ 8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng [MNE_##name] = offsetof (union mnestr_t, MNESTRFIELD (__LINE__)), 8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include MNEFILE 9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef MNE 9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9425b3c049e70834cf33790a28643ab058b507b35cBen Chengenum 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_rex_b = 0, 9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_rex_x, 9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_rex_r, 9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_rex_w, 10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_rex, 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_cs, 10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_ds, 10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_es, 10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_fs, 10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_gs, 10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_ss, 10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_data16, 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_addr16, 10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_rep, 11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_repne, 11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng idx_lock 11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11425b3c049e70834cf33790a28643ab058b507b35cBen Chengenum 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define prefbit(pref) has_##pref = 1 << idx_##pref 11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (rex_b), 11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (rex_x), 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (rex_r), 12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (rex_w), 12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (rex), 12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (cs), 12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (ds), 12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (es), 12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (fs), 12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (gs), 12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (ss), 12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (data16), 12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (addr16), 13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (rep), 13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (repne), 13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefbit (lock) 13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef prefbit 13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define SEGMENT_PREFIXES \ 13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng (has_cs | has_ds | has_es | has_fs | has_gs | has_ss) 13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define prefix_cs 0x2e 13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define prefix_ds 0x3e 14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define prefix_es 0x26 14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define prefix_fs 0x64 14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define prefix_gs 0x65 14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define prefix_ss 0x36 14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define prefix_data16 0x66 14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define prefix_addr16 0x67 14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define prefix_rep 0xf3 14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define prefix_repne 0xf2 14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define prefix_lock 0xf0 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const uint8_t known_prefixes[] = 15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define newpref(pref) [idx_##pref] = prefix_##pref 15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (cs), 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (ds), 15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (es), 15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (fs), 15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (gs), 15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (ss), 16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (data16), 16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (addr16), 16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (rep), 16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (repne), 16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (lock) 16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef newpref 16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define nknown_prefixes (sizeof (known_prefixes) / sizeof (known_prefixes[0])) 16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if 0 17125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *prefix_str[] = 17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define newpref(pref) [idx_##pref] = #pref 17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (cs), 17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (ds), 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (es), 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (fs), 17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (gs), 17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (ss), 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (data16), 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (addr16), 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (rep), 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (repne), 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng newpref (lock) 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef newpref 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char amd3dnowstr[] = 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PAVGUSB 1 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pavgusb\0" 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PFADD (MNE_3DNOW_PAVGUSB + 8) 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pfadd\0" 19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PFSUB (MNE_3DNOW_PFADD + 6) 19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pfsub\0" 19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PFSUBR (MNE_3DNOW_PFSUB + 6) 19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pfsubr\0" 19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PFACC (MNE_3DNOW_PFSUBR + 7) 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pfacc\0" 20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PFCMPGE (MNE_3DNOW_PFACC + 6) 20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pfcmpge\0" 20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PFCMPGT (MNE_3DNOW_PFCMPGE + 8) 20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pfcmpgt\0" 20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PFCMPEQ (MNE_3DNOW_PFCMPGT + 8) 20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pfcmpeq\0" 20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PFMIN (MNE_3DNOW_PFCMPEQ + 8) 20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pfmin\0" 20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PFMAX (MNE_3DNOW_PFMIN + 6) 21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pfmax\0" 21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PI2FD (MNE_3DNOW_PFMAX + 6) 21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pi2fd\0" 21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PF2ID (MNE_3DNOW_PI2FD + 6) 21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pf2id\0" 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PFRCP (MNE_3DNOW_PF2ID + 6) 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pfrcp\0" 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PFRSQRT (MNE_3DNOW_PFRCP + 6) 21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pfrsqrt\0" 21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PFMUL (MNE_3DNOW_PFRSQRT + 8) 22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pfmul\0" 22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PFRCPIT1 (MNE_3DNOW_PFMUL + 6) 22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pfrcpit1\0" 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PFRSQIT1 (MNE_3DNOW_PFRCPIT1 + 9) 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pfrsqit1\0" 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PFRCPIT2 (MNE_3DNOW_PFRSQIT1 + 9) 22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pfrcpit2\0" 22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MNE_3DNOW_PMULHRW (MNE_3DNOW_PFRCPIT2 + 9) 22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng "pmulhrw"; 22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define AMD3DNOW_LOW_IDX 0x0d 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define AMD3DNOW_HIGH_IDX (sizeof (amd3dnow) + AMD3DNOW_LOW_IDX - 1) 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define AMD3DNOW_IDX(val) ((val) - AMD3DNOW_LOW_IDX) 23325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const unsigned char amd3dnow[] = 23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0xbf)] = MNE_3DNOW_PAVGUSB, 23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0x9e)] = MNE_3DNOW_PFADD, 23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0x9a)] = MNE_3DNOW_PFSUB, 23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0xaa)] = MNE_3DNOW_PFSUBR, 23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0xae)] = MNE_3DNOW_PFACC, 24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0x90)] = MNE_3DNOW_PFCMPGE, 24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0xa0)] = MNE_3DNOW_PFCMPGT, 24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0xb0)] = MNE_3DNOW_PFCMPEQ, 24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0x94)] = MNE_3DNOW_PFMIN, 24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0xa4)] = MNE_3DNOW_PFMAX, 24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0x0d)] = MNE_3DNOW_PI2FD, 24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0x1d)] = MNE_3DNOW_PF2ID, 24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0x96)] = MNE_3DNOW_PFRCP, 24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0x97)] = MNE_3DNOW_PFRSQRT, 24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0xb4)] = MNE_3DNOW_PFMUL, 25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0xa6)] = MNE_3DNOW_PFRCPIT1, 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0xa7)] = MNE_3DNOW_PFRSQIT1, 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0xb6)] = MNE_3DNOW_PFRCPIT2, 25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng [AMD3DNOW_IDX (0xb7)] = MNE_3DNOW_PMULHRW 25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25725b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct output_data 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr addr; 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int *prefixes; 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t opoff1; 26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t opoff2; 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t opoff3; 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *bufp; 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t *bufcntp; 26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t bufsize; 26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng const uint8_t *data; 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng const uint8_t **param_start; 26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng const uint8_t *end; 27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *labelbuf; 27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t labelbufsize; 27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng enum 27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng addr_none = 0, 27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng addr_abs_symbolic, 27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng addr_abs_always, 27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng addr_rel_symbolic, 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng addr_rel_always 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } symaddr_use; 28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr symaddr; 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}; 28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef DISFILE 28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define DISFILE "i386_dis.h" 28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include DISFILE 28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define ADD_CHAR(ch) \ 29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng do { \ 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (bufcnt == bufsize)) \ 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto enomem; \ 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng buf[bufcnt++] = (ch); \ 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } while (0) 29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define ADD_STRING(str) \ 29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng do { \ 29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *_str0 = (str); \ 30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t _len0 = strlen (_str0); \ 30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_NSTRING (_str0, _len0); \ 30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } while (0) 30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define ADD_NSTRING(str, len) \ 30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng do { \ 30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *_str = (str); \ 30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t _len = (len); \ 30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (bufcnt + _len > bufsize)) \ 30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto enomem; \ 31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (buf + bufcnt, _str, _len); \ 31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufcnt += _len; \ 31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } while (0) 31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31525b3c049e70834cf33790a28643ab058b507b35cBen Chengint 31625b3c049e70834cf33790a28643ab058b507b35cBen Chengi386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, 31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *fmt, DisasmOutputCB_t outcb, DisasmGetSymCB_t symcb, 31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *outcbarg, void *symcbarg) 31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *save_fmt = fmt; 32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define BUFSIZE 512 32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng char initbuf[BUFSIZE]; 32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng int prefixes; 32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t bufcnt; 32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t bufsize = BUFSIZE; 32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *buf = initbuf; 32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng const uint8_t *param_start; 32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct output_data output_data = 33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng .prefixes = &prefixes, 33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng .bufp = buf, 33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng .bufsize = bufsize, 33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng .bufcntp = &bufcnt, 33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng .param_start = ¶m_start, 33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng .end = end 33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int retval = 0; 34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (1) 34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefixes = 0; 34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng const uint8_t *data = *startp; 34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng const uint8_t *begin = data; 34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Recognize all prefixes. */ 34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng int last_prefix_bit = 0; 35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (data < end) 35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int i; 35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (i = idx_cs; i < nknown_prefixes; ++i) 35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (known_prefixes[i] == *data) 35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (i == nknown_prefixes) 35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefixes |= last_prefix_bit = 1 << i; 36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++data; 36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data < end && (*data & 0xf0) == 0x40) 36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefixes |= ((*data++) & 0xf) | has_rex; 36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufcnt = 0; 37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t cnt = 0; 37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng const uint8_t *curr = match_data; 37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng const uint8_t *const match_end = match_data + sizeof (match_data); 37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (data <= end); 37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == end) 37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes != 0) 37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto print_prefix; 38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng retval = -1; 38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto do_ret; 38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng next_match: 38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (curr < match_end) 38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t len = *curr++; 38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t clen = len >> 4; 39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng len &= 0xf; 39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const uint8_t *next_curr = curr + clen + (len - clen) * 2; 39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (len > 0); 39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (curr + clen + 2 * (len - clen) <= match_end); 39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng const uint8_t *codep = data; 39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng int correct_prefix = 0; 39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int opoff = 0; 39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data > begin && codep[-1] == *curr && clen > 0) 40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We match a prefix byte. This is exactly one byte and 40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng is matched exactly, without a mask. */ 40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng --len; 40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng --clen; 40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng opoff = 8; 40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++curr; 40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (last_prefix_bit != 0); 41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng correct_prefix = last_prefix_bit; 41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = len; 41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (clen > 0) 41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*codep++ != *curr++) 41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto not; 41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng --avail; 42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng --clen; 42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (codep == end && avail > 0) 42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto do_ret; 42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (avail > 0) 42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t masked = *codep++ & *curr++; 42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (masked != *curr++) 42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng not: 43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng curr = next_curr; 43225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++cnt; 43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufcnt = 0; 43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto next_match; 43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng --avail; 43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (codep == end && avail > 0) 43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto do_ret; 44025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (len > end - data) 44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* There is not enough data for the entire instruction. The 44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng caller can figure this out by looking at the pointer into 44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng the input data. */ 44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto do_ret; 44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (correct_prefix == 0 44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng || (prefixes & correct_prefix) != 0); 45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefixes ^= correct_prefix; 45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (0) 45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Resize the buffer. */ 45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *oldbuf; 45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng enomem: 45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng oldbuf = buf; 45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (buf == initbuf) 45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng buf = malloc (2 * bufsize); 46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng buf = realloc (buf, 2 * bufsize); 46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (buf == NULL) 46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng buf = oldbuf; 46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng retval = ENOMEM; 46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto do_ret; 46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufsize *= 2; 46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.bufp = buf; 47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.bufsize = bufsize; 47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufcnt = 0; 47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == end) 47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (prefixes != 0); 47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto print_prefix; 47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 47925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 48025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* gcc is not clever enough to see the following variables 48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng are not used uninitialized. */ 48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng asm ("" 48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng : "=mr" (opoff), "=mr" (correct_prefix), "=mr" (codep), 48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng "=mr" (next_curr), "=mr" (len)); 48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t prefix_size = 0; 48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng // XXXonly print as prefix if valid? 49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((prefixes & has_lock) != 0) 49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("lock "); 49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefix_size += 5; 49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (instrtab[cnt].rep) 49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((prefixes & has_rep) != 0) 49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("rep "); 50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefix_size += 4; 50225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (instrtab[cnt].repe 50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (prefixes & (has_rep | has_repne)) != 0) 50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((prefixes & has_repne) != 0) 50825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 50925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("repne "); 51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefix_size += 6; 51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((prefixes & has_rep) != 0) 51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("repe "); 51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefix_size += 5; 51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((prefixes & (has_rep | has_repne)) != 0) 51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t byte; 52125b3c049e70834cf33790a28643ab058b507b35cBen Cheng print_prefix: 52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufcnt = 0; 52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng byte = *begin; 52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is a prefix byte. Print it. */ 52525b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (byte) 52625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 52725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case prefix_rep: 52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("rep"); 52925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 53025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case prefix_repne: 53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("repne"); 53225b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 53325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case prefix_cs: 53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("cs"); 53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case prefix_ds: 53725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("ds"); 53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case prefix_es: 54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("es"); 54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case prefix_fs: 54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("fs"); 54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case prefix_gs: 54625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("gs"); 54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 54825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case prefix_ss: 54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("ss"); 55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case prefix_data16: 55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("data16"); 55325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 55425b3c049e70834cf33790a28643ab058b507b35cBen Cheng case prefix_addr16: 55525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("addr16"); 55625b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 55725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case prefix_lock: 55825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("lock"); 55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 0x40 ... 0x4f: 56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("rex"); 56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (byte != 0x40) 56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR ('.'); 56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (byte & 0x8) 56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR ('w'); 56825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (byte & 0x4) 56925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR ('r'); 57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (byte & 0x3) 57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR ('x'); 57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (byte & 0x1) 57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR ('b'); 57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 57625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Cannot happen. */ 57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng puts ("unknown prefix"); 58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng abort (); 58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 58225b3c049e70834cf33790a28643ab058b507b35cBen Cheng data = begin + 1; 58325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++addr; 58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto out; 58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 58825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We have a match. First determine how many bytes are 58925b3c049e70834cf33790a28643ab058b507b35cBen Cheng needed for the adressing mode. */ 59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng param_start = codep; 59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (instrtab[cnt].modrm) 59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t modrm = codep[-1]; 59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef X86_64 59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (likely ((prefixes & has_addr16) != 0)) 59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Account for displacement. */ 59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80) 60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng param_start += 2; 60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((modrm & 0xc0) == 0x40) 60225b3c049e70834cf33790a28643ab058b507b35cBen Cheng param_start += 1; 60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 60425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Account for SIB. */ 60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 0x4) 60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng param_start += 1; 61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Account for displacement. */ 61225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80 61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng || ((modrm & 0xc7) == 0x4 && (codep[0] & 0x7) == 0x5)) 61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng param_start += 4; 61525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if ((modrm & 0xc0) == 0x40) 61625b3c049e70834cf33790a28643ab058b507b35cBen Cheng param_start += 1; 61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (param_start > end)) 62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto not; 62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 62225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.addr = addr + (data - begin); 62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.data = data; 62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 62625b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned long string_end_idx = 0; 62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng fmt = save_fmt; 62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *deferred_start = NULL; 62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t deferred_len = 0; 63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng // XXX Can we get this from color.c? 63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng static const char color_off[] = "\e[0m"; 63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (*fmt != '\0') 63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*fmt != '%') 63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng char ch = *fmt++; 63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ch == '\\') 63825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 63925b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch ((ch = *fmt++)) 64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case '0' ... '7': 64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng int val = ch - '0'; 64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ch = *fmt; 64525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ch >= '0' && ch <= '7') 64625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng val *= 8; 64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng val += ch - '0'; 64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ch = *++fmt; 65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ch >= '0' && ch <= '7' && val < 32) 65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 65225b3c049e70834cf33790a28643ab058b507b35cBen Cheng val *= 8; 65325b3c049e70834cf33790a28643ab058b507b35cBen Cheng val += ch - '0'; 65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++fmt; 65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ch = val; 65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 'n': 66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ch = '\n'; 66325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 66425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 't': 66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ch = '\t'; 66725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 66825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66925b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng retval = EINVAL; 67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto do_ret; 67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (ch == '\e' && *fmt == '[') 67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 67625b3c049e70834cf33790a28643ab058b507b35cBen Cheng deferred_start = fmt - 1; 67725b3c049e70834cf33790a28643ab058b507b35cBen Cheng do 67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++fmt; 67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (*fmt != 'm' && *fmt != '\0'); 68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*fmt == 'm') 68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 68325b3c049e70834cf33790a28643ab058b507b35cBen Cheng deferred_len = ++fmt - deferred_start; 68425b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 68525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 68625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68725b3c049e70834cf33790a28643ab058b507b35cBen Cheng fmt = deferred_start + 1; 68825b3c049e70834cf33790a28643ab058b507b35cBen Cheng deferred_start = NULL; 68925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 69025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR (ch); 69125b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 69225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 69325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++fmt; 69425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 69525b3c049e70834cf33790a28643ab058b507b35cBen Cheng int width = 0; 69625b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (isdigit (*fmt)) 69725b3c049e70834cf33790a28643ab058b507b35cBen Cheng width = width * 10 + (*fmt++ - '0'); 69825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 69925b3c049e70834cf33790a28643ab058b507b35cBen Cheng int prec = 0; 70025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*fmt == '.') 70125b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (isdigit (*++fmt)) 70225b3c049e70834cf33790a28643ab058b507b35cBen Cheng prec = prec * 10 + (*fmt - '0'); 70325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 70425b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t start_idx = bufcnt; 70525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t non_printing = 0; 70625b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (*fmt++) 70725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 70825b3c049e70834cf33790a28643ab058b507b35cBen Cheng char mnebuf[16]; 70925b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *str; 71025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 71125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 'm': 71225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Mnemonic. */ 71325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 71425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (instrtab[cnt].mnemonic == MNE_INVALID)) 71525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 71625b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (*data) 71725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 71825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 71925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 0x90: 72025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes & has_rex_b) 72125b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto not; 72225b3c049e70834cf33790a28643ab058b507b35cBen Cheng str = "nop"; 72325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 72425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 72525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 72625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 0x98: 72725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 72825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes == (has_rex_w | has_rex)) 72925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 73025b3c049e70834cf33790a28643ab058b507b35cBen Cheng str = "cltq"; 73125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 73225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 73325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 73425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes & ~has_data16) 73525b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto print_prefix; 73625b3c049e70834cf33790a28643ab058b507b35cBen Cheng str = prefixes & has_data16 ? "cbtw" : "cwtl"; 73725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 73825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 73925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 0x99: 74025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 74125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes == (has_rex_w | has_rex)) 74225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 74325b3c049e70834cf33790a28643ab058b507b35cBen Cheng str = "cqto"; 74425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 74525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 74625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 74725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes & ~has_data16) 74825b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto print_prefix; 74925b3c049e70834cf33790a28643ab058b507b35cBen Cheng str = prefixes & has_data16 ? "cwtd" : "cltd"; 75025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 75125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 75225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 0xe3: 75325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes & ~has_addr16) 75425b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto print_prefix; 75525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 75625b3c049e70834cf33790a28643ab058b507b35cBen Cheng str = prefixes & has_addr16 ? "jecxz" : "jrcxz"; 75725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 75825b3c049e70834cf33790a28643ab058b507b35cBen Cheng str = prefixes & has_addr16 ? "jcxz" : "jecxz"; 75925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 76025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 76125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 76225b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 0x0f: 76325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data[1] == 0x0f) 76425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 76525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* AMD 3DNOW. We need one more byte. */ 76625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (param_start >= end) 76725b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto not; 76825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*param_start < AMD3DNOW_LOW_IDX 76925b3c049e70834cf33790a28643ab058b507b35cBen Cheng || *param_start > AMD3DNOW_HIGH_IDX) 77025b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto not; 77125b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned int idx 77225b3c049e70834cf33790a28643ab058b507b35cBen Cheng = amd3dnow[AMD3DNOW_IDX (*param_start)]; 77325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (idx == 0) 77425b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto not; 77525b3c049e70834cf33790a28643ab058b507b35cBen Cheng str = amd3dnowstr + idx - 1; 77625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Eat the immediate byte indicating the 77725b3c049e70834cf33790a28643ab058b507b35cBen Cheng operation. */ 77825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++param_start; 77925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 78025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 78125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 78225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data[1] == 0xc7) 78325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 78425b3c049e70834cf33790a28643ab058b507b35cBen Cheng str = ((prefixes & has_rex_w) 78525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? "cmpxchg16b" : "cmpxchg8b"); 78625b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 78725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 78825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 78925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data[1] == 0xc2) 79025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 79125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (param_start >= end) 79225b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto not; 79325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*param_start > 7) 79425b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto not; 79525b3c049e70834cf33790a28643ab058b507b35cBen Cheng static const char cmpops[][9] = 79625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 79725b3c049e70834cf33790a28643ab058b507b35cBen Cheng [0] = "cmpeq", 79825b3c049e70834cf33790a28643ab058b507b35cBen Cheng [1] = "cmplt", 79925b3c049e70834cf33790a28643ab058b507b35cBen Cheng [2] = "cmple", 80025b3c049e70834cf33790a28643ab058b507b35cBen Cheng [3] = "cmpunord", 80125b3c049e70834cf33790a28643ab058b507b35cBen Cheng [4] = "cmpneq", 80225b3c049e70834cf33790a28643ab058b507b35cBen Cheng [5] = "cmpnlt", 80325b3c049e70834cf33790a28643ab058b507b35cBen Cheng [6] = "cmpnle", 80425b3c049e70834cf33790a28643ab058b507b35cBen Cheng [7] = "cmpord" 80525b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 80625b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *cp = stpcpy (mnebuf, cmpops[*param_start]); 80725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (correct_prefix & (has_rep | has_repne)) 80825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = 's'; 80925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 81025b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = 'p'; 81125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (correct_prefix & (has_data16 | has_repne)) 81225b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = 'd'; 81325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 81425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp++ = 's'; 81525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *cp = '\0'; 81625b3c049e70834cf33790a28643ab058b507b35cBen Cheng str = mnebuf; 81725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Eat the immediate byte indicating the 81825b3c049e70834cf33790a28643ab058b507b35cBen Cheng operation. */ 81925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++param_start; 82025b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 82125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 82225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 82325b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 82425b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (! "INVALID not handled"); 82525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 82625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 82725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 82825b3c049e70834cf33790a28643ab058b507b35cBen Cheng str = mnestr.str + mneidx[instrtab[cnt].mnemonic]; 82925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 83025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (deferred_start != NULL) 83125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 83225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_NSTRING (deferred_start, deferred_len); 83325b3c049e70834cf33790a28643ab058b507b35cBen Cheng non_printing += deferred_len; 83425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 83525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 83625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING (str); 83725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 83825b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (instrtab[cnt].suffix) 83925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 84025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case suffix_none: 84125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 84225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 84325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case suffix_w: 84425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((codep[-1] & 0xc0) != 0xc0) 84525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 84625b3c049e70834cf33790a28643ab058b507b35cBen Cheng char ch; 84725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 84825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data[0] & 1) 84925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 85025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes & has_data16) 85125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ch = 'w'; 85225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 85325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (prefixes & has_rex_w) 85425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ch = 'q'; 85525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 85625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 85725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ch = 'l'; 85825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 85925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 86025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ch = 'b'; 86125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 86225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR (ch); 86325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 86425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 86525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 86625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case suffix_w0: 86725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((codep[-1] & 0xc0) != 0xc0) 86825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR ('l'); 86925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 87025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 87125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case suffix_w1: 87225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((data[0] & 0x4) == 0) 87325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR ('l'); 87425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 87525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 87625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case suffix_W: 87725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes & has_data16) 87825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 87925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR ('w'); 88025b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefixes &= ~has_data16; 88125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 88225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 88325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 88425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR ('q'); 88525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 88625b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 88725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 88825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case suffix_W1: 88925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes & has_data16) 89025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 89125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR ('w'); 89225b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefixes &= ~has_data16; 89325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 89425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef X86_64 89525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (prefixes & has_rex_w) 89625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR ('q'); 89725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 89825b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 89925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 90025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case suffix_tttn:; 90125b3c049e70834cf33790a28643ab058b507b35cBen Cheng static const char tttn[16][3] = 90225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 90325b3c049e70834cf33790a28643ab058b507b35cBen Cheng "o", "no", "b", "ae", "e", "ne", "be", "a", 90425b3c049e70834cf33790a28643ab058b507b35cBen Cheng "s", "ns", "p", "np", "l", "ge", "le", "g" 90525b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 90625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING (tttn[codep[-1 - instrtab[cnt].modrm] & 0x0f]); 90725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 90825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 90925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case suffix_D: 91025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((codep[-1] & 0xc0) != 0xc0) 91125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR ((data[0] & 0x04) == 0 ? 's' : 'l'); 91225b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 91325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 91425b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 91525b3c049e70834cf33790a28643ab058b507b35cBen Cheng printf("unknown suffix %d\n", instrtab[cnt].suffix); 91625b3c049e70834cf33790a28643ab058b507b35cBen Cheng abort (); 91725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 91825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 91925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (deferred_start != NULL) 92025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 92125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING (color_off); 92225b3c049e70834cf33790a28643ab058b507b35cBen Cheng non_printing += strlen (color_off); 92325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 92425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 92525b3c049e70834cf33790a28643ab058b507b35cBen Cheng string_end_idx = bufcnt; 92625b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 92725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 92825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 'o': 92925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prec == 1 && instrtab[cnt].fct1 != 0) 93025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 93125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* First parameter. */ 93225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (deferred_start != NULL) 93325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 93425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_NSTRING (deferred_start, deferred_len); 93525b3c049e70834cf33790a28643ab058b507b35cBen Cheng non_printing += deferred_len; 93625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 93725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 93825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (instrtab[cnt].str1 != 0) 93925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING (op1_str 94025b3c049e70834cf33790a28643ab058b507b35cBen Cheng + op1_str_idx[instrtab[cnt].str1 - 1]); 94125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 94225b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.opoff1 = (instrtab[cnt].off1_1 94325b3c049e70834cf33790a28643ab058b507b35cBen Cheng + OFF1_1_BIAS - opoff); 94425b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.opoff2 = (instrtab[cnt].off1_2 94525b3c049e70834cf33790a28643ab058b507b35cBen Cheng + OFF1_2_BIAS - opoff); 94625b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.opoff3 = (instrtab[cnt].off1_3 94725b3c049e70834cf33790a28643ab058b507b35cBen Cheng + OFF1_3_BIAS - opoff); 94825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int r = op1_fct[instrtab[cnt].fct1] (&output_data); 94925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (r < 0) 95025b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto not; 95125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (r > 0) 95225b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto enomem; 95325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 95425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (deferred_start != NULL) 95525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 95625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING (color_off); 95725b3c049e70834cf33790a28643ab058b507b35cBen Cheng non_printing += strlen (color_off); 95825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 95925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 96025b3c049e70834cf33790a28643ab058b507b35cBen Cheng string_end_idx = bufcnt; 96125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 96225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (prec == 2 && instrtab[cnt].fct2 != 0) 96325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 96425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Second parameter. */ 96525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (deferred_start != NULL) 96625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 96725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_NSTRING (deferred_start, deferred_len); 96825b3c049e70834cf33790a28643ab058b507b35cBen Cheng non_printing += deferred_len; 96925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 97025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 97125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (instrtab[cnt].str2 != 0) 97225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING (op2_str 97325b3c049e70834cf33790a28643ab058b507b35cBen Cheng + op2_str_idx[instrtab[cnt].str2 - 1]); 97425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 97525b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.opoff1 = (instrtab[cnt].off2_1 97625b3c049e70834cf33790a28643ab058b507b35cBen Cheng + OFF2_1_BIAS - opoff); 97725b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.opoff2 = (instrtab[cnt].off2_2 97825b3c049e70834cf33790a28643ab058b507b35cBen Cheng + OFF2_2_BIAS - opoff); 97925b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.opoff3 = (instrtab[cnt].off2_3 98025b3c049e70834cf33790a28643ab058b507b35cBen Cheng + OFF2_3_BIAS - opoff); 98125b3c049e70834cf33790a28643ab058b507b35cBen Cheng int r = op2_fct[instrtab[cnt].fct2] (&output_data); 98225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (r < 0) 98325b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto not; 98425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (r > 0) 98525b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto enomem; 98625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 98725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (deferred_start != NULL) 98825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 98925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING (color_off); 99025b3c049e70834cf33790a28643ab058b507b35cBen Cheng non_printing += strlen (color_off); 99125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 99225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 99325b3c049e70834cf33790a28643ab058b507b35cBen Cheng string_end_idx = bufcnt; 99425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 99525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (prec == 3 && instrtab[cnt].fct3 != 0) 99625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 99725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Third parameter. */ 99825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (deferred_start != NULL) 99925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 100025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_NSTRING (deferred_start, deferred_len); 100125b3c049e70834cf33790a28643ab058b507b35cBen Cheng non_printing += deferred_len; 100225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 100325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 100425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (instrtab[cnt].str3 != 0) 100525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING (op3_str 100625b3c049e70834cf33790a28643ab058b507b35cBen Cheng + op3_str_idx[instrtab[cnt].str3 - 1]); 100725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 100825b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.opoff1 = (instrtab[cnt].off3_1 100925b3c049e70834cf33790a28643ab058b507b35cBen Cheng + OFF3_1_BIAS - opoff); 101025b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.opoff2 = (instrtab[cnt].off3_2 101125b3c049e70834cf33790a28643ab058b507b35cBen Cheng + OFF3_2_BIAS - opoff); 101225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef OFF3_3_BITS 101325b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.opoff3 = (instrtab[cnt].off3_3 101425b3c049e70834cf33790a28643ab058b507b35cBen Cheng + OFF3_3_BIAS - opoff); 101525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#else 101625b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.opoff3 = 0; 101725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 101825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int r = op3_fct[instrtab[cnt].fct3] (&output_data); 101925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (r < 0) 102025b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto not; 102125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (r > 0) 102225b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto enomem; 102325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 102425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (deferred_start != NULL) 102525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 102625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING (color_off); 102725b3c049e70834cf33790a28643ab058b507b35cBen Cheng non_printing += strlen (color_off); 102825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 102925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 103025b3c049e70834cf33790a28643ab058b507b35cBen Cheng string_end_idx = bufcnt; 103125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 103225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 103325b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufcnt = string_end_idx; 103425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 103525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 103625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 'e': 103725b3c049e70834cf33790a28643ab058b507b35cBen Cheng string_end_idx = bufcnt; 103825b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 103925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 104025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 'a': 104125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Pad to requested column. */ 104225b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (bufcnt - non_printing < (size_t) width) 104325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR (' '); 104425b3c049e70834cf33790a28643ab058b507b35cBen Cheng width = 0; 104525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 104625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 104725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case 'l': 104825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (deferred_start != NULL) 104925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 105025b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_NSTRING (deferred_start, deferred_len); 105125b3c049e70834cf33790a28643ab058b507b35cBen Cheng non_printing += deferred_len; 105225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 105325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 105425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (output_data.labelbuf != NULL 105525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && output_data.labelbuf[0] != '\0') 105625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 105725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING (output_data.labelbuf); 105825b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.labelbuf[0] = '\0'; 105925b3c049e70834cf33790a28643ab058b507b35cBen Cheng string_end_idx = bufcnt; 106025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 106125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (output_data.symaddr_use != addr_none) 106225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 106325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr symaddr = output_data.symaddr; 106425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (output_data.symaddr_use >= addr_rel_symbolic) 106525b3c049e70834cf33790a28643ab058b507b35cBen Cheng symaddr += addr + param_start - begin; 106625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 106725b3c049e70834cf33790a28643ab058b507b35cBen Cheng // XXX Lookup symbol based on symaddr 106825b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *symstr = NULL; 106925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symcb != NULL 107025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && symcb (0 /* XXX */, 0 /* XXX */, symaddr, 107125b3c049e70834cf33790a28643ab058b507b35cBen Cheng &output_data.labelbuf, 107225b3c049e70834cf33790a28643ab058b507b35cBen Cheng &output_data.labelbufsize, symcbarg) == 0) 107325b3c049e70834cf33790a28643ab058b507b35cBen Cheng symstr = output_data.labelbuf; 107425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 107525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t bufavail = bufsize - bufcnt; 107625b3c049e70834cf33790a28643ab058b507b35cBen Cheng int r = 0; 107725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (symstr != NULL) 107825b3c049e70834cf33790a28643ab058b507b35cBen Cheng r = snprintf (&buf[bufcnt], bufavail, "# <%s>", 107925b3c049e70834cf33790a28643ab058b507b35cBen Cheng symstr); 108025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (output_data.symaddr_use == addr_abs_always 108125b3c049e70834cf33790a28643ab058b507b35cBen Cheng || output_data.symaddr_use == addr_rel_always) 108225b3c049e70834cf33790a28643ab058b507b35cBen Cheng r = snprintf (&buf[bufcnt], bufavail, "# %#" PRIx64, 108325b3c049e70834cf33790a28643ab058b507b35cBen Cheng (uint64_t) symaddr); 108425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 108525b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (r >= 0); 108625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) r >= bufavail) 108725b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto enomem; 108825b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufcnt += r; 108925b3c049e70834cf33790a28643ab058b507b35cBen Cheng string_end_idx = bufcnt; 109025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 109125b3c049e70834cf33790a28643ab058b507b35cBen Cheng output_data.symaddr_use = addr_none; 109225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 109325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (deferred_start != NULL) 109425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 109525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING (color_off); 109625b3c049e70834cf33790a28643ab058b507b35cBen Cheng non_printing += strlen (color_off); 109725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 109825b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 109925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 110025b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 110125b3c049e70834cf33790a28643ab058b507b35cBen Cheng abort (); 110225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 110325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 110425b3c049e70834cf33790a28643ab058b507b35cBen Cheng deferred_start = NULL; 110525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 110625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Pad according to the specified width. */ 110725b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (bufcnt + prefix_size - non_printing < start_idx + width) 110825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_CHAR (' '); 110925b3c049e70834cf33790a28643ab058b507b35cBen Cheng prefix_size = 0; 111025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 111125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 111225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((prefixes & SEGMENT_PREFIXES) != 0) 111325b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto print_prefix; 111425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 111525b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (string_end_idx != ~0ul); 111625b3c049e70834cf33790a28643ab058b507b35cBen Cheng bufcnt = string_end_idx; 111725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 111825b3c049e70834cf33790a28643ab058b507b35cBen Cheng addr += param_start - begin; 111925b3c049e70834cf33790a28643ab058b507b35cBen Cheng data = param_start; 112025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 112125b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto out; 112225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 112325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 112425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Invalid (or at least unhandled) opcode. */ 112525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (prefixes != 0) 112625b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto print_prefix; 112725b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (*startp == data); 112825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++data; 112925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ADD_STRING ("(bad)"); 113025b3c049e70834cf33790a28643ab058b507b35cBen Cheng addr += data - begin; 113125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 113225b3c049e70834cf33790a28643ab058b507b35cBen Cheng out: 113325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (bufcnt == bufsize) 113425b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto enomem; 113525b3c049e70834cf33790a28643ab058b507b35cBen Cheng buf[bufcnt] = '\0'; 113625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 113725b3c049e70834cf33790a28643ab058b507b35cBen Cheng *startp = data; 113825b3c049e70834cf33790a28643ab058b507b35cBen Cheng retval = outcb (buf, bufcnt, outcbarg); 113925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (retval != 0) 114025b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto do_ret; 114125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 114225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 114325b3c049e70834cf33790a28643ab058b507b35cBen Cheng do_ret: 114425b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (output_data.labelbuf); 114525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (buf != initbuf) 114625b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (buf); 114725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 114825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return retval; 114925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 1150