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 = &param_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