1da0c48c4Sopenharmony_ci/* Disassembler for x86. 2da0c48c4Sopenharmony_ci Copyright (C) 2007, 2008, 2009, 2011 Red Hat, Inc. 3da0c48c4Sopenharmony_ci This file is part of elfutils. 4da0c48c4Sopenharmony_ci Written by Ulrich Drepper <drepper@redhat.com>, 2007. 5da0c48c4Sopenharmony_ci 6da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 7da0c48c4Sopenharmony_ci it under the terms of either 8da0c48c4Sopenharmony_ci 9da0c48c4Sopenharmony_ci * the GNU Lesser General Public License as published by the Free 10da0c48c4Sopenharmony_ci Software Foundation; either version 3 of the License, or (at 11da0c48c4Sopenharmony_ci your option) any later version 12da0c48c4Sopenharmony_ci 13da0c48c4Sopenharmony_ci or 14da0c48c4Sopenharmony_ci 15da0c48c4Sopenharmony_ci * the GNU General Public License as published by the Free 16da0c48c4Sopenharmony_ci Software Foundation; either version 2 of the License, or (at 17da0c48c4Sopenharmony_ci your option) any later version 18da0c48c4Sopenharmony_ci 19da0c48c4Sopenharmony_ci or both in parallel, as here. 20da0c48c4Sopenharmony_ci 21da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 22da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 23da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24da0c48c4Sopenharmony_ci General Public License for more details. 25da0c48c4Sopenharmony_ci 26da0c48c4Sopenharmony_ci You should have received copies of the GNU General Public License and 27da0c48c4Sopenharmony_ci the GNU Lesser General Public License along with this program. If 28da0c48c4Sopenharmony_ci not, see <http://www.gnu.org/licenses/>. */ 29da0c48c4Sopenharmony_ci 30da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H 31da0c48c4Sopenharmony_ci# include <config.h> 32da0c48c4Sopenharmony_ci#endif 33da0c48c4Sopenharmony_ci 34da0c48c4Sopenharmony_ci#include <assert.h> 35da0c48c4Sopenharmony_ci#include <config.h> 36da0c48c4Sopenharmony_ci#include <ctype.h> 37da0c48c4Sopenharmony_ci#include <errno.h> 38da0c48c4Sopenharmony_ci#include <gelf.h> 39da0c48c4Sopenharmony_ci#include <stddef.h> 40da0c48c4Sopenharmony_ci#include <stdint.h> 41da0c48c4Sopenharmony_ci#include <stdlib.h> 42da0c48c4Sopenharmony_ci#include <string.h> 43da0c48c4Sopenharmony_ci 44da0c48c4Sopenharmony_ci#include "../libebl/libeblP.h" 45da0c48c4Sopenharmony_ci 46da0c48c4Sopenharmony_ci#define MACHINE_ENCODING LITTLE_ENDIAN 47da0c48c4Sopenharmony_ci#include "memory-access.h" 48da0c48c4Sopenharmony_ci 49da0c48c4Sopenharmony_ci 50da0c48c4Sopenharmony_ci#ifndef MNEFILE 51da0c48c4Sopenharmony_ci# define MNEFILE "i386.mnemonics" 52da0c48c4Sopenharmony_ci#endif 53da0c48c4Sopenharmony_ci 54da0c48c4Sopenharmony_ci#define MNESTRFIELD(line) MNESTRFIELD1 (line) 55da0c48c4Sopenharmony_ci#define MNESTRFIELD1(line) str##line 56da0c48c4Sopenharmony_cistatic const union mnestr_t 57da0c48c4Sopenharmony_ci{ 58da0c48c4Sopenharmony_ci struct 59da0c48c4Sopenharmony_ci { 60da0c48c4Sopenharmony_ci#define MNE(name) char MNESTRFIELD (__LINE__)[sizeof (#name)]; 61da0c48c4Sopenharmony_ci#include MNEFILE 62da0c48c4Sopenharmony_ci#undef MNE 63da0c48c4Sopenharmony_ci }; 64da0c48c4Sopenharmony_ci char str[0]; 65da0c48c4Sopenharmony_ci} mnestr = 66da0c48c4Sopenharmony_ci { 67da0c48c4Sopenharmony_ci { 68da0c48c4Sopenharmony_ci#define MNE(name) #name, 69da0c48c4Sopenharmony_ci#include MNEFILE 70da0c48c4Sopenharmony_ci#undef MNE 71da0c48c4Sopenharmony_ci } 72da0c48c4Sopenharmony_ci }; 73da0c48c4Sopenharmony_ci 74da0c48c4Sopenharmony_ci/* The index can be stored in the instrtab. */ 75da0c48c4Sopenharmony_cienum 76da0c48c4Sopenharmony_ci { 77da0c48c4Sopenharmony_ci#define MNE(name) MNE_##name, 78da0c48c4Sopenharmony_ci#include MNEFILE 79da0c48c4Sopenharmony_ci#undef MNE 80da0c48c4Sopenharmony_ci MNE_INVALID 81da0c48c4Sopenharmony_ci }; 82da0c48c4Sopenharmony_ci 83da0c48c4Sopenharmony_cistatic const unsigned short int mneidx[] = 84da0c48c4Sopenharmony_ci { 85da0c48c4Sopenharmony_ci#define MNE(name) \ 86da0c48c4Sopenharmony_ci [MNE_##name] = offsetof (union mnestr_t, MNESTRFIELD (__LINE__)), 87da0c48c4Sopenharmony_ci#include MNEFILE 88da0c48c4Sopenharmony_ci#undef MNE 89da0c48c4Sopenharmony_ci }; 90da0c48c4Sopenharmony_ci 91da0c48c4Sopenharmony_ci 92da0c48c4Sopenharmony_cienum 93da0c48c4Sopenharmony_ci { 94da0c48c4Sopenharmony_ci idx_rex_b = 0, 95da0c48c4Sopenharmony_ci idx_rex_x, 96da0c48c4Sopenharmony_ci idx_rex_r, 97da0c48c4Sopenharmony_ci idx_rex_w, 98da0c48c4Sopenharmony_ci idx_rex, 99da0c48c4Sopenharmony_ci idx_cs, 100da0c48c4Sopenharmony_ci idx_ds, 101da0c48c4Sopenharmony_ci idx_es, 102da0c48c4Sopenharmony_ci idx_fs, 103da0c48c4Sopenharmony_ci idx_gs, 104da0c48c4Sopenharmony_ci idx_ss, 105da0c48c4Sopenharmony_ci idx_data16, 106da0c48c4Sopenharmony_ci idx_addr16, 107da0c48c4Sopenharmony_ci idx_rep, 108da0c48c4Sopenharmony_ci idx_repne, 109da0c48c4Sopenharmony_ci idx_lock 110da0c48c4Sopenharmony_ci }; 111da0c48c4Sopenharmony_ci 112da0c48c4Sopenharmony_cienum 113da0c48c4Sopenharmony_ci { 114da0c48c4Sopenharmony_ci#define prefbit(pref) has_##pref = 1 << idx_##pref 115da0c48c4Sopenharmony_ci prefbit (rex_b), 116da0c48c4Sopenharmony_ci prefbit (rex_x), 117da0c48c4Sopenharmony_ci prefbit (rex_r), 118da0c48c4Sopenharmony_ci prefbit (rex_w), 119da0c48c4Sopenharmony_ci prefbit (rex), 120da0c48c4Sopenharmony_ci prefbit (cs), 121da0c48c4Sopenharmony_ci prefbit (ds), 122da0c48c4Sopenharmony_ci prefbit (es), 123da0c48c4Sopenharmony_ci prefbit (fs), 124da0c48c4Sopenharmony_ci prefbit (gs), 125da0c48c4Sopenharmony_ci prefbit (ss), 126da0c48c4Sopenharmony_ci prefbit (data16), 127da0c48c4Sopenharmony_ci prefbit (addr16), 128da0c48c4Sopenharmony_ci prefbit (rep), 129da0c48c4Sopenharmony_ci prefbit (repne), 130da0c48c4Sopenharmony_ci prefbit (lock) 131da0c48c4Sopenharmony_ci#undef prefbit 132da0c48c4Sopenharmony_ci }; 133da0c48c4Sopenharmony_ci#define SEGMENT_PREFIXES \ 134da0c48c4Sopenharmony_ci (has_cs | has_ds | has_es | has_fs | has_gs | has_ss) 135da0c48c4Sopenharmony_ci 136da0c48c4Sopenharmony_ci#define prefix_cs 0x2e 137da0c48c4Sopenharmony_ci#define prefix_ds 0x3e 138da0c48c4Sopenharmony_ci#define prefix_es 0x26 139da0c48c4Sopenharmony_ci#define prefix_fs 0x64 140da0c48c4Sopenharmony_ci#define prefix_gs 0x65 141da0c48c4Sopenharmony_ci#define prefix_ss 0x36 142da0c48c4Sopenharmony_ci#define prefix_data16 0x66 143da0c48c4Sopenharmony_ci#define prefix_addr16 0x67 144da0c48c4Sopenharmony_ci#define prefix_rep 0xf3 145da0c48c4Sopenharmony_ci#define prefix_repne 0xf2 146da0c48c4Sopenharmony_ci#define prefix_lock 0xf0 147da0c48c4Sopenharmony_ci 148da0c48c4Sopenharmony_ci 149da0c48c4Sopenharmony_cistatic const uint8_t known_prefixes[] = 150da0c48c4Sopenharmony_ci { 151da0c48c4Sopenharmony_ci#define newpref(pref) [idx_##pref] = prefix_##pref 152da0c48c4Sopenharmony_ci newpref (cs), 153da0c48c4Sopenharmony_ci newpref (ds), 154da0c48c4Sopenharmony_ci newpref (es), 155da0c48c4Sopenharmony_ci newpref (fs), 156da0c48c4Sopenharmony_ci newpref (gs), 157da0c48c4Sopenharmony_ci newpref (ss), 158da0c48c4Sopenharmony_ci newpref (data16), 159da0c48c4Sopenharmony_ci newpref (addr16), 160da0c48c4Sopenharmony_ci newpref (rep), 161da0c48c4Sopenharmony_ci newpref (repne), 162da0c48c4Sopenharmony_ci newpref (lock) 163da0c48c4Sopenharmony_ci#undef newpref 164da0c48c4Sopenharmony_ci }; 165da0c48c4Sopenharmony_ci#define nknown_prefixes (sizeof (known_prefixes) / sizeof (known_prefixes[0])) 166da0c48c4Sopenharmony_ci 167da0c48c4Sopenharmony_ci 168da0c48c4Sopenharmony_ci#if 0 169da0c48c4Sopenharmony_cistatic const char *prefix_str[] = 170da0c48c4Sopenharmony_ci { 171da0c48c4Sopenharmony_ci#define newpref(pref) [idx_##pref] = #pref 172da0c48c4Sopenharmony_ci newpref (cs), 173da0c48c4Sopenharmony_ci newpref (ds), 174da0c48c4Sopenharmony_ci newpref (es), 175da0c48c4Sopenharmony_ci newpref (fs), 176da0c48c4Sopenharmony_ci newpref (gs), 177da0c48c4Sopenharmony_ci newpref (ss), 178da0c48c4Sopenharmony_ci newpref (data16), 179da0c48c4Sopenharmony_ci newpref (addr16), 180da0c48c4Sopenharmony_ci newpref (rep), 181da0c48c4Sopenharmony_ci newpref (repne), 182da0c48c4Sopenharmony_ci newpref (lock) 183da0c48c4Sopenharmony_ci#undef newpref 184da0c48c4Sopenharmony_ci }; 185da0c48c4Sopenharmony_ci#endif 186da0c48c4Sopenharmony_ci 187da0c48c4Sopenharmony_ci 188da0c48c4Sopenharmony_cistatic const char amd3dnowstr[] = 189da0c48c4Sopenharmony_ci#define MNE_3DNOW_PAVGUSB 1 190da0c48c4Sopenharmony_ci "pavgusb\0" 191da0c48c4Sopenharmony_ci#define MNE_3DNOW_PFADD (MNE_3DNOW_PAVGUSB + 8) 192da0c48c4Sopenharmony_ci "pfadd\0" 193da0c48c4Sopenharmony_ci#define MNE_3DNOW_PFSUB (MNE_3DNOW_PFADD + 6) 194da0c48c4Sopenharmony_ci "pfsub\0" 195da0c48c4Sopenharmony_ci#define MNE_3DNOW_PFSUBR (MNE_3DNOW_PFSUB + 6) 196da0c48c4Sopenharmony_ci "pfsubr\0" 197da0c48c4Sopenharmony_ci#define MNE_3DNOW_PFACC (MNE_3DNOW_PFSUBR + 7) 198da0c48c4Sopenharmony_ci "pfacc\0" 199da0c48c4Sopenharmony_ci#define MNE_3DNOW_PFCMPGE (MNE_3DNOW_PFACC + 6) 200da0c48c4Sopenharmony_ci "pfcmpge\0" 201da0c48c4Sopenharmony_ci#define MNE_3DNOW_PFCMPGT (MNE_3DNOW_PFCMPGE + 8) 202da0c48c4Sopenharmony_ci "pfcmpgt\0" 203da0c48c4Sopenharmony_ci#define MNE_3DNOW_PFCMPEQ (MNE_3DNOW_PFCMPGT + 8) 204da0c48c4Sopenharmony_ci "pfcmpeq\0" 205da0c48c4Sopenharmony_ci#define MNE_3DNOW_PFMIN (MNE_3DNOW_PFCMPEQ + 8) 206da0c48c4Sopenharmony_ci "pfmin\0" 207da0c48c4Sopenharmony_ci#define MNE_3DNOW_PFMAX (MNE_3DNOW_PFMIN + 6) 208da0c48c4Sopenharmony_ci "pfmax\0" 209da0c48c4Sopenharmony_ci#define MNE_3DNOW_PI2FD (MNE_3DNOW_PFMAX + 6) 210da0c48c4Sopenharmony_ci "pi2fd\0" 211da0c48c4Sopenharmony_ci#define MNE_3DNOW_PF2ID (MNE_3DNOW_PI2FD + 6) 212da0c48c4Sopenharmony_ci "pf2id\0" 213da0c48c4Sopenharmony_ci#define MNE_3DNOW_PFRCP (MNE_3DNOW_PF2ID + 6) 214da0c48c4Sopenharmony_ci "pfrcp\0" 215da0c48c4Sopenharmony_ci#define MNE_3DNOW_PFRSQRT (MNE_3DNOW_PFRCP + 6) 216da0c48c4Sopenharmony_ci "pfrsqrt\0" 217da0c48c4Sopenharmony_ci#define MNE_3DNOW_PFMUL (MNE_3DNOW_PFRSQRT + 8) 218da0c48c4Sopenharmony_ci "pfmul\0" 219da0c48c4Sopenharmony_ci#define MNE_3DNOW_PFRCPIT1 (MNE_3DNOW_PFMUL + 6) 220da0c48c4Sopenharmony_ci "pfrcpit1\0" 221da0c48c4Sopenharmony_ci#define MNE_3DNOW_PFRSQIT1 (MNE_3DNOW_PFRCPIT1 + 9) 222da0c48c4Sopenharmony_ci "pfrsqit1\0" 223da0c48c4Sopenharmony_ci#define MNE_3DNOW_PFRCPIT2 (MNE_3DNOW_PFRSQIT1 + 9) 224da0c48c4Sopenharmony_ci "pfrcpit2\0" 225da0c48c4Sopenharmony_ci#define MNE_3DNOW_PMULHRW (MNE_3DNOW_PFRCPIT2 + 9) 226da0c48c4Sopenharmony_ci "pmulhrw"; 227da0c48c4Sopenharmony_ci 228da0c48c4Sopenharmony_ci#define AMD3DNOW_LOW_IDX 0x0d 229da0c48c4Sopenharmony_ci#define AMD3DNOW_HIGH_IDX (sizeof (amd3dnow) + AMD3DNOW_LOW_IDX - 1) 230da0c48c4Sopenharmony_ci#define AMD3DNOW_IDX(val) ((val) - AMD3DNOW_LOW_IDX) 231da0c48c4Sopenharmony_cistatic const unsigned char amd3dnow[] = 232da0c48c4Sopenharmony_ci { 233da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0xbf)] = MNE_3DNOW_PAVGUSB, 234da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0x9e)] = MNE_3DNOW_PFADD, 235da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0x9a)] = MNE_3DNOW_PFSUB, 236da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0xaa)] = MNE_3DNOW_PFSUBR, 237da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0xae)] = MNE_3DNOW_PFACC, 238da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0x90)] = MNE_3DNOW_PFCMPGE, 239da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0xa0)] = MNE_3DNOW_PFCMPGT, 240da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0xb0)] = MNE_3DNOW_PFCMPEQ, 241da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0x94)] = MNE_3DNOW_PFMIN, 242da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0xa4)] = MNE_3DNOW_PFMAX, 243da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0x0d)] = MNE_3DNOW_PI2FD, 244da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0x1d)] = MNE_3DNOW_PF2ID, 245da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0x96)] = MNE_3DNOW_PFRCP, 246da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0x97)] = MNE_3DNOW_PFRSQRT, 247da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0xb4)] = MNE_3DNOW_PFMUL, 248da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0xa6)] = MNE_3DNOW_PFRCPIT1, 249da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0xa7)] = MNE_3DNOW_PFRSQIT1, 250da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0xb6)] = MNE_3DNOW_PFRCPIT2, 251da0c48c4Sopenharmony_ci [AMD3DNOW_IDX (0xb7)] = MNE_3DNOW_PMULHRW 252da0c48c4Sopenharmony_ci }; 253da0c48c4Sopenharmony_ci 254da0c48c4Sopenharmony_ci 255da0c48c4Sopenharmony_cistruct output_data 256da0c48c4Sopenharmony_ci{ 257da0c48c4Sopenharmony_ci GElf_Addr addr; 258da0c48c4Sopenharmony_ci int *prefixes; 259da0c48c4Sopenharmony_ci size_t opoff1; 260da0c48c4Sopenharmony_ci size_t opoff2; 261da0c48c4Sopenharmony_ci size_t opoff3; 262da0c48c4Sopenharmony_ci char *bufp; 263da0c48c4Sopenharmony_ci size_t *bufcntp; 264da0c48c4Sopenharmony_ci size_t bufsize; 265da0c48c4Sopenharmony_ci const uint8_t *data; 266da0c48c4Sopenharmony_ci const uint8_t **param_start; 267da0c48c4Sopenharmony_ci const uint8_t *end; 268da0c48c4Sopenharmony_ci char *labelbuf; 269da0c48c4Sopenharmony_ci size_t labelbufsize; 270da0c48c4Sopenharmony_ci enum 271da0c48c4Sopenharmony_ci { 272da0c48c4Sopenharmony_ci addr_none = 0, 273da0c48c4Sopenharmony_ci addr_abs_symbolic, 274da0c48c4Sopenharmony_ci addr_abs_always, 275da0c48c4Sopenharmony_ci addr_rel_symbolic, 276da0c48c4Sopenharmony_ci addr_rel_always 277da0c48c4Sopenharmony_ci } symaddr_use; 278da0c48c4Sopenharmony_ci GElf_Addr symaddr; 279da0c48c4Sopenharmony_ci}; 280da0c48c4Sopenharmony_ci 281da0c48c4Sopenharmony_ci 282da0c48c4Sopenharmony_ci#ifndef DISFILE 283da0c48c4Sopenharmony_ci# define DISFILE "i386_dis.h" 284da0c48c4Sopenharmony_ci#endif 285da0c48c4Sopenharmony_ci#include DISFILE 286da0c48c4Sopenharmony_ci 287da0c48c4Sopenharmony_ci 288da0c48c4Sopenharmony_ci#define ADD_CHAR(ch) \ 289da0c48c4Sopenharmony_ci do { \ 290da0c48c4Sopenharmony_ci if (unlikely (bufcnt == bufsize)) \ 291da0c48c4Sopenharmony_ci goto enomem; \ 292da0c48c4Sopenharmony_ci buf[bufcnt++] = (ch); \ 293da0c48c4Sopenharmony_ci } while (0) 294da0c48c4Sopenharmony_ci 295da0c48c4Sopenharmony_ci#define ADD_STRING(str) \ 296da0c48c4Sopenharmony_ci do { \ 297da0c48c4Sopenharmony_ci const char *_str0 = (str); \ 298da0c48c4Sopenharmony_ci size_t _len0 = strlen (_str0); \ 299da0c48c4Sopenharmony_ci ADD_NSTRING (_str0, _len0); \ 300da0c48c4Sopenharmony_ci } while (0) 301da0c48c4Sopenharmony_ci 302da0c48c4Sopenharmony_ci#define ADD_NSTRING(str, len) \ 303da0c48c4Sopenharmony_ci do { \ 304da0c48c4Sopenharmony_ci const char *_str = (str); \ 305da0c48c4Sopenharmony_ci size_t _len = (len); \ 306da0c48c4Sopenharmony_ci if (unlikely (bufcnt + _len > bufsize)) \ 307da0c48c4Sopenharmony_ci goto enomem; \ 308da0c48c4Sopenharmony_ci memcpy (buf + bufcnt, _str, _len); \ 309da0c48c4Sopenharmony_ci bufcnt += _len; \ 310da0c48c4Sopenharmony_ci } while (0) 311da0c48c4Sopenharmony_ci 312da0c48c4Sopenharmony_ci 313da0c48c4Sopenharmony_ciint 314da0c48c4Sopenharmony_cii386_disasm (Ebl *ebl __attribute__((unused)), 315da0c48c4Sopenharmony_ci const uint8_t **startp, const uint8_t *end, GElf_Addr addr, 316da0c48c4Sopenharmony_ci const char *fmt, DisasmOutputCB_t outcb, DisasmGetSymCB_t symcb, 317da0c48c4Sopenharmony_ci void *outcbarg, void *symcbarg) 318da0c48c4Sopenharmony_ci{ 319da0c48c4Sopenharmony_ci const char *save_fmt = fmt; 320da0c48c4Sopenharmony_ci 321da0c48c4Sopenharmony_ci#define BUFSIZE 512 322da0c48c4Sopenharmony_ci char initbuf[BUFSIZE]; 323da0c48c4Sopenharmony_ci int prefixes; 324da0c48c4Sopenharmony_ci size_t bufcnt; 325da0c48c4Sopenharmony_ci size_t bufsize = BUFSIZE; 326da0c48c4Sopenharmony_ci char *buf = initbuf; 327da0c48c4Sopenharmony_ci const uint8_t *param_start; 328da0c48c4Sopenharmony_ci 329da0c48c4Sopenharmony_ci struct output_data output_data = 330da0c48c4Sopenharmony_ci { 331da0c48c4Sopenharmony_ci .prefixes = &prefixes, 332da0c48c4Sopenharmony_ci .bufp = buf, 333da0c48c4Sopenharmony_ci .bufsize = bufsize, 334da0c48c4Sopenharmony_ci .bufcntp = &bufcnt, 335da0c48c4Sopenharmony_ci .param_start = ¶m_start, 336da0c48c4Sopenharmony_ci .end = end 337da0c48c4Sopenharmony_ci }; 338da0c48c4Sopenharmony_ci 339da0c48c4Sopenharmony_ci int retval = 0; 340da0c48c4Sopenharmony_ci while (1) 341da0c48c4Sopenharmony_ci { 342da0c48c4Sopenharmony_ci prefixes = 0; 343da0c48c4Sopenharmony_ci 344da0c48c4Sopenharmony_ci const uint8_t *data = *startp; 345da0c48c4Sopenharmony_ci const uint8_t *begin = data; 346da0c48c4Sopenharmony_ci 347da0c48c4Sopenharmony_ci /* Recognize all prefixes. */ 348da0c48c4Sopenharmony_ci int last_prefix_bit = 0; 349da0c48c4Sopenharmony_ci while (data < end) 350da0c48c4Sopenharmony_ci { 351da0c48c4Sopenharmony_ci unsigned int i; 352da0c48c4Sopenharmony_ci for (i = idx_cs; i < nknown_prefixes; ++i) 353da0c48c4Sopenharmony_ci if (known_prefixes[i] == *data) 354da0c48c4Sopenharmony_ci break; 355da0c48c4Sopenharmony_ci if (i == nknown_prefixes) 356da0c48c4Sopenharmony_ci break; 357da0c48c4Sopenharmony_ci 358da0c48c4Sopenharmony_ci prefixes |= last_prefix_bit = 1 << i; 359da0c48c4Sopenharmony_ci 360da0c48c4Sopenharmony_ci ++data; 361da0c48c4Sopenharmony_ci } 362da0c48c4Sopenharmony_ci 363da0c48c4Sopenharmony_ci#ifdef X86_64 364da0c48c4Sopenharmony_ci if (data < end && (*data & 0xf0) == 0x40) 365da0c48c4Sopenharmony_ci prefixes |= ((*data++) & 0xf) | has_rex; 366da0c48c4Sopenharmony_ci#endif 367da0c48c4Sopenharmony_ci 368da0c48c4Sopenharmony_ci bufcnt = 0; 369da0c48c4Sopenharmony_ci size_t cnt = 0; 370da0c48c4Sopenharmony_ci 371da0c48c4Sopenharmony_ci const uint8_t *curr = match_data; 372da0c48c4Sopenharmony_ci const uint8_t *const match_end = match_data + sizeof (match_data); 373da0c48c4Sopenharmony_ci 374da0c48c4Sopenharmony_ci assert (data <= end); 375da0c48c4Sopenharmony_ci if (data == end) 376da0c48c4Sopenharmony_ci { 377da0c48c4Sopenharmony_ci if (prefixes != 0) 378da0c48c4Sopenharmony_ci goto print_prefix; 379da0c48c4Sopenharmony_ci 380da0c48c4Sopenharmony_ci retval = -1; 381da0c48c4Sopenharmony_ci goto do_ret; 382da0c48c4Sopenharmony_ci } 383da0c48c4Sopenharmony_ci 384da0c48c4Sopenharmony_ci next_match: 385da0c48c4Sopenharmony_ci while (curr < match_end) 386da0c48c4Sopenharmony_ci { 387da0c48c4Sopenharmony_ci uint_fast8_t len = *curr++; 388da0c48c4Sopenharmony_ci uint_fast8_t clen = len >> 4; 389da0c48c4Sopenharmony_ci len &= 0xf; 390da0c48c4Sopenharmony_ci const uint8_t *next_curr = curr + clen + (len - clen) * 2; 391da0c48c4Sopenharmony_ci 392da0c48c4Sopenharmony_ci assert (len > 0); 393da0c48c4Sopenharmony_ci assert (curr + clen + 2 * (len - clen) <= match_end); 394da0c48c4Sopenharmony_ci 395da0c48c4Sopenharmony_ci const uint8_t *codep = data; 396da0c48c4Sopenharmony_ci int correct_prefix = 0; 397da0c48c4Sopenharmony_ci int opoff = 0; 398da0c48c4Sopenharmony_ci 399da0c48c4Sopenharmony_ci if (data > begin && codep[-1] == *curr && clen > 0) 400da0c48c4Sopenharmony_ci { 401da0c48c4Sopenharmony_ci /* We match a prefix byte. This is exactly one byte and 402da0c48c4Sopenharmony_ci is matched exactly, without a mask. */ 403da0c48c4Sopenharmony_ci --len; 404da0c48c4Sopenharmony_ci --clen; 405da0c48c4Sopenharmony_ci opoff = 8; 406da0c48c4Sopenharmony_ci 407da0c48c4Sopenharmony_ci ++curr; 408da0c48c4Sopenharmony_ci 409da0c48c4Sopenharmony_ci if (last_prefix_bit == 0) 410da0c48c4Sopenharmony_ci goto invalid_op; 411da0c48c4Sopenharmony_ci correct_prefix = last_prefix_bit; 412da0c48c4Sopenharmony_ci } 413da0c48c4Sopenharmony_ci 414da0c48c4Sopenharmony_ci size_t avail = len; 415da0c48c4Sopenharmony_ci while (clen > 0) 416da0c48c4Sopenharmony_ci { 417da0c48c4Sopenharmony_ci if (*codep++ != *curr++) 418da0c48c4Sopenharmony_ci goto not; 419da0c48c4Sopenharmony_ci --avail; 420da0c48c4Sopenharmony_ci --clen; 421da0c48c4Sopenharmony_ci if (codep == end && avail > 0) 422da0c48c4Sopenharmony_ci goto do_ret; 423da0c48c4Sopenharmony_ci } 424da0c48c4Sopenharmony_ci 425da0c48c4Sopenharmony_ci while (avail > 0) 426da0c48c4Sopenharmony_ci { 427da0c48c4Sopenharmony_ci uint_fast8_t masked = *codep++ & *curr++; 428da0c48c4Sopenharmony_ci if (masked != *curr++) 429da0c48c4Sopenharmony_ci { 430da0c48c4Sopenharmony_ci not: 431da0c48c4Sopenharmony_ci curr = next_curr; 432da0c48c4Sopenharmony_ci ++cnt; 433da0c48c4Sopenharmony_ci bufcnt = 0; 434da0c48c4Sopenharmony_ci goto next_match; 435da0c48c4Sopenharmony_ci } 436da0c48c4Sopenharmony_ci 437da0c48c4Sopenharmony_ci --avail; 438da0c48c4Sopenharmony_ci if (codep == end && avail > 0) 439da0c48c4Sopenharmony_ci goto do_ret; 440da0c48c4Sopenharmony_ci } 441da0c48c4Sopenharmony_ci 442da0c48c4Sopenharmony_ci if (len > end - data) 443da0c48c4Sopenharmony_ci /* There is not enough data for the entire instruction. The 444da0c48c4Sopenharmony_ci caller can figure this out by looking at the pointer into 445da0c48c4Sopenharmony_ci the input data. */ 446da0c48c4Sopenharmony_ci goto do_ret; 447da0c48c4Sopenharmony_ci 448da0c48c4Sopenharmony_ci if (correct_prefix != 0 && (prefixes & correct_prefix) == 0) 449da0c48c4Sopenharmony_ci goto invalid_op; 450da0c48c4Sopenharmony_ci prefixes ^= correct_prefix; 451da0c48c4Sopenharmony_ci 452da0c48c4Sopenharmony_ci if (0) 453da0c48c4Sopenharmony_ci { 454da0c48c4Sopenharmony_ci /* Resize the buffer. */ 455da0c48c4Sopenharmony_ci char *oldbuf; 456da0c48c4Sopenharmony_ci enomem: 457da0c48c4Sopenharmony_ci oldbuf = buf; 458da0c48c4Sopenharmony_ci if (buf == initbuf) 459da0c48c4Sopenharmony_ci buf = malloc (2 * bufsize); 460da0c48c4Sopenharmony_ci else 461da0c48c4Sopenharmony_ci buf = realloc (buf, 2 * bufsize); 462da0c48c4Sopenharmony_ci if (buf == NULL) 463da0c48c4Sopenharmony_ci { 464da0c48c4Sopenharmony_ci buf = oldbuf; 465da0c48c4Sopenharmony_ci retval = ENOMEM; 466da0c48c4Sopenharmony_ci goto do_ret; 467da0c48c4Sopenharmony_ci } 468da0c48c4Sopenharmony_ci bufsize *= 2; 469da0c48c4Sopenharmony_ci 470da0c48c4Sopenharmony_ci output_data.bufp = buf; 471da0c48c4Sopenharmony_ci output_data.bufsize = bufsize; 472da0c48c4Sopenharmony_ci bufcnt = 0; 473da0c48c4Sopenharmony_ci 474da0c48c4Sopenharmony_ci if (data == end) 475da0c48c4Sopenharmony_ci { 476da0c48c4Sopenharmony_ci if (prefixes == 0) 477da0c48c4Sopenharmony_ci goto invalid_op; 478da0c48c4Sopenharmony_ci goto print_prefix; 479da0c48c4Sopenharmony_ci } 480da0c48c4Sopenharmony_ci 481da0c48c4Sopenharmony_ci /* gcc is not clever enough to see the following variables 482da0c48c4Sopenharmony_ci are not used uninitialized. */ 483da0c48c4Sopenharmony_ci asm ("" 484da0c48c4Sopenharmony_ci : "=mr" (opoff), "=mr" (correct_prefix), "=mr" (codep), 485da0c48c4Sopenharmony_ci "=mr" (next_curr), "=mr" (len)); 486da0c48c4Sopenharmony_ci } 487da0c48c4Sopenharmony_ci 488da0c48c4Sopenharmony_ci size_t prefix_size = 0; 489da0c48c4Sopenharmony_ci 490da0c48c4Sopenharmony_ci // XXXonly print as prefix if valid? 491da0c48c4Sopenharmony_ci if ((prefixes & has_lock) != 0) 492da0c48c4Sopenharmony_ci { 493da0c48c4Sopenharmony_ci ADD_STRING ("lock "); 494da0c48c4Sopenharmony_ci prefix_size += 5; 495da0c48c4Sopenharmony_ci } 496da0c48c4Sopenharmony_ci 497da0c48c4Sopenharmony_ci if (instrtab[cnt].rep) 498da0c48c4Sopenharmony_ci { 499da0c48c4Sopenharmony_ci if ((prefixes & has_rep) != 0) 500da0c48c4Sopenharmony_ci { 501da0c48c4Sopenharmony_ci ADD_STRING ("rep "); 502da0c48c4Sopenharmony_ci prefix_size += 4; 503da0c48c4Sopenharmony_ci } 504da0c48c4Sopenharmony_ci } 505da0c48c4Sopenharmony_ci else if (instrtab[cnt].repe 506da0c48c4Sopenharmony_ci && (prefixes & (has_rep | has_repne)) != 0) 507da0c48c4Sopenharmony_ci { 508da0c48c4Sopenharmony_ci if ((prefixes & has_repne) != 0) 509da0c48c4Sopenharmony_ci { 510da0c48c4Sopenharmony_ci ADD_STRING ("repne "); 511da0c48c4Sopenharmony_ci prefix_size += 6; 512da0c48c4Sopenharmony_ci } 513da0c48c4Sopenharmony_ci else if ((prefixes & has_rep) != 0) 514da0c48c4Sopenharmony_ci { 515da0c48c4Sopenharmony_ci ADD_STRING ("repe "); 516da0c48c4Sopenharmony_ci prefix_size += 5; 517da0c48c4Sopenharmony_ci } 518da0c48c4Sopenharmony_ci } 519da0c48c4Sopenharmony_ci else if ((prefixes & (has_rep | has_repne)) != 0) 520da0c48c4Sopenharmony_ci { 521da0c48c4Sopenharmony_ci uint_fast8_t byte; 522da0c48c4Sopenharmony_ci print_prefix: 523da0c48c4Sopenharmony_ci bufcnt = 0; 524da0c48c4Sopenharmony_ci byte = *begin; 525da0c48c4Sopenharmony_ci /* This is a prefix byte. Print it. */ 526da0c48c4Sopenharmony_ci switch (byte) 527da0c48c4Sopenharmony_ci { 528da0c48c4Sopenharmony_ci case prefix_rep: 529da0c48c4Sopenharmony_ci ADD_STRING ("rep"); 530da0c48c4Sopenharmony_ci break; 531da0c48c4Sopenharmony_ci case prefix_repne: 532da0c48c4Sopenharmony_ci ADD_STRING ("repne"); 533da0c48c4Sopenharmony_ci break; 534da0c48c4Sopenharmony_ci case prefix_cs: 535da0c48c4Sopenharmony_ci ADD_STRING ("cs"); 536da0c48c4Sopenharmony_ci break; 537da0c48c4Sopenharmony_ci case prefix_ds: 538da0c48c4Sopenharmony_ci ADD_STRING ("ds"); 539da0c48c4Sopenharmony_ci break; 540da0c48c4Sopenharmony_ci case prefix_es: 541da0c48c4Sopenharmony_ci ADD_STRING ("es"); 542da0c48c4Sopenharmony_ci break; 543da0c48c4Sopenharmony_ci case prefix_fs: 544da0c48c4Sopenharmony_ci ADD_STRING ("fs"); 545da0c48c4Sopenharmony_ci break; 546da0c48c4Sopenharmony_ci case prefix_gs: 547da0c48c4Sopenharmony_ci ADD_STRING ("gs"); 548da0c48c4Sopenharmony_ci break; 549da0c48c4Sopenharmony_ci case prefix_ss: 550da0c48c4Sopenharmony_ci ADD_STRING ("ss"); 551da0c48c4Sopenharmony_ci break; 552da0c48c4Sopenharmony_ci case prefix_data16: 553da0c48c4Sopenharmony_ci ADD_STRING ("data16"); 554da0c48c4Sopenharmony_ci break; 555da0c48c4Sopenharmony_ci case prefix_addr16: 556da0c48c4Sopenharmony_ci ADD_STRING ("addr16"); 557da0c48c4Sopenharmony_ci break; 558da0c48c4Sopenharmony_ci case prefix_lock: 559da0c48c4Sopenharmony_ci ADD_STRING ("lock"); 560da0c48c4Sopenharmony_ci break; 561da0c48c4Sopenharmony_ci#ifdef X86_64 562da0c48c4Sopenharmony_ci case 0x40 ... 0x4f: 563da0c48c4Sopenharmony_ci ADD_STRING ("rex"); 564da0c48c4Sopenharmony_ci if (byte != 0x40) 565da0c48c4Sopenharmony_ci { 566da0c48c4Sopenharmony_ci ADD_CHAR ('.'); 567da0c48c4Sopenharmony_ci if (byte & 0x8) 568da0c48c4Sopenharmony_ci ADD_CHAR ('w'); 569da0c48c4Sopenharmony_ci if (byte & 0x4) 570da0c48c4Sopenharmony_ci ADD_CHAR ('r'); 571da0c48c4Sopenharmony_ci if (byte & 0x3) 572da0c48c4Sopenharmony_ci ADD_CHAR ('x'); 573da0c48c4Sopenharmony_ci if (byte & 0x1) 574da0c48c4Sopenharmony_ci ADD_CHAR ('b'); 575da0c48c4Sopenharmony_ci } 576da0c48c4Sopenharmony_ci break; 577da0c48c4Sopenharmony_ci#endif 578da0c48c4Sopenharmony_ci default: 579da0c48c4Sopenharmony_ci /* Cannot happen. */ 580da0c48c4Sopenharmony_ci puts ("unknown prefix"); 581da0c48c4Sopenharmony_ci abort (); 582da0c48c4Sopenharmony_ci } 583da0c48c4Sopenharmony_ci data = begin + 1; 584da0c48c4Sopenharmony_ci ++addr; 585da0c48c4Sopenharmony_ci 586da0c48c4Sopenharmony_ci goto out; 587da0c48c4Sopenharmony_ci } 588da0c48c4Sopenharmony_ci 589da0c48c4Sopenharmony_ci /* We have a match. First determine how many bytes are 590da0c48c4Sopenharmony_ci needed for the addressing mode. */ 591da0c48c4Sopenharmony_ci param_start = codep; 592da0c48c4Sopenharmony_ci if (instrtab[cnt].modrm) 593da0c48c4Sopenharmony_ci { 594da0c48c4Sopenharmony_ci uint_fast8_t modrm = codep[-1]; 595da0c48c4Sopenharmony_ci 596da0c48c4Sopenharmony_ci#ifndef X86_64 597da0c48c4Sopenharmony_ci if (likely ((prefixes & has_addr16) != 0)) 598da0c48c4Sopenharmony_ci { 599da0c48c4Sopenharmony_ci /* Account for displacement. */ 600da0c48c4Sopenharmony_ci if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80) 601da0c48c4Sopenharmony_ci param_start += 2; 602da0c48c4Sopenharmony_ci else if ((modrm & 0xc0) == 0x40) 603da0c48c4Sopenharmony_ci param_start += 1; 604da0c48c4Sopenharmony_ci } 605da0c48c4Sopenharmony_ci else 606da0c48c4Sopenharmony_ci#endif 607da0c48c4Sopenharmony_ci { 608da0c48c4Sopenharmony_ci /* Account for SIB. */ 609da0c48c4Sopenharmony_ci if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 0x4) 610da0c48c4Sopenharmony_ci param_start += 1; 611da0c48c4Sopenharmony_ci 612da0c48c4Sopenharmony_ci /* Account for displacement. */ 613da0c48c4Sopenharmony_ci if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80 614da0c48c4Sopenharmony_ci || ((modrm & 0xc7) == 0x4 615da0c48c4Sopenharmony_ci && param_start < end 616da0c48c4Sopenharmony_ci && (codep[0] & 0x7) == 0x5)) 617da0c48c4Sopenharmony_ci param_start += 4; 618da0c48c4Sopenharmony_ci else if ((modrm & 0xc0) == 0x40) 619da0c48c4Sopenharmony_ci param_start += 1; 620da0c48c4Sopenharmony_ci } 621da0c48c4Sopenharmony_ci 622da0c48c4Sopenharmony_ci if (unlikely (param_start > end)) 623da0c48c4Sopenharmony_ci goto not; 624da0c48c4Sopenharmony_ci } 625da0c48c4Sopenharmony_ci 626da0c48c4Sopenharmony_ci output_data.addr = addr + (data - begin); 627da0c48c4Sopenharmony_ci output_data.data = data; 628da0c48c4Sopenharmony_ci 629da0c48c4Sopenharmony_ci unsigned long string_end_idx = 0; 630da0c48c4Sopenharmony_ci fmt = save_fmt; 631da0c48c4Sopenharmony_ci const char *deferred_start = NULL; 632da0c48c4Sopenharmony_ci size_t deferred_len = 0; 633da0c48c4Sopenharmony_ci // XXX Can we get this from color.c? 634da0c48c4Sopenharmony_ci static const char color_off[] = "\e[0m"; 635da0c48c4Sopenharmony_ci while (*fmt != '\0') 636da0c48c4Sopenharmony_ci { 637da0c48c4Sopenharmony_ci if (*fmt != '%') 638da0c48c4Sopenharmony_ci { 639da0c48c4Sopenharmony_ci char ch = *fmt++; 640da0c48c4Sopenharmony_ci if (ch == '\\') 641da0c48c4Sopenharmony_ci { 642da0c48c4Sopenharmony_ci switch ((ch = *fmt++)) 643da0c48c4Sopenharmony_ci { 644da0c48c4Sopenharmony_ci case '0' ... '7': 645da0c48c4Sopenharmony_ci { 646da0c48c4Sopenharmony_ci int val = ch - '0'; 647da0c48c4Sopenharmony_ci ch = *fmt; 648da0c48c4Sopenharmony_ci if (ch >= '0' && ch <= '7') 649da0c48c4Sopenharmony_ci { 650da0c48c4Sopenharmony_ci val *= 8; 651da0c48c4Sopenharmony_ci val += ch - '0'; 652da0c48c4Sopenharmony_ci ch = *++fmt; 653da0c48c4Sopenharmony_ci if (ch >= '0' && ch <= '7' && val < 32) 654da0c48c4Sopenharmony_ci { 655da0c48c4Sopenharmony_ci val *= 8; 656da0c48c4Sopenharmony_ci val += ch - '0'; 657da0c48c4Sopenharmony_ci ++fmt; 658da0c48c4Sopenharmony_ci } 659da0c48c4Sopenharmony_ci } 660da0c48c4Sopenharmony_ci ch = val; 661da0c48c4Sopenharmony_ci } 662da0c48c4Sopenharmony_ci break; 663da0c48c4Sopenharmony_ci 664da0c48c4Sopenharmony_ci case 'n': 665da0c48c4Sopenharmony_ci ch = '\n'; 666da0c48c4Sopenharmony_ci break; 667da0c48c4Sopenharmony_ci 668da0c48c4Sopenharmony_ci case 't': 669da0c48c4Sopenharmony_ci ch = '\t'; 670da0c48c4Sopenharmony_ci break; 671da0c48c4Sopenharmony_ci 672da0c48c4Sopenharmony_ci default: 673da0c48c4Sopenharmony_ci retval = EINVAL; 674da0c48c4Sopenharmony_ci goto do_ret; 675da0c48c4Sopenharmony_ci } 676da0c48c4Sopenharmony_ci } 677da0c48c4Sopenharmony_ci else if (ch == '\e' && *fmt == '[') 678da0c48c4Sopenharmony_ci { 679da0c48c4Sopenharmony_ci deferred_start = fmt - 1; 680da0c48c4Sopenharmony_ci do 681da0c48c4Sopenharmony_ci ++fmt; 682da0c48c4Sopenharmony_ci while (*fmt != 'm' && *fmt != '\0'); 683da0c48c4Sopenharmony_ci 684da0c48c4Sopenharmony_ci if (*fmt == 'm') 685da0c48c4Sopenharmony_ci { 686da0c48c4Sopenharmony_ci deferred_len = ++fmt - deferred_start; 687da0c48c4Sopenharmony_ci continue; 688da0c48c4Sopenharmony_ci } 689da0c48c4Sopenharmony_ci 690da0c48c4Sopenharmony_ci fmt = deferred_start + 1; 691da0c48c4Sopenharmony_ci deferred_start = NULL; 692da0c48c4Sopenharmony_ci } 693da0c48c4Sopenharmony_ci ADD_CHAR (ch); 694da0c48c4Sopenharmony_ci continue; 695da0c48c4Sopenharmony_ci } 696da0c48c4Sopenharmony_ci ++fmt; 697da0c48c4Sopenharmony_ci 698da0c48c4Sopenharmony_ci int width = 0; 699da0c48c4Sopenharmony_ci while (isdigit (*fmt)) 700da0c48c4Sopenharmony_ci width = width * 10 + (*fmt++ - '0'); 701da0c48c4Sopenharmony_ci 702da0c48c4Sopenharmony_ci int prec = 0; 703da0c48c4Sopenharmony_ci if (*fmt == '.') 704da0c48c4Sopenharmony_ci while (isdigit (*++fmt)) 705da0c48c4Sopenharmony_ci prec = prec * 10 + (*fmt - '0'); 706da0c48c4Sopenharmony_ci 707da0c48c4Sopenharmony_ci size_t start_idx = bufcnt; 708da0c48c4Sopenharmony_ci size_t non_printing = 0; 709da0c48c4Sopenharmony_ci switch (*fmt++) 710da0c48c4Sopenharmony_ci { 711da0c48c4Sopenharmony_ci char mnebuf[16]; 712da0c48c4Sopenharmony_ci const char *str; 713da0c48c4Sopenharmony_ci 714da0c48c4Sopenharmony_ci case 'm': 715da0c48c4Sopenharmony_ci /* Mnemonic. */ 716da0c48c4Sopenharmony_ci 717da0c48c4Sopenharmony_ci if (unlikely (instrtab[cnt].mnemonic == MNE_INVALID)) 718da0c48c4Sopenharmony_ci { 719da0c48c4Sopenharmony_ci switch (*data) 720da0c48c4Sopenharmony_ci { 721da0c48c4Sopenharmony_ci#ifdef X86_64 722da0c48c4Sopenharmony_ci case 0x90: 723da0c48c4Sopenharmony_ci if (prefixes & has_rex_b) 724da0c48c4Sopenharmony_ci goto not; 725da0c48c4Sopenharmony_ci str = "nop"; 726da0c48c4Sopenharmony_ci break; 727da0c48c4Sopenharmony_ci#endif 728da0c48c4Sopenharmony_ci 729da0c48c4Sopenharmony_ci case 0x98: 730da0c48c4Sopenharmony_ci#ifdef X86_64 731da0c48c4Sopenharmony_ci if (prefixes == (has_rex_w | has_rex)) 732da0c48c4Sopenharmony_ci { 733da0c48c4Sopenharmony_ci str = "cltq"; 734da0c48c4Sopenharmony_ci break; 735da0c48c4Sopenharmony_ci } 736da0c48c4Sopenharmony_ci#endif 737da0c48c4Sopenharmony_ci if (prefixes & ~has_data16) 738da0c48c4Sopenharmony_ci goto print_prefix; 739da0c48c4Sopenharmony_ci str = prefixes & has_data16 ? "cbtw" : "cwtl"; 740da0c48c4Sopenharmony_ci break; 741da0c48c4Sopenharmony_ci 742da0c48c4Sopenharmony_ci case 0x99: 743da0c48c4Sopenharmony_ci#ifdef X86_64 744da0c48c4Sopenharmony_ci if (prefixes == (has_rex_w | has_rex)) 745da0c48c4Sopenharmony_ci { 746da0c48c4Sopenharmony_ci str = "cqto"; 747da0c48c4Sopenharmony_ci break; 748da0c48c4Sopenharmony_ci } 749da0c48c4Sopenharmony_ci#endif 750da0c48c4Sopenharmony_ci if (prefixes & ~has_data16) 751da0c48c4Sopenharmony_ci goto print_prefix; 752da0c48c4Sopenharmony_ci str = prefixes & has_data16 ? "cwtd" : "cltd"; 753da0c48c4Sopenharmony_ci break; 754da0c48c4Sopenharmony_ci 755da0c48c4Sopenharmony_ci case 0xe3: 756da0c48c4Sopenharmony_ci if (prefixes & ~has_addr16) 757da0c48c4Sopenharmony_ci goto print_prefix; 758da0c48c4Sopenharmony_ci#ifdef X86_64 759da0c48c4Sopenharmony_ci str = prefixes & has_addr16 ? "jecxz" : "jrcxz"; 760da0c48c4Sopenharmony_ci#else 761da0c48c4Sopenharmony_ci str = prefixes & has_addr16 ? "jcxz" : "jecxz"; 762da0c48c4Sopenharmony_ci#endif 763da0c48c4Sopenharmony_ci break; 764da0c48c4Sopenharmony_ci 765da0c48c4Sopenharmony_ci case 0x0f: 766da0c48c4Sopenharmony_ci if (data[1] == 0x0f) 767da0c48c4Sopenharmony_ci { 768da0c48c4Sopenharmony_ci /* AMD 3DNOW. We need one more byte. */ 769da0c48c4Sopenharmony_ci if (param_start >= end) 770da0c48c4Sopenharmony_ci goto not; 771da0c48c4Sopenharmony_ci if (*param_start < AMD3DNOW_LOW_IDX 772da0c48c4Sopenharmony_ci || *param_start > AMD3DNOW_HIGH_IDX) 773da0c48c4Sopenharmony_ci goto not; 774da0c48c4Sopenharmony_ci unsigned int idx 775da0c48c4Sopenharmony_ci = amd3dnow[AMD3DNOW_IDX (*param_start)]; 776da0c48c4Sopenharmony_ci if (idx == 0) 777da0c48c4Sopenharmony_ci goto not; 778da0c48c4Sopenharmony_ci str = amd3dnowstr + idx - 1; 779da0c48c4Sopenharmony_ci /* Eat the immediate byte indicating the 780da0c48c4Sopenharmony_ci operation. */ 781da0c48c4Sopenharmony_ci ++param_start; 782da0c48c4Sopenharmony_ci break; 783da0c48c4Sopenharmony_ci } 784da0c48c4Sopenharmony_ci#ifdef X86_64 785da0c48c4Sopenharmony_ci if (data[1] == 0xc7) 786da0c48c4Sopenharmony_ci { 787da0c48c4Sopenharmony_ci str = ((prefixes & has_rex_w) 788da0c48c4Sopenharmony_ci ? "cmpxchg16b" : "cmpxchg8b"); 789da0c48c4Sopenharmony_ci break; 790da0c48c4Sopenharmony_ci } 791da0c48c4Sopenharmony_ci#endif 792da0c48c4Sopenharmony_ci if (data[1] == 0xc2) 793da0c48c4Sopenharmony_ci { 794da0c48c4Sopenharmony_ci if (param_start >= end) 795da0c48c4Sopenharmony_ci goto not; 796da0c48c4Sopenharmony_ci if (*param_start > 7) 797da0c48c4Sopenharmony_ci goto not; 798da0c48c4Sopenharmony_ci static const char cmpops[][9] = 799da0c48c4Sopenharmony_ci { 800da0c48c4Sopenharmony_ci [0] = "cmpeq", 801da0c48c4Sopenharmony_ci [1] = "cmplt", 802da0c48c4Sopenharmony_ci [2] = "cmple", 803da0c48c4Sopenharmony_ci [3] = "cmpunord", 804da0c48c4Sopenharmony_ci [4] = "cmpneq", 805da0c48c4Sopenharmony_ci [5] = "cmpnlt", 806da0c48c4Sopenharmony_ci [6] = "cmpnle", 807da0c48c4Sopenharmony_ci [7] = "cmpord" 808da0c48c4Sopenharmony_ci }; 809da0c48c4Sopenharmony_ci char *cp = stpcpy (mnebuf, cmpops[*param_start]); 810da0c48c4Sopenharmony_ci if (correct_prefix & (has_rep | has_repne)) 811da0c48c4Sopenharmony_ci *cp++ = 's'; 812da0c48c4Sopenharmony_ci else 813da0c48c4Sopenharmony_ci *cp++ = 'p'; 814da0c48c4Sopenharmony_ci if (correct_prefix & (has_data16 | has_repne)) 815da0c48c4Sopenharmony_ci *cp++ = 'd'; 816da0c48c4Sopenharmony_ci else 817da0c48c4Sopenharmony_ci *cp++ = 's'; 818da0c48c4Sopenharmony_ci *cp = '\0'; 819da0c48c4Sopenharmony_ci str = mnebuf; 820da0c48c4Sopenharmony_ci /* Eat the immediate byte indicating the 821da0c48c4Sopenharmony_ci operation. */ 822da0c48c4Sopenharmony_ci ++param_start; 823da0c48c4Sopenharmony_ci break; 824da0c48c4Sopenharmony_ci } 825da0c48c4Sopenharmony_ci FALLTHROUGH; 826da0c48c4Sopenharmony_ci default: 827da0c48c4Sopenharmony_ci str = "INVALID not handled"; 828da0c48c4Sopenharmony_ci break; 829da0c48c4Sopenharmony_ci } 830da0c48c4Sopenharmony_ci } 831da0c48c4Sopenharmony_ci else 832da0c48c4Sopenharmony_ci str = mnestr.str + mneidx[instrtab[cnt].mnemonic]; 833da0c48c4Sopenharmony_ci 834da0c48c4Sopenharmony_ci if (deferred_start != NULL) 835da0c48c4Sopenharmony_ci { 836da0c48c4Sopenharmony_ci ADD_NSTRING (deferred_start, deferred_len); 837da0c48c4Sopenharmony_ci non_printing += deferred_len; 838da0c48c4Sopenharmony_ci } 839da0c48c4Sopenharmony_ci 840da0c48c4Sopenharmony_ci ADD_STRING (str); 841da0c48c4Sopenharmony_ci 842da0c48c4Sopenharmony_ci switch (instrtab[cnt].suffix) 843da0c48c4Sopenharmony_ci { 844da0c48c4Sopenharmony_ci case suffix_none: 845da0c48c4Sopenharmony_ci break; 846da0c48c4Sopenharmony_ci 847da0c48c4Sopenharmony_ci case suffix_w: 848da0c48c4Sopenharmony_ci if ((codep[-1] & 0xc0) != 0xc0) 849da0c48c4Sopenharmony_ci { 850da0c48c4Sopenharmony_ci char ch; 851da0c48c4Sopenharmony_ci 852da0c48c4Sopenharmony_ci if (data[0] & 1) 853da0c48c4Sopenharmony_ci { 854da0c48c4Sopenharmony_ci if (prefixes & has_data16) 855da0c48c4Sopenharmony_ci ch = 'w'; 856da0c48c4Sopenharmony_ci#ifdef X86_64 857da0c48c4Sopenharmony_ci else if (prefixes & has_rex_w) 858da0c48c4Sopenharmony_ci ch = 'q'; 859da0c48c4Sopenharmony_ci#endif 860da0c48c4Sopenharmony_ci else 861da0c48c4Sopenharmony_ci ch = 'l'; 862da0c48c4Sopenharmony_ci } 863da0c48c4Sopenharmony_ci else 864da0c48c4Sopenharmony_ci ch = 'b'; 865da0c48c4Sopenharmony_ci 866da0c48c4Sopenharmony_ci ADD_CHAR (ch); 867da0c48c4Sopenharmony_ci } 868da0c48c4Sopenharmony_ci break; 869da0c48c4Sopenharmony_ci 870da0c48c4Sopenharmony_ci case suffix_w0: 871da0c48c4Sopenharmony_ci if ((codep[-1] & 0xc0) != 0xc0) 872da0c48c4Sopenharmony_ci ADD_CHAR ('l'); 873da0c48c4Sopenharmony_ci break; 874da0c48c4Sopenharmony_ci 875da0c48c4Sopenharmony_ci case suffix_w1: 876da0c48c4Sopenharmony_ci if ((data[0] & 0x4) == 0) 877da0c48c4Sopenharmony_ci ADD_CHAR ('l'); 878da0c48c4Sopenharmony_ci break; 879da0c48c4Sopenharmony_ci 880da0c48c4Sopenharmony_ci case suffix_W: 881da0c48c4Sopenharmony_ci if (prefixes & has_data16) 882da0c48c4Sopenharmony_ci { 883da0c48c4Sopenharmony_ci ADD_CHAR ('w'); 884da0c48c4Sopenharmony_ci prefixes &= ~has_data16; 885da0c48c4Sopenharmony_ci } 886da0c48c4Sopenharmony_ci#ifdef X86_64 887da0c48c4Sopenharmony_ci else 888da0c48c4Sopenharmony_ci ADD_CHAR ('q'); 889da0c48c4Sopenharmony_ci#endif 890da0c48c4Sopenharmony_ci break; 891da0c48c4Sopenharmony_ci 892da0c48c4Sopenharmony_ci case suffix_W1: 893da0c48c4Sopenharmony_ci if (prefixes & has_data16) 894da0c48c4Sopenharmony_ci { 895da0c48c4Sopenharmony_ci ADD_CHAR ('w'); 896da0c48c4Sopenharmony_ci prefixes &= ~has_data16; 897da0c48c4Sopenharmony_ci } 898da0c48c4Sopenharmony_ci#ifdef X86_64 899da0c48c4Sopenharmony_ci else if (prefixes & has_rex_w) 900da0c48c4Sopenharmony_ci ADD_CHAR ('q'); 901da0c48c4Sopenharmony_ci#endif 902da0c48c4Sopenharmony_ci break; 903da0c48c4Sopenharmony_ci 904da0c48c4Sopenharmony_ci case suffix_tttn:; 905da0c48c4Sopenharmony_ci static const char tttn[16][3] = 906da0c48c4Sopenharmony_ci { 907da0c48c4Sopenharmony_ci "o", "no", "b", "ae", "e", "ne", "be", "a", 908da0c48c4Sopenharmony_ci "s", "ns", "p", "np", "l", "ge", "le", "g" 909da0c48c4Sopenharmony_ci }; 910da0c48c4Sopenharmony_ci ADD_STRING (tttn[codep[-1 - instrtab[cnt].modrm] & 0x0f]); 911da0c48c4Sopenharmony_ci break; 912da0c48c4Sopenharmony_ci 913da0c48c4Sopenharmony_ci case suffix_D: 914da0c48c4Sopenharmony_ci if ((codep[-1] & 0xc0) != 0xc0) 915da0c48c4Sopenharmony_ci ADD_CHAR ((data[0] & 0x04) == 0 ? 's' : 'l'); 916da0c48c4Sopenharmony_ci break; 917da0c48c4Sopenharmony_ci 918da0c48c4Sopenharmony_ci default: 919da0c48c4Sopenharmony_ci printf("unknown suffix %d\n", instrtab[cnt].suffix); 920da0c48c4Sopenharmony_ci abort (); 921da0c48c4Sopenharmony_ci } 922da0c48c4Sopenharmony_ci 923da0c48c4Sopenharmony_ci if (deferred_start != NULL) 924da0c48c4Sopenharmony_ci { 925da0c48c4Sopenharmony_ci ADD_STRING (color_off); 926da0c48c4Sopenharmony_ci non_printing += strlen (color_off); 927da0c48c4Sopenharmony_ci } 928da0c48c4Sopenharmony_ci 929da0c48c4Sopenharmony_ci string_end_idx = bufcnt; 930da0c48c4Sopenharmony_ci break; 931da0c48c4Sopenharmony_ci 932da0c48c4Sopenharmony_ci case 'o': 933da0c48c4Sopenharmony_ci if (prec == 1 && instrtab[cnt].fct1 != 0) 934da0c48c4Sopenharmony_ci { 935da0c48c4Sopenharmony_ci /* First parameter. */ 936da0c48c4Sopenharmony_ci if (deferred_start != NULL) 937da0c48c4Sopenharmony_ci { 938da0c48c4Sopenharmony_ci ADD_NSTRING (deferred_start, deferred_len); 939da0c48c4Sopenharmony_ci non_printing += deferred_len; 940da0c48c4Sopenharmony_ci } 941da0c48c4Sopenharmony_ci 942da0c48c4Sopenharmony_ci if (instrtab[cnt].str1 != 0) 943da0c48c4Sopenharmony_ci ADD_STRING (op1_str 944da0c48c4Sopenharmony_ci + op1_str_idx[instrtab[cnt].str1 - 1]); 945da0c48c4Sopenharmony_ci 946da0c48c4Sopenharmony_ci output_data.opoff1 = (instrtab[cnt].off1_1 947da0c48c4Sopenharmony_ci + OFF1_1_BIAS - opoff); 948da0c48c4Sopenharmony_ci output_data.opoff2 = (instrtab[cnt].off1_2 949da0c48c4Sopenharmony_ci + OFF1_2_BIAS - opoff); 950da0c48c4Sopenharmony_ci output_data.opoff3 = (instrtab[cnt].off1_3 951da0c48c4Sopenharmony_ci + OFF1_3_BIAS - opoff); 952da0c48c4Sopenharmony_ci int r = op1_fct[instrtab[cnt].fct1] (&output_data); 953da0c48c4Sopenharmony_ci if (r < 0) 954da0c48c4Sopenharmony_ci goto not; 955da0c48c4Sopenharmony_ci if (r > 0) 956da0c48c4Sopenharmony_ci goto enomem; 957da0c48c4Sopenharmony_ci 958da0c48c4Sopenharmony_ci if (deferred_start != NULL) 959da0c48c4Sopenharmony_ci { 960da0c48c4Sopenharmony_ci ADD_STRING (color_off); 961da0c48c4Sopenharmony_ci non_printing += strlen (color_off); 962da0c48c4Sopenharmony_ci } 963da0c48c4Sopenharmony_ci 964da0c48c4Sopenharmony_ci string_end_idx = bufcnt; 965da0c48c4Sopenharmony_ci } 966da0c48c4Sopenharmony_ci else if (prec == 2 && instrtab[cnt].fct2 != 0) 967da0c48c4Sopenharmony_ci { 968da0c48c4Sopenharmony_ci /* Second parameter. */ 969da0c48c4Sopenharmony_ci if (deferred_start != NULL) 970da0c48c4Sopenharmony_ci { 971da0c48c4Sopenharmony_ci ADD_NSTRING (deferred_start, deferred_len); 972da0c48c4Sopenharmony_ci non_printing += deferred_len; 973da0c48c4Sopenharmony_ci } 974da0c48c4Sopenharmony_ci 975da0c48c4Sopenharmony_ci if (instrtab[cnt].str2 != 0) 976da0c48c4Sopenharmony_ci ADD_STRING (op2_str 977da0c48c4Sopenharmony_ci + op2_str_idx[instrtab[cnt].str2 - 1]); 978da0c48c4Sopenharmony_ci 979da0c48c4Sopenharmony_ci output_data.opoff1 = (instrtab[cnt].off2_1 980da0c48c4Sopenharmony_ci + OFF2_1_BIAS - opoff); 981da0c48c4Sopenharmony_ci output_data.opoff2 = (instrtab[cnt].off2_2 982da0c48c4Sopenharmony_ci + OFF2_2_BIAS - opoff); 983da0c48c4Sopenharmony_ci output_data.opoff3 = (instrtab[cnt].off2_3 984da0c48c4Sopenharmony_ci + OFF2_3_BIAS - opoff); 985da0c48c4Sopenharmony_ci int r = op2_fct[instrtab[cnt].fct2] (&output_data); 986da0c48c4Sopenharmony_ci if (r < 0) 987da0c48c4Sopenharmony_ci goto not; 988da0c48c4Sopenharmony_ci if (r > 0) 989da0c48c4Sopenharmony_ci goto enomem; 990da0c48c4Sopenharmony_ci 991da0c48c4Sopenharmony_ci if (deferred_start != NULL) 992da0c48c4Sopenharmony_ci { 993da0c48c4Sopenharmony_ci ADD_STRING (color_off); 994da0c48c4Sopenharmony_ci non_printing += strlen (color_off); 995da0c48c4Sopenharmony_ci } 996da0c48c4Sopenharmony_ci 997da0c48c4Sopenharmony_ci string_end_idx = bufcnt; 998da0c48c4Sopenharmony_ci } 999da0c48c4Sopenharmony_ci else if (prec == 3 && instrtab[cnt].fct3 != 0) 1000da0c48c4Sopenharmony_ci { 1001da0c48c4Sopenharmony_ci /* Third parameter. */ 1002da0c48c4Sopenharmony_ci if (deferred_start != NULL) 1003da0c48c4Sopenharmony_ci { 1004da0c48c4Sopenharmony_ci ADD_NSTRING (deferred_start, deferred_len); 1005da0c48c4Sopenharmony_ci non_printing += deferred_len; 1006da0c48c4Sopenharmony_ci } 1007da0c48c4Sopenharmony_ci 1008da0c48c4Sopenharmony_ci if (instrtab[cnt].str3 != 0) 1009da0c48c4Sopenharmony_ci ADD_STRING (op3_str 1010da0c48c4Sopenharmony_ci + op3_str_idx[instrtab[cnt].str3 - 1]); 1011da0c48c4Sopenharmony_ci 1012da0c48c4Sopenharmony_ci output_data.opoff1 = (instrtab[cnt].off3_1 1013da0c48c4Sopenharmony_ci + OFF3_1_BIAS - opoff); 1014da0c48c4Sopenharmony_ci output_data.opoff2 = (instrtab[cnt].off3_2 1015da0c48c4Sopenharmony_ci + OFF3_2_BIAS - opoff); 1016da0c48c4Sopenharmony_ci#ifdef OFF3_3_BITS 1017da0c48c4Sopenharmony_ci output_data.opoff3 = (instrtab[cnt].off3_3 1018da0c48c4Sopenharmony_ci + OFF3_3_BIAS - opoff); 1019da0c48c4Sopenharmony_ci#else 1020da0c48c4Sopenharmony_ci output_data.opoff3 = 0; 1021da0c48c4Sopenharmony_ci#endif 1022da0c48c4Sopenharmony_ci int r = op3_fct[instrtab[cnt].fct3] (&output_data); 1023da0c48c4Sopenharmony_ci if (r < 0) 1024da0c48c4Sopenharmony_ci goto not; 1025da0c48c4Sopenharmony_ci if (r > 0) 1026da0c48c4Sopenharmony_ci goto enomem; 1027da0c48c4Sopenharmony_ci 1028da0c48c4Sopenharmony_ci if (deferred_start != NULL) 1029da0c48c4Sopenharmony_ci { 1030da0c48c4Sopenharmony_ci ADD_STRING (color_off); 1031da0c48c4Sopenharmony_ci non_printing += strlen (color_off); 1032da0c48c4Sopenharmony_ci } 1033da0c48c4Sopenharmony_ci 1034da0c48c4Sopenharmony_ci string_end_idx = bufcnt; 1035da0c48c4Sopenharmony_ci } 1036da0c48c4Sopenharmony_ci else 1037da0c48c4Sopenharmony_ci start_idx = bufcnt = string_end_idx; 1038da0c48c4Sopenharmony_ci break; 1039da0c48c4Sopenharmony_ci 1040da0c48c4Sopenharmony_ci case 'e': 1041da0c48c4Sopenharmony_ci string_end_idx = bufcnt; 1042da0c48c4Sopenharmony_ci break; 1043da0c48c4Sopenharmony_ci 1044da0c48c4Sopenharmony_ci case 'a': 1045da0c48c4Sopenharmony_ci /* Pad to requested column. */ 1046da0c48c4Sopenharmony_ci while (bufcnt - non_printing < (size_t) width) 1047da0c48c4Sopenharmony_ci ADD_CHAR (' '); 1048da0c48c4Sopenharmony_ci width = 0; 1049da0c48c4Sopenharmony_ci break; 1050da0c48c4Sopenharmony_ci 1051da0c48c4Sopenharmony_ci case 'l': 1052da0c48c4Sopenharmony_ci if (deferred_start != NULL) 1053da0c48c4Sopenharmony_ci { 1054da0c48c4Sopenharmony_ci ADD_NSTRING (deferred_start, deferred_len); 1055da0c48c4Sopenharmony_ci non_printing += deferred_len; 1056da0c48c4Sopenharmony_ci } 1057da0c48c4Sopenharmony_ci 1058da0c48c4Sopenharmony_ci if (output_data.labelbuf != NULL 1059da0c48c4Sopenharmony_ci && output_data.labelbuf[0] != '\0') 1060da0c48c4Sopenharmony_ci { 1061da0c48c4Sopenharmony_ci ADD_STRING (output_data.labelbuf); 1062da0c48c4Sopenharmony_ci output_data.labelbuf[0] = '\0'; 1063da0c48c4Sopenharmony_ci string_end_idx = bufcnt; 1064da0c48c4Sopenharmony_ci } 1065da0c48c4Sopenharmony_ci else if (output_data.symaddr_use != addr_none) 1066da0c48c4Sopenharmony_ci { 1067da0c48c4Sopenharmony_ci GElf_Addr symaddr = output_data.symaddr; 1068da0c48c4Sopenharmony_ci if (output_data.symaddr_use >= addr_rel_symbolic) 1069da0c48c4Sopenharmony_ci symaddr += addr + param_start - begin; 1070da0c48c4Sopenharmony_ci 1071da0c48c4Sopenharmony_ci // XXX Lookup symbol based on symaddr 1072da0c48c4Sopenharmony_ci const char *symstr = NULL; 1073da0c48c4Sopenharmony_ci if (symcb != NULL 1074da0c48c4Sopenharmony_ci && symcb (0 /* XXX */, 0 /* XXX */, symaddr, 1075da0c48c4Sopenharmony_ci &output_data.labelbuf, 1076da0c48c4Sopenharmony_ci &output_data.labelbufsize, symcbarg) == 0) 1077da0c48c4Sopenharmony_ci symstr = output_data.labelbuf; 1078da0c48c4Sopenharmony_ci 1079da0c48c4Sopenharmony_ci size_t bufavail = bufsize - bufcnt; 1080da0c48c4Sopenharmony_ci int r = 0; 1081da0c48c4Sopenharmony_ci if (symstr != NULL) 1082da0c48c4Sopenharmony_ci r = snprintf (&buf[bufcnt], bufavail, "# <%s>", 1083da0c48c4Sopenharmony_ci symstr); 1084da0c48c4Sopenharmony_ci else if (output_data.symaddr_use == addr_abs_always 1085da0c48c4Sopenharmony_ci || output_data.symaddr_use == addr_rel_always) 1086da0c48c4Sopenharmony_ci r = snprintf (&buf[bufcnt], bufavail, "# %#" PRIx64, 1087da0c48c4Sopenharmony_ci (uint64_t) symaddr); 1088da0c48c4Sopenharmony_ci 1089da0c48c4Sopenharmony_ci assert (r >= 0); 1090da0c48c4Sopenharmony_ci if ((size_t) r >= bufavail) 1091da0c48c4Sopenharmony_ci goto enomem; 1092da0c48c4Sopenharmony_ci bufcnt += r; 1093da0c48c4Sopenharmony_ci string_end_idx = bufcnt; 1094da0c48c4Sopenharmony_ci 1095da0c48c4Sopenharmony_ci output_data.symaddr_use = addr_none; 1096da0c48c4Sopenharmony_ci } 1097da0c48c4Sopenharmony_ci if (deferred_start != NULL) 1098da0c48c4Sopenharmony_ci { 1099da0c48c4Sopenharmony_ci ADD_STRING (color_off); 1100da0c48c4Sopenharmony_ci non_printing += strlen (color_off); 1101da0c48c4Sopenharmony_ci } 1102da0c48c4Sopenharmony_ci break; 1103da0c48c4Sopenharmony_ci 1104da0c48c4Sopenharmony_ci default: 1105da0c48c4Sopenharmony_ci abort (); 1106da0c48c4Sopenharmony_ci } 1107da0c48c4Sopenharmony_ci 1108da0c48c4Sopenharmony_ci deferred_start = NULL; 1109da0c48c4Sopenharmony_ci 1110da0c48c4Sopenharmony_ci /* Pad according to the specified width. */ 1111da0c48c4Sopenharmony_ci while (bufcnt + prefix_size - non_printing < start_idx + width) 1112da0c48c4Sopenharmony_ci ADD_CHAR (' '); 1113da0c48c4Sopenharmony_ci prefix_size = 0; 1114da0c48c4Sopenharmony_ci } 1115da0c48c4Sopenharmony_ci 1116da0c48c4Sopenharmony_ci if ((prefixes & SEGMENT_PREFIXES) != 0) 1117da0c48c4Sopenharmony_ci goto print_prefix; 1118da0c48c4Sopenharmony_ci 1119da0c48c4Sopenharmony_ci assert (string_end_idx != ~0ul); 1120da0c48c4Sopenharmony_ci bufcnt = string_end_idx; 1121da0c48c4Sopenharmony_ci 1122da0c48c4Sopenharmony_ci addr += param_start - begin; 1123da0c48c4Sopenharmony_ci data = param_start; 1124da0c48c4Sopenharmony_ci 1125da0c48c4Sopenharmony_ci goto out; 1126da0c48c4Sopenharmony_ci } 1127da0c48c4Sopenharmony_ci 1128da0c48c4Sopenharmony_ci /* Invalid (or at least unhandled) opcode. */ 1129da0c48c4Sopenharmony_ci invalid_op: 1130da0c48c4Sopenharmony_ci if (prefixes != 0) 1131da0c48c4Sopenharmony_ci goto print_prefix; 1132da0c48c4Sopenharmony_ci /* Make sure we get past the unrecognized opcode if we haven't yet. */ 1133da0c48c4Sopenharmony_ci if (*startp == data) 1134da0c48c4Sopenharmony_ci ++data; 1135da0c48c4Sopenharmony_ci ADD_STRING ("(bad)"); 1136da0c48c4Sopenharmony_ci addr += data - begin; 1137da0c48c4Sopenharmony_ci 1138da0c48c4Sopenharmony_ci out: 1139da0c48c4Sopenharmony_ci if (bufcnt == bufsize) 1140da0c48c4Sopenharmony_ci goto enomem; 1141da0c48c4Sopenharmony_ci buf[bufcnt] = '\0'; 1142da0c48c4Sopenharmony_ci 1143da0c48c4Sopenharmony_ci *startp = data; 1144da0c48c4Sopenharmony_ci retval = outcb (buf, bufcnt, outcbarg); 1145da0c48c4Sopenharmony_ci if (retval != 0) 1146da0c48c4Sopenharmony_ci goto do_ret; 1147da0c48c4Sopenharmony_ci } 1148da0c48c4Sopenharmony_ci 1149da0c48c4Sopenharmony_ci do_ret: 1150da0c48c4Sopenharmony_ci free (output_data.labelbuf); 1151da0c48c4Sopenharmony_ci if (buf != initbuf) 1152da0c48c4Sopenharmony_ci free (buf); 1153da0c48c4Sopenharmony_ci 1154da0c48c4Sopenharmony_ci return retval; 1155da0c48c4Sopenharmony_ci} 1156