Blame libcpu/riscv_disasm.c

Packit Service 97d2fb
/* Disassembler for RISC-V.
Packit Service 97d2fb
   Copyright (C) 2019 Red Hat, Inc.
Packit Service 97d2fb
   This file is part of elfutils.
Packit Service 97d2fb
   Written by Ulrich Drepper <drepper@redhat.com>, 2019.
Packit Service 97d2fb
Packit Service 97d2fb
   This file is free software; you can redistribute it and/or modify
Packit Service 97d2fb
   it under the terms of either
Packit Service 97d2fb
Packit Service 97d2fb
     * the GNU Lesser General Public License as published by the Free
Packit Service 97d2fb
       Software Foundation; either version 3 of the License, or (at
Packit Service 97d2fb
       your option) any later version
Packit Service 97d2fb
Packit Service 97d2fb
   or
Packit Service 97d2fb
Packit Service 97d2fb
     * the GNU General Public License as published by the Free
Packit Service 97d2fb
       Software Foundation; either version 2 of the License, or (at
Packit Service 97d2fb
       your option) any later version
Packit Service 97d2fb
Packit Service 97d2fb
   or both in parallel, as here.
Packit Service 97d2fb
Packit Service 97d2fb
   elfutils is distributed in the hope that it will be useful, but
Packit Service 97d2fb
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 97d2fb
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 97d2fb
   General Public License for more details.
Packit Service 97d2fb
Packit Service 97d2fb
   You should have received copies of the GNU General Public License and
Packit Service 97d2fb
   the GNU Lesser General Public License along with this program.  If
Packit Service 97d2fb
   not, see <http://www.gnu.org/licenses/>.  */
Packit Service 97d2fb
Packit Service 97d2fb
#ifdef HAVE_CONFIG_H
Packit Service 97d2fb
# include <config.h>
Packit Service 97d2fb
#endif
Packit Service 97d2fb
Packit Service 97d2fb
#include <assert.h>
Packit Service 97d2fb
#include <ctype.h>
Packit Service 97d2fb
#include <errno.h>
Packit Service 97d2fb
#include <inttypes.h>
Packit Service 97d2fb
#include <stdio.h>
Packit Service 97d2fb
#include <stdlib.h>
Packit Service 97d2fb
#include <string.h>
Packit Service 97d2fb
Packit Service 97d2fb
#include "../libebl/libeblP.h"
Packit Service 97d2fb
Packit Service 97d2fb
#define MACHINE_ENCODING __LITTLE_ENDIAN
Packit Service 97d2fb
#include "memory-access.h"
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
#define ADD_CHAR(ch) \
Packit Service 97d2fb
  do {									      \
Packit Service 97d2fb
    if (unlikely (bufcnt == bufsize))					      \
Packit Service 97d2fb
      goto enomem;							      \
Packit Service 97d2fb
    buf[bufcnt++] = (ch);						      \
Packit Service 97d2fb
  } while (0)
Packit Service 97d2fb
Packit Service 97d2fb
#define ADD_STRING(str) \
Packit Service 97d2fb
  do {									      \
Packit Service 97d2fb
    const char *_str0 = (str);						      \
Packit Service 97d2fb
    size_t _len0 = strlen (_str0);					      \
Packit Service 97d2fb
    ADD_NSTRING (_str0, _len0);						      \
Packit Service 97d2fb
  } while (0)
Packit Service 97d2fb
Packit Service 97d2fb
#define ADD_NSTRING(str, len) \
Packit Service 97d2fb
  do {									      \
Packit Service 97d2fb
    const char *_str = (str);						      \
Packit Service 97d2fb
    size_t _len = (len);						      \
Packit Service 97d2fb
    if (unlikely (bufcnt + _len > bufsize))				      \
Packit Service 97d2fb
      goto enomem;							      \
Packit Service 97d2fb
    memcpy (buf + bufcnt, _str, _len);					      \
Packit Service 97d2fb
    bufcnt += _len;							      \
Packit Service 97d2fb
  } while (0)
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
static const char *regnames[32] =
Packit Service 97d2fb
  {
Packit Service 97d2fb
    "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
Packit Service 97d2fb
    "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
Packit Service 97d2fb
    "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
Packit Service 97d2fb
    "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"
Packit Service 97d2fb
  };
Packit Service 97d2fb
#define REG(nr) ((char *) regnames[nr])
Packit Service 97d2fb
#define REGP(nr) REG (8 + (nr))
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
static const char *fregnames[32] =
Packit Service 97d2fb
  {
Packit Service 97d2fb
    "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
Packit Service 97d2fb
    "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
Packit Service 97d2fb
    "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
Packit Service 97d2fb
    "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11"
Packit Service 97d2fb
  };
Packit Service 97d2fb
#define FREG(nr) ((char *) fregnames[nr])
Packit Service 97d2fb
#define FREGP(nr) FREG (8 + (nr))
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
struct known_csrs
Packit Service 97d2fb
  {
Packit Service 97d2fb
    uint16_t nr;
Packit Service 97d2fb
    const char *name;
Packit Service 97d2fb
  };
Packit Service 97d2fb
Packit Service 97d2fb
static int compare_csr (const void *a, const void *b)
Packit Service 97d2fb
{
Packit Service 97d2fb
  const struct known_csrs *ka = (const struct known_csrs *) a;
Packit Service 97d2fb
  const struct known_csrs *kb = (const struct known_csrs *) b;
Packit Service 97d2fb
  if (ka->nr < kb->nr)
Packit Service 97d2fb
    return -1;
Packit Service 97d2fb
  return ka->nr == kb->nr ? 0 : 1;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
int
Packit Service 97d2fb
riscv_disasm (Ebl *ebl,
Packit Service 97d2fb
	      const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
Packit Service 97d2fb
	      const char *fmt, DisasmOutputCB_t outcb,
Packit Service 97d2fb
	      DisasmGetSymCB_t symcb __attribute__((unused)),
Packit Service 97d2fb
	      void *outcbarg, void *symcbarg __attribute__((unused)))
Packit Service 97d2fb
{
Packit Service 97d2fb
  const char *const save_fmt = fmt;
Packit Service 97d2fb
Packit Service 97d2fb
#define BUFSIZE 512
Packit Service 97d2fb
  char initbuf[BUFSIZE];
Packit Service 97d2fb
  size_t bufcnt;
Packit Service 97d2fb
  size_t bufsize = BUFSIZE;
Packit Service 97d2fb
  char *buf = initbuf;
Packit Service 97d2fb
Packit Service 97d2fb
  int retval = 0;
Packit Service 97d2fb
  while (1)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      const uint8_t *data = *startp;
Packit Service 97d2fb
      assert (data <= end);
Packit Service 97d2fb
      if (data + 2 > end)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  if (data != end)
Packit Service 97d2fb
	    retval = -1;
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      uint16_t first = read_2ubyte_unaligned (data);
Packit Service 97d2fb
Packit Service 97d2fb
      // Determine length.
Packit Service 97d2fb
      size_t length;
Packit Service 97d2fb
      if ((first & 0x3) != 0x3)
Packit Service 97d2fb
	length = 2;
Packit Service 97d2fb
      else if ((first & 0x1f) != 0x1f)
Packit Service 97d2fb
	length = 4;
Packit Service 97d2fb
      else if ((first & 0x3f) != 0x3f)
Packit Service 97d2fb
	length = 6;
Packit Service 97d2fb
      else if ((first & 0x7f) != 0x7f)
Packit Service 97d2fb
	length = 8;
Packit Service 97d2fb
      else
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  uint16_t nnn = (first >> 12) & 0x7;
Packit Service 97d2fb
	  if (nnn != 0x7)
Packit Service 97d2fb
	    length = 10 + 2 * nnn;
Packit Service 97d2fb
	  else
Packit Service 97d2fb
	    // This is invalid as of the RISC-V spec on 2019-06-21.
Packit Service 97d2fb
	    // The instruction is at least 192 bits in size so use
Packit Service 97d2fb
	    // this minimum size.
Packit Service 97d2fb
	    length = 24;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      if (data + length > end)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  retval = -1;
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      char *mne = NULL;
Packit Service 97d2fb
      char mnebuf[32];
Packit Service 97d2fb
      char *op[5] = { NULL, NULL, NULL, NULL, NULL };
Packit Service 97d2fb
      char immbuf[32];
Packit Service 97d2fb
      size_t len;
Packit Service 97d2fb
      char *strp = NULL;
Packit Service 97d2fb
      char addrbuf[32];
Packit Service 97d2fb
      bufcnt = 0;
Packit Service 97d2fb
      int64_t opaddr;
Packit Service 97d2fb
      if (length == 2)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  size_t idx = (first >> 13) * 3 + (first & 0x3);
Packit Service 97d2fb
	  switch (idx)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	    uint16_t rd;
Packit Service 97d2fb
	    uint16_t rs1;
Packit Service 97d2fb
	    uint16_t rs2;
Packit Service 97d2fb
Packit Service 97d2fb
	    case 0:
Packit Service 97d2fb
	      if ((first & 0x1fe0) != 0)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = "addi";
Packit Service 97d2fb
		  op[0] = REGP ((first & 0x1c) >> 2);
Packit Service 97d2fb
		  op[1] = REG (2);
Packit Service 97d2fb
		  opaddr = (((first >> 1) & 0x3c0)
Packit Service 97d2fb
			    | ((first >> 7) & 0x30)
Packit Service 97d2fb
			    | ((first >> 2) & 0x8)
Packit Service 97d2fb
			    | ((first >> 4) & 0x4));
Packit Service 97d2fb
		  snprintf (addrbuf, sizeof (addrbuf), "%" PRIu64, opaddr);
Packit Service 97d2fb
		  op[2] = addrbuf;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else if (first == 0)
Packit Service 97d2fb
		mne = "unimp";
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 1:
Packit Service 97d2fb
	      rs1 = (first >> 7) & 0x1f;
Packit Service 97d2fb
	      int16_t nzimm = ((0 - ((first >> 7) & 0x20))
Packit Service 97d2fb
			       | ((first >> 2) & 0x1f));
Packit Service 97d2fb
	      if (rs1 == 0)
Packit Service 97d2fb
	        mne = nzimm == 0 ? "nop" : "c.nop";
Packit Service 97d2fb
	      else
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = nzimm == 0 ? "c.addi" : "addi";
Packit Service 97d2fb
		  op[0] = op[1] = REG (rs1);
Packit Service 97d2fb
		  snprintf (addrbuf, sizeof (addrbuf), "%" PRId16, nzimm);
Packit Service 97d2fb
		  op[2] = addrbuf;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 2:
Packit Service 97d2fb
	      rs1 = (first >> 7) & 0x1f;
Packit Service 97d2fb
	      op[0] = op[1] = REG (rs1);
Packit Service 97d2fb
	      opaddr = ((first >> 7) & 0x20) | ((first >> 2) & 0x1f);
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr);
Packit Service 97d2fb
	      op[2] = addrbuf;
Packit Service 97d2fb
	      mne = rs1 == 0 ? "c.slli" : "slli";
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 3:
Packit Service 97d2fb
	      op[0] = FREGP ((first >> 2) & 0x7);
Packit Service 97d2fb
	      opaddr = ((first << 1) & 0xc0) | ((first >> 7) & 0x38);
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "%" PRIu64 "(%s)",
Packit Service 97d2fb
			opaddr, REGP ((first >> 7) & 0x7));
Packit Service 97d2fb
	      op[1] = addrbuf;
Packit Service 97d2fb
	      mne = "fld";
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 4:
Packit Service 97d2fb
	      if (ebl->class == ELFCLASS32)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = "jal";
Packit Service 97d2fb
		  opaddr = (((first << 3) & 0x20) | ((first >> 2) & 0xe)
Packit Service 97d2fb
			    | ((first << 1) & 0x80) | ((first >> 1) | 0x40)
Packit Service 97d2fb
			    | ((first << 2) & 0x400) | (first & 0xb00)
Packit Service 97d2fb
			    | ((first >> 6) & 0x10));
Packit Service 97d2fb
		  snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr);
Packit Service 97d2fb
		  op[0] = addrbuf;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  int32_t imm = (((UINT32_C (0) - ((first >> 12) & 0x1)) << 5)
Packit Service 97d2fb
				 | ((first >> 2) & 0x1f));
Packit Service 97d2fb
		  uint16_t reg = (first >> 7) & 0x1f;
Packit Service 97d2fb
		  if (reg == 0)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      // Reserved
Packit Service 97d2fb
		      len = snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx16, first);
Packit Service 97d2fb
		      strp = addrbuf;
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      if (imm == 0)
Packit Service 97d2fb
			mne = "sext.w";
Packit Service 97d2fb
		      else
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  mne = "addiw";
Packit Service 97d2fb
			  snprintf (addrbuf, sizeof (addrbuf), "%" PRId32, imm);
Packit Service 97d2fb
			  op[2] = addrbuf;
Packit Service 97d2fb
			}
Packit Service 97d2fb
		      op[0] = op[1] = REG (reg);
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 5:
Packit Service 97d2fb
	      op[0] = FREG ((first >> 7) & 0x1f);
Packit Service 97d2fb
	      opaddr = ((first << 4) & 0x1c0) | ((first >> 7) & 0x20) | ((first >> 2) & 0x18);
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "%" PRIu64 "(%s)", opaddr, REG (2));
Packit Service 97d2fb
	      op[1] = addrbuf;
Packit Service 97d2fb
	      mne = "fld";
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 6:
Packit Service 97d2fb
	    case 18:
Packit Service 97d2fb
	      mne = idx == 6 ? "lw" : "sw";
Packit Service 97d2fb
	      op[0] = REGP ((first >> 2) & 0x7);
Packit Service 97d2fb
	      opaddr = (((first >> 7) & 0x38) | ((first << 1) & 0x40)
Packit Service 97d2fb
			| ((first >> 4) & 0x4));
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)",
Packit Service 97d2fb
			opaddr, REGP ((first >> 7) & 0x7));
Packit Service 97d2fb
	      op[1] = addrbuf;
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 7:
Packit Service 97d2fb
	      mne = (first & 0xf80) == 0 ? "c.li" : "li";
Packit Service 97d2fb
	      op[0] = REG((first >> 7) & 0x1f);
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId16,
Packit Service 97d2fb
			(UINT16_C (0) - ((first >> 7) & 0x20)) | ((first >> 2) & 0x1f));
Packit Service 97d2fb
	      op[1] = addrbuf;
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 8:
Packit Service 97d2fb
	      rd = ((first >> 7) & 0x1f);
Packit Service 97d2fb
	      if (rd == 0)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  len = snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx16, first);
Packit Service 97d2fb
		  strp = addrbuf;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  uint16_t uimm = (((first << 4) & 0xc0)
Packit Service 97d2fb
				   | ((first >> 7) & 0x20)
Packit Service 97d2fb
				   | ((first >> 2) & 0x1c));
Packit Service 97d2fb
		  mne = "lw";
Packit Service 97d2fb
		  op[0] = REG (rd);
Packit Service 97d2fb
		  snprintf (addrbuf, sizeof (addrbuf), "%" PRIu16 "(%s)", uimm, REG (2));
Packit Service 97d2fb
		  op[1] = addrbuf;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 9:
Packit Service 97d2fb
	      if (ebl->class == ELFCLASS32)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = "flw";
Packit Service 97d2fb
		  op[0] = FREGP ((first >> 2) & 0x7);
Packit Service 97d2fb
		  opaddr = (((first << 1) & 0x40)
Packit Service 97d2fb
		            | ((first >> 7) & 0x38)
Packit Service 97d2fb
			    | ((first >> 4) & 0x4));
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = "ld";
Packit Service 97d2fb
		  op[0] = REGP ((first >> 2) & 0x7);
Packit Service 97d2fb
		  opaddr = ((first >> 7) & 0x38) | ((first << 1) & 0xc0);
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)",
Packit Service 97d2fb
			opaddr, REGP ((first >> 7) & 0x7));
Packit Service 97d2fb
	      op[1] = addrbuf;
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 10:
Packit Service 97d2fb
	      if ((first & 0xf80) == (2 << 7))
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = "addi";
Packit Service 97d2fb
		  op[0] = op[1] = REG (2);
Packit Service 97d2fb
		  opaddr = (((first >> 2) & 0x10) | ((first << 3) & 0x20)
Packit Service 97d2fb
			    | ((first << 1) & 0x40) | ((first << 4) & 0x180)
Packit Service 97d2fb
			    | ((UINT64_C (0) - ((first >> 12) & 0x1)) << 9));
Packit Service 97d2fb
		  snprintf (addrbuf, sizeof (addrbuf), "%" PRId64, opaddr);
Packit Service 97d2fb
		  op[2] = addrbuf;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = "lui";
Packit Service 97d2fb
		  op[0] = REG((first & 0xf80) >> 7);
Packit Service 97d2fb
		  opaddr = (((UINT64_C (0) - ((first >> 12) & 0x1)) & ~0x1f)
Packit Service 97d2fb
			    | ((first >> 2) & 0x1f));
Packit Service 97d2fb
		  snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr & 0xfffff);
Packit Service 97d2fb
		  op[1] = addrbuf;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 11:
Packit Service 97d2fb
	      if (ebl->class == ELFCLASS32)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = "flw";
Packit Service 97d2fb
		  op[0] = FREG ((first >> 7) & 0x1f);
Packit Service 97d2fb
		  opaddr = (((first << 4) & 0xc0)
Packit Service 97d2fb
			    | ((first >> 7) & 0x20)
Packit Service 97d2fb
			    | ((first >> 2) & 0x1c));
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = "ld";
Packit Service 97d2fb
		  op[0] = REG ((first >> 7) & 0x1f);
Packit Service 97d2fb
		  opaddr = (((first << 4) & 0x1c0)
Packit Service 97d2fb
			    | ((first >> 7) & 0x20)
Packit Service 97d2fb
			    | ((first >> 2) & 0x18));
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)", opaddr, REG (2));
Packit Service 97d2fb
	      op[1] = addrbuf;
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 13:
Packit Service 97d2fb
	      if ((first & 0xc00) != 0xc00)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  int16_t imm = ((first >> 7) & 0x20) | ((first >> 2) & 0x1f);
Packit Service 97d2fb
		  if ((first & 0xc00) == 0x800)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      imm |= 0 - (imm & 0x20);
Packit Service 97d2fb
		      mne = "andi";
Packit Service 97d2fb
		      snprintf (addrbuf, sizeof (addrbuf), "%" PRId16, imm);
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      if (ebl->class != ELFCLASS32 || imm < 32)
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  mne = (first & 0x400) ? "srai" : "srli";
Packit Service 97d2fb
			  if (imm == 0)
Packit Service 97d2fb
			    {
Packit Service 97d2fb
			      strcpy (stpcpy (mnebuf, "c."), mne);
Packit Service 97d2fb
			      mne = mnebuf;
Packit Service 97d2fb
			    }
Packit Service 97d2fb
			}
Packit Service 97d2fb
		      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx16, imm);
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  op[2] = addrbuf;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  op[2] = REGP ((first >> 2) & 0x7);
Packit Service 97d2fb
		  static const char *const arithmne[8] =
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      "sub", "xor", "or", "and", "subw", "addw", NULL, NULL
Packit Service 97d2fb
		    };
Packit Service 97d2fb
		  mne = (char *) arithmne[((first >> 10) & 0x4) | ((first >> 5) & 0x3)];
Packit Service 97d2fb
		}
Packit Service 97d2fb
		op[0] = op[1] = REGP ((first >> 7) & 0x7);
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 14:
Packit Service 97d2fb
	      rs1 = (first >> 7) & 0x1f;
Packit Service 97d2fb
	      rs2 = (first >> 2) & 0x1f;
Packit Service 97d2fb
	      op[0] = REG (rs1);
Packit Service 97d2fb
	      if ((first & 0x1000) == 0)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  if (rs2 == 0)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      op[1] = NULL;
Packit Service 97d2fb
		      if (rs1 == 1)
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  mne = "ret";
Packit Service 97d2fb
			  op[0] = NULL;
Packit Service 97d2fb
			}
Packit Service 97d2fb
		      else
Packit Service 97d2fb
			mne = "jr";
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      mne = rs1 != 0 ? "mv" : "c.mv";
Packit Service 97d2fb
		      op[1] = REG (rs2);
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  if (rs2 == 0)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      if (rs1 == 0)
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  mne = "ebreak";
Packit Service 97d2fb
			  op[0] = op[1] = NULL;
Packit Service 97d2fb
			}
Packit Service 97d2fb
		      else
Packit Service 97d2fb
			mne = "jalr";
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      mne = rs1 != 0 ? "add" : "c.add";
Packit Service 97d2fb
		      op[2] = REG (rs2);
Packit Service 97d2fb
		      op[1] = op[0];
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 15:
Packit Service 97d2fb
	      op[0] = FREGP ((first >> 2) & 0x7);
Packit Service 97d2fb
	      opaddr = ((first << 1) & 0xc0) | ((first >> 7) & 0x38);
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "%" PRIu64 "(%s)",
Packit Service 97d2fb
			opaddr, REGP ((first >> 7) & 0x7));
Packit Service 97d2fb
	      op[1] = addrbuf;
Packit Service 97d2fb
	      mne = "fsd";
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 16:
Packit Service 97d2fb
	      opaddr = (((UINT64_C (0) - ((first >> 12) & 0x1)) << 11)
Packit Service 97d2fb
			| ((first << 2) & 0x400)
Packit Service 97d2fb
			| ((first >> 1) & 0x300)
Packit Service 97d2fb
			| ((first << 1) & 0x80)
Packit Service 97d2fb
			| ((first >> 1) & 0x40)
Packit Service 97d2fb
			| ((first << 3) & 0x20)
Packit Service 97d2fb
			| ((first >> 7) & 0x10)
Packit Service 97d2fb
			| ((first >> 2) & 0xe));
Packit Service 97d2fb
	      mne = "j";
Packit Service 97d2fb
	      // TODO translate address
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, addr + opaddr);
Packit Service 97d2fb
	      op[0] = addrbuf;
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 17:
Packit Service 97d2fb
	      op[0] = FREG ((first >> 2) & 0x1f);
Packit Service 97d2fb
	      opaddr = ((first >> 1) & 0x1c0) | ((first >> 7) & 0x38);
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "%" PRIu64 "(%s)", opaddr, REG (2));
Packit Service 97d2fb
	      op[1] = addrbuf;
Packit Service 97d2fb
	      mne = "fsd";
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 19:
Packit Service 97d2fb
	    case 22:
Packit Service 97d2fb
	      mne = idx == 19 ? "beqz" : "bnez";
Packit Service 97d2fb
	      op[0] = REG (8 + ((first >> 7) & 0x7));
Packit Service 97d2fb
	      opaddr = addr + (((UINT64_C (0) - ((first >> 12) & 0x1)) & ~0xff)
Packit Service 97d2fb
			       | ((first << 1) & 0xc0) | ((first << 3) & 0x20)
Packit Service 97d2fb
			       | ((first >> 7) & 0x18) |  ((first >> 2) & 0x6));
Packit Service 97d2fb
	      // TODO translate address
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr);
Packit Service 97d2fb
	      op[1] = addrbuf;
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 20:
Packit Service 97d2fb
	      op[0] = REG ((first >> 2) & 0x1f);
Packit Service 97d2fb
	      opaddr = ((first >> 1) & 0xc0) | ((first >> 7) & 0x3c);
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)", opaddr, REG (2));
Packit Service 97d2fb
	      op[1] = addrbuf;
Packit Service 97d2fb
	      mne = "sw";
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 21:
Packit Service 97d2fb
	      if (idx == 18 || ebl->class == ELFCLASS32)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = "fsw";
Packit Service 97d2fb
		  op[0] = FREGP ((first >> 2) & 0x7);
Packit Service 97d2fb
		  opaddr = (((first >> 7) & 0x38) | ((first << 1) & 0x40)
Packit Service 97d2fb
			    | ((first >> 4) & 0x4));
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = "sd";
Packit Service 97d2fb
		  op[0] = REGP ((first >> 2) & 0x7);
Packit Service 97d2fb
		  opaddr = ((first >> 7) & 0x38) | ((first << 1) & 0xc0);
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)",
Packit Service 97d2fb
			opaddr, REGP ((first >> 7) & 0x7));
Packit Service 97d2fb
	      op[1] = addrbuf;
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 23:
Packit Service 97d2fb
	      if (idx == 18 || ebl->class == ELFCLASS32)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = "fsw";
Packit Service 97d2fb
		  op[0] = FREG ((first & 0x7c) >> 2);
Packit Service 97d2fb
		  opaddr = ((first & 0x1e00) >> 7) | ((first & 0x180) >> 1);
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = "sd";
Packit Service 97d2fb
		  op[0] = REG ((first & 0x7c) >> 2);
Packit Service 97d2fb
		  opaddr = ((first & 0x1c00) >> 7) | ((first & 0x380) >> 1);
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)", opaddr, REG (2));
Packit Service 97d2fb
	      op[1] = addrbuf;
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    default:
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    }
Packit Service 97d2fb
Packit Service 97d2fb
	  if (strp == NULL && mne == NULL)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      len = snprintf (immbuf, sizeof (immbuf), "0x%04" PRIx16, first);
Packit Service 97d2fb
	      strp = immbuf;
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	}
Packit Service 97d2fb
      else if (length == 4)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  uint32_t word = read_4ubyte_unaligned (data);
Packit Service 97d2fb
	  size_t idx = (word >> 2) & 0x1f;
Packit Service 97d2fb
Packit Service 97d2fb
	  switch (idx)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	    static const char widthchar[4] = { 's', 'd', '\0', 'q' };
Packit Service 97d2fb
	    static const char intwidthchar[4] = { 'w', 'd', '\0', 'q' };
Packit Service 97d2fb
	    static const char *const rndmode[8] = { "rne", "rtz", "rdn", "rup", "rmm", "???", "???", "dyn" };
Packit Service 97d2fb
	    uint32_t rd;
Packit Service 97d2fb
	    uint32_t rs1;
Packit Service 97d2fb
	    uint32_t rs2;
Packit Service 97d2fb
	    uint32_t rs3;
Packit Service 97d2fb
	    uint32_t func;
Packit Service 97d2fb
Packit Service 97d2fb
	    case 0x00:
Packit Service 97d2fb
	    case 0x01:
Packit Service 97d2fb
	      // LOAD and LOAD-FP
Packit Service 97d2fb
	      rd = (word >> 7) & 0x1f;
Packit Service 97d2fb
	      op[0] = idx == 0x00 ? REG (rd) : FREG (rd);
Packit Service 97d2fb
	      opaddr = ((int32_t) word) >> 20;
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)",
Packit Service 97d2fb
			opaddr, REG ((word >> 15) & 0x1f));
Packit Service 97d2fb
	      op[1] = addrbuf;
Packit Service 97d2fb
	      func = (word >> 12) & 0x7;
Packit Service 97d2fb
	      static const char *const loadmne[8] =
Packit Service 97d2fb
	        {
Packit Service 97d2fb
	          "lb", "lh", "lw", "ld", "lbu", "lhu", "lwu", NULL
Packit Service 97d2fb
	        };
Packit Service 97d2fb
	      static const char *const floadmne[8] =
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  NULL, NULL, "flw", "fld", "flq", NULL, NULL, NULL
Packit Service 97d2fb
		};
Packit Service 97d2fb
	      mne = (char *) (idx == 0x00 ? loadmne[func] : floadmne[func]);
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 0x03:
Packit Service 97d2fb
	      // MISC-MEM
Packit Service 97d2fb
	      rd = (word >> 7) & 0x1f;
Packit Service 97d2fb
	      rs1 = (word >> 15) & 0x1f;
Packit Service 97d2fb
	      func = (word >> 12) & 0x7;
Packit Service 97d2fb
Packit Service 97d2fb
	      if (word == 0x8330000f)
Packit Service 97d2fb
		mne = "fence.tso";
Packit Service 97d2fb
	      else if (word == 0x0000100f)
Packit Service 97d2fb
		mne = "fence.i";
Packit Service 97d2fb
	      else if (func == 0 && rd == 0 && rs1 == 0 && (word & 0xf0000000) == 0)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  static const char *const order[16] =
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      "unknown", "w", "r", "rw", "o", "ow", "or", "orw",
Packit Service 97d2fb
		      "i", "iw", "ir", "irw", "io", "iow", "ior", "iorw"
Packit Service 97d2fb
		    };
Packit Service 97d2fb
		  uint32_t pred = (word >> 20) & 0xf;
Packit Service 97d2fb
		  uint32_t succ = (word >> 24) & 0xf;
Packit Service 97d2fb
		  if (pred != 0xf || succ != 0xf)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      op[0] = (char *) order[succ];
Packit Service 97d2fb
		      op[1] = (char *) order[pred];
Packit Service 97d2fb
		     }
Packit Service 97d2fb
		   mne = "fence";
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 0x04:
Packit Service 97d2fb
	    case 0x06:
Packit Service 97d2fb
	      // OP-IMM and OP-IMM32
Packit Service 97d2fb
	      rd = (word >> 7) & 0x1f;
Packit Service 97d2fb
	      op[0] = REG (rd);
Packit Service 97d2fb
	      rs1 = (word >> 15) & 0x1f;
Packit Service 97d2fb
	      op[1] = REG (rs1);
Packit Service 97d2fb
	      opaddr = ((int32_t) word) >> 20;
Packit Service 97d2fb
	      static const char *const opimmmne[8] =
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  "addi", NULL, "slti", "sltiu", "xori", NULL, "ori", "andi"
Packit Service 97d2fb
		};
Packit Service 97d2fb
	      func = (word >> 12) & 0x7;
Packit Service 97d2fb
	      mne = (char *) opimmmne[func];
Packit Service 97d2fb
	      if (mne == NULL)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  const uint64_t shiftmask = ebl->class == ELFCLASS32 ? 0x1f : 0x3f;
Packit Service 97d2fb
		  if (func == 0x1 && (opaddr & ~shiftmask) == 0)
Packit Service 97d2fb
		    mne = "slli";
Packit Service 97d2fb
		  else if (func == 0x5 && (opaddr & ~shiftmask) == 0)
Packit Service 97d2fb
		    mne = "srli";
Packit Service 97d2fb
		  else if (func == 0x5 && (opaddr & ~shiftmask) == 0x400)
Packit Service 97d2fb
		    mne = "srai";
Packit Service 97d2fb
		  snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr & shiftmask);
Packit Service 97d2fb
		  op[2] = addrbuf;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else if (func == 0x0 && (rd != 0 || idx == 0x06) && rs1 == 0 && rd != 0)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = "li";
Packit Service 97d2fb
		  snprintf (addrbuf, sizeof (addrbuf), "%" PRId64, opaddr);
Packit Service 97d2fb
		  op[1] = addrbuf;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else if (func == 0x00 && opaddr == 0)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  if (idx == 0x06)
Packit Service 97d2fb
		    mne ="sext.";
Packit Service 97d2fb
		  else if (rd == 0)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      mne = "nop";
Packit Service 97d2fb
		      op[0] = op[1] = NULL;
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else
Packit Service 97d2fb
		    mne = "mv";
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else if (func == 0x3 && opaddr == 1)
Packit Service 97d2fb
		mne = "seqz";
Packit Service 97d2fb
	      else if (func == 0x4 && opaddr == -1)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = "not";
Packit Service 97d2fb
		  op[2] = NULL;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  snprintf (addrbuf, sizeof (addrbuf), "%" PRId64, opaddr);
Packit Service 97d2fb
		  op[2] = addrbuf;
Packit Service 97d2fb
Packit Service 97d2fb
		  if (func == 0x0 && rs1 == 0 && rd != 0)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      op[1] = op[2];
Packit Service 97d2fb
		      op[2] = NULL;
Packit Service 97d2fb
		      mne = "li";
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      if (mne != NULL && idx == 0x06)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  mne = strcpy (mnebuf, mne);
Packit Service 97d2fb
		  strcat (mnebuf, "w");
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 0x05:
Packit Service 97d2fb
	    case 0x0d:
Packit Service 97d2fb
	      // LUI and AUIPC
Packit Service 97d2fb
	      mne = idx == 0x05 ? "auipc" : "lui";
Packit Service 97d2fb
	      op[0] = REG ((word >> 7) & 0x1f);
Packit Service 97d2fb
	      opaddr = word >> 12;
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr);
Packit Service 97d2fb
	      op[1] = addrbuf;
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 0x08:
Packit Service 97d2fb
	    case 0x09:
Packit Service 97d2fb
	      // STORE and STORE-FP
Packit Service 97d2fb
	      rs2 = (word >> 20) & 0x1f;
Packit Service 97d2fb
	      op[0] = idx == 0x08 ? REG (rs2) : FREG (rs2);
Packit Service 97d2fb
	      opaddr = ((((int64_t) ((int32_t) word) >> 20)) & ~0x1f) | ((word >> 7) & 0x1f);
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)",
Packit Service 97d2fb
			opaddr, REG ((word >> 15) & 0x1f));
Packit Service 97d2fb
	      op[1] = addrbuf;
Packit Service 97d2fb
	      func = (word >> 12) & 0x7;
Packit Service 97d2fb
	      static const char *const storemne[8] =
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  "sb", "sh", "sw", "sd", NULL, NULL, NULL, NULL
Packit Service 97d2fb
		};
Packit Service 97d2fb
	      static const char *const fstoremne[8] =
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  NULL, NULL, "fsw", "fsd", "fsq", NULL, NULL, NULL
Packit Service 97d2fb
		};
Packit Service 97d2fb
	      mne = (char *) (idx == 0x08 ? storemne[func] : fstoremne[func]);
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 0x0b:
Packit Service 97d2fb
	      // AMO
Packit Service 97d2fb
	      op[0] = REG ((word >> 7) & 0x1f);
Packit Service 97d2fb
	      rs1 = (word >> 15) & 0x1f;
Packit Service 97d2fb
	      rs2 = (word >> 20) & 0x1f;
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "(%s)", REG (rs1));
Packit Service 97d2fb
	      op[2] = addrbuf;
Packit Service 97d2fb
	      size_t width = (word >> 12) & 0x7;
Packit Service 97d2fb
	      func = word >> 27;
Packit Service 97d2fb
	      static const char *const amomne[32] =
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  "amoadd", "amoswap", "lr", "sc", "amoxor", NULL, NULL, NULL,
Packit Service 97d2fb
		  "amoor", NULL, NULL, NULL, "amoand", NULL, NULL, NULL,
Packit Service 97d2fb
		  "amomin", NULL, NULL, NULL, "amomax", NULL, NULL, NULL,
Packit Service 97d2fb
		  "amominu", NULL, NULL, NULL, "amomaxu", NULL, NULL, NULL
Packit Service 97d2fb
		};
Packit Service 97d2fb
	      if (amomne[func] != NULL && width >= 2 && width <= 3
Packit Service 97d2fb
		  && (func != 0x02 || rs2 == 0))
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  if (func == 0x02)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      op[1] = op[2];
Packit Service 97d2fb
		      op[2] = NULL;
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else
Packit Service 97d2fb
		    op[1] = REG (rs2);
Packit Service 97d2fb
Packit Service 97d2fb
		  char *cp = stpcpy (mnebuf, amomne[func]);
Packit Service 97d2fb
		  *cp++ = '.';
Packit Service 97d2fb
		  *cp++ = "  wd    "[width];
Packit Service 97d2fb
		  assert (cp[-1] != ' ');
Packit Service 97d2fb
		  static const char *const aqrlstr[4] =
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      "", ".rl", ".aq", ".aqrl"
Packit Service 97d2fb
		    };
Packit Service 97d2fb
		  strcpy (cp, aqrlstr[(word >> 25) & 0x3]);
Packit Service 97d2fb
		  mne = mnebuf;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 0x0c:
Packit Service 97d2fb
	    case 0x0e:
Packit Service 97d2fb
	      // OP and OP-32
Packit Service 97d2fb
	      if ((word & 0xbc000000) == 0)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  rs1 = (word >> 15) & 0x1f;
Packit Service 97d2fb
		  rs2 = (word >> 20) & 0x1f;
Packit Service 97d2fb
		  op[0] = REG ((word >> 7) & 0x1f);
Packit Service 97d2fb
		  func = ((word >> 21) & 0x10) | ((word >> 27) & 0x8) | ((word >> 12) & 0x7);
Packit Service 97d2fb
		  static const char *const arithmne2[32] =
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      "add", "sll", "slt", "sltu", "xor", "srl", "or", "and",
Packit Service 97d2fb
		      "sub", NULL, NULL, NULL, NULL, "sra", NULL, NULL,
Packit Service 97d2fb
		      "mul", "mulh", "mulhsu", "mulhu", "div", "divu", "rem", "remu",
Packit Service 97d2fb
		      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
Packit Service 97d2fb
		    };
Packit Service 97d2fb
		  static const char *const arithmne3[32] =
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      "addw", "sllw", NULL, NULL, NULL, "srlw", NULL, NULL,
Packit Service 97d2fb
		      "subw", NULL, NULL, NULL, NULL, "sraw", NULL, NULL,
Packit Service 97d2fb
		      "mulw", NULL, NULL, NULL, "divw", "divuw", "remw", "remuw",
Packit Service 97d2fb
		      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
Packit Service 97d2fb
		    };
Packit Service 97d2fb
		  if (func == 8 && rs1 == 0)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      mne = idx == 0x0c ? "neg" : "negw";
Packit Service 97d2fb
		      op[1] = REG (rs2);
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else if (idx == 0x0c && rs2 == 0 && func == 2)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      op[1] = REG (rs1);
Packit Service 97d2fb
		      mne = "sltz";
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else if (idx == 0x0c && rs1 == 0 && (func == 2 || func == 3))
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      op[1] = REG (rs2);
Packit Service 97d2fb
		      mne = func == 2 ? "sgtz" : "snez";
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      mne = (char *) (idx == 0x0c ? arithmne2[func] : arithmne3[func]);
Packit Service 97d2fb
		      op[1] = REG (rs1);
Packit Service 97d2fb
		      op[2] = REG (rs2);
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 0x10:
Packit Service 97d2fb
	    case 0x11:
Packit Service 97d2fb
	    case 0x12:
Packit Service 97d2fb
	    case 0x13:
Packit Service 97d2fb
	      // MADD, MSUB, NMSUB, NMADD
Packit Service 97d2fb
	      if ((word & 0x06000000) != 0x04000000)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  rd = (word >> 7) & 0x1f;
Packit Service 97d2fb
		  rs1 = (word >> 15) & 0x1f;
Packit Service 97d2fb
		  rs2 = (word >> 20) & 0x1f;
Packit Service 97d2fb
		  rs3 = (word >> 27) & 0x1f;
Packit Service 97d2fb
		  uint32_t rm = (word >> 12) & 0x7;
Packit Service 97d2fb
		  width = (word >> 25) & 0x3;
Packit Service 97d2fb
Packit Service 97d2fb
		  static const char *const fmamne[4] =
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      "fmadd.", "fmsub.", "fnmsub.", "fnmadd."
Packit Service 97d2fb
		    };
Packit Service 97d2fb
		  char *cp = stpcpy (mnebuf, fmamne[idx & 0x3]);
Packit Service 97d2fb
		  *cp++ = widthchar[width];
Packit Service 97d2fb
		  *cp = '\0';
Packit Service 97d2fb
		  mne = mnebuf;
Packit Service 97d2fb
		  op[0] = FREG (rd);
Packit Service 97d2fb
		  op[1] = FREG (rs1);
Packit Service 97d2fb
		  op[2] = FREG (rs2);
Packit Service 97d2fb
		  op[3] = FREG (rs3);
Packit Service 97d2fb
		  if (rm != 0x7)
Packit Service 97d2fb
		    op[4] = (char *) rndmode[rm];
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 0x14:
Packit Service 97d2fb
	      // OP-FP
Packit Service 97d2fb
	      if ((word & 0x06000000) != 0x04000000)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  width = (word >> 25) & 0x3;
Packit Service 97d2fb
		  rd = (word >> 7) & 0x1f;
Packit Service 97d2fb
		  rs1 = (word >> 15) & 0x1f;
Packit Service 97d2fb
		  rs2 = (word >> 20) & 0x1f;
Packit Service 97d2fb
		  func = word >> 27;
Packit Service 97d2fb
		  uint32_t rm = (word >> 12) & 0x7;
Packit Service 97d2fb
		  if (func < 4)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      static const char *const fpop[4] =
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  "fadd", "fsub", "fmul", "fdiv"
Packit Service 97d2fb
			};
Packit Service 97d2fb
		      char *cp = stpcpy (mnebuf, fpop[func]);
Packit Service 97d2fb
		      *cp++ = '.';
Packit Service 97d2fb
		      *cp++ = widthchar[width];
Packit Service 97d2fb
		      *cp = '\0';
Packit Service 97d2fb
		      mne = mnebuf;
Packit Service 97d2fb
		      op[0] = FREG (rd);
Packit Service 97d2fb
		      op[1] = FREG (rs1);
Packit Service 97d2fb
		      op[2] = FREG (rs2);
Packit Service 97d2fb
		      if (rm != 0x7)
Packit Service 97d2fb
			op[3] = (char *) rndmode[rm];
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else if (func == 0x1c && width != 2 && rs2 == 0 && rm <= 1)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      char *cp;
Packit Service 97d2fb
		      if (rm == 0)
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  cp = stpcpy (mnebuf, "fmv.x.");
Packit Service 97d2fb
			  *cp++ = intwidthchar[width];
Packit Service 97d2fb
			}
Packit Service 97d2fb
		      else
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  cp = stpcpy (mnebuf, "fclass.");
Packit Service 97d2fb
			  *cp++ = widthchar[width];
Packit Service 97d2fb
			}
Packit Service 97d2fb
		      *cp = '\0';
Packit Service 97d2fb
		      mne = mnebuf;
Packit Service 97d2fb
		      op[0] = REG (rd);
Packit Service 97d2fb
		      op[1] = FREG (rs1);
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else if (func == 0x1e && width != 2 && rs2 == 0 && rm == 0)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      char *cp = stpcpy (mnebuf, "fmv.");
Packit Service 97d2fb
		      *cp++ = intwidthchar[width];
Packit Service 97d2fb
		      strcpy (cp, ".x");
Packit Service 97d2fb
		      mne = mnebuf;
Packit Service 97d2fb
		      op[0] = FREG (rd);
Packit Service 97d2fb
		      op[1] = REG (rs1);
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else if (func == 0x14)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      uint32_t cmpop = (word >> 12) & 0x7;
Packit Service 97d2fb
		      if (cmpop < 3)
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  static const char *const mnefpcmp[3] =
Packit Service 97d2fb
			    {
Packit Service 97d2fb
			      "fle", "flt", "feq"
Packit Service 97d2fb
			    };
Packit Service 97d2fb
			  char *cp = stpcpy (mnebuf, mnefpcmp[cmpop]);
Packit Service 97d2fb
			  *cp++ = '.';
Packit Service 97d2fb
			  *cp++ = widthchar[width];
Packit Service 97d2fb
			  *cp = '\0';
Packit Service 97d2fb
			  mne = mnebuf;
Packit Service 97d2fb
			  op[0] = REG (rd);
Packit Service 97d2fb
			  op[1] = FREG (rs1);
Packit Service 97d2fb
			  op[2] = FREG (rs2);
Packit Service 97d2fb
			}
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else if (func == 0x04)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      uint32_t cmpop = (word >> 12) & 0x7;
Packit Service 97d2fb
		      if (cmpop < 3)
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  op[0] = FREG (rd);
Packit Service 97d2fb
			  op[1] = FREG (rs1);
Packit Service 97d2fb
Packit Service 97d2fb
			  static const char *const mnefpcmp[3] =
Packit Service 97d2fb
			    {
Packit Service 97d2fb
			      "fsgnj.", "fsgnjn.", "fsgnjx."
Packit Service 97d2fb
			    };
Packit Service 97d2fb
			  static const char *const altsignmne[3] =
Packit Service 97d2fb
			    {
Packit Service 97d2fb
			      "fmv.", "fneg.", "fabs."
Packit Service 97d2fb
			    };
Packit Service 97d2fb
			  char *cp = stpcpy (mnebuf, rs1 == rs2 ? altsignmne[cmpop] : mnefpcmp[cmpop]);
Packit Service 97d2fb
			  *cp++ = widthchar[width];
Packit Service 97d2fb
			  *cp = '\0';
Packit Service 97d2fb
			  mne = mnebuf;
Packit Service 97d2fb
Packit Service 97d2fb
			  if (rs1 != rs2)
Packit Service 97d2fb
			    op[2] = FREG (rs2);
Packit Service 97d2fb
			}
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else if (func == 0x08 && width != 2 && rs2 <= 3 && rs2 != 2 && rs2 != width)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      op[0] = FREG (rd);
Packit Service 97d2fb
		      op[1] = FREG (rs1);
Packit Service 97d2fb
		      char *cp = stpcpy (mnebuf, "fcvt.");
Packit Service 97d2fb
		      *cp++ = widthchar[width];
Packit Service 97d2fb
		      *cp++ = '.';
Packit Service 97d2fb
		      *cp++ = widthchar[rs2];
Packit Service 97d2fb
		      *cp = '\0';
Packit Service 97d2fb
		      mne = mnebuf;
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else if ((func & 0x1d) == 0x18 && width != 2 && rs2 < 4)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      char *cp = stpcpy (mnebuf, "fcvt.");
Packit Service 97d2fb
		      if (func == 0x18)
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  *cp++ = rs2 >= 2 ? 'l' : 'w';
Packit Service 97d2fb
			  if ((rs2 & 1) == 1)
Packit Service 97d2fb
			    *cp++ = 'u';
Packit Service 97d2fb
			  *cp++ = '.';
Packit Service 97d2fb
			  *cp++ = widthchar[width];
Packit Service 97d2fb
			  *cp = '\0';
Packit Service 97d2fb
			  op[0] = REG (rd);
Packit Service 97d2fb
			  op[1] = FREG (rs1);
Packit Service 97d2fb
			}
Packit Service 97d2fb
		      else
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  *cp++ = widthchar[width];
Packit Service 97d2fb
			  *cp++ = '.';
Packit Service 97d2fb
			  *cp++ = rs2 >= 2 ? 'l' : 'w';
Packit Service 97d2fb
			  if ((rs2 & 1) == 1)
Packit Service 97d2fb
			    *cp++ = 'u';
Packit Service 97d2fb
			  *cp = '\0';
Packit Service 97d2fb
			  op[0] = FREG (rd);
Packit Service 97d2fb
			  op[1] = REG (rs1);
Packit Service 97d2fb
			}
Packit Service 97d2fb
		      mne = mnebuf;
Packit Service 97d2fb
		      if (rm != 0x7 && (func == 0x18 || width == 0 || rs2 >= 2))
Packit Service 97d2fb
			op[2] = (char *) rndmode[rm];
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else if (func == 0x0b && rs2 == 0)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      op[0] = FREG (rd);
Packit Service 97d2fb
		      op[1] = FREG (rs1);
Packit Service 97d2fb
		      char *cp = stpcpy (mnebuf, "fsqrt.");
Packit Service 97d2fb
		      *cp++ = widthchar[width];
Packit Service 97d2fb
		      *cp = '\0';
Packit Service 97d2fb
		      mne = mnebuf;
Packit Service 97d2fb
		      if (rm != 0x7)
Packit Service 97d2fb
			op[2] = (char *) rndmode[rm];
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else if (func == 0x05 && rm < 2)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      op[0] = FREG (rd);
Packit Service 97d2fb
		      op[1] = FREG (rs1);
Packit Service 97d2fb
		      op[2] = FREG (rs2);
Packit Service 97d2fb
		      char *cp = stpcpy (mnebuf, rm == 0 ? "fmin." : "fmax.");
Packit Service 97d2fb
		      *cp++ = widthchar[width];
Packit Service 97d2fb
		      *cp = '\0';
Packit Service 97d2fb
		      mne = mnebuf;
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else if (func == 0x14 && rm <= 0x2)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      op[0] = REG (rd);
Packit Service 97d2fb
		      op[1] = FREG (rs1);
Packit Service 97d2fb
		      op[2] = FREG (rs2);
Packit Service 97d2fb
		      static const char *const fltcmpmne[3] =
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  "fle.", "flt.", "feq."
Packit Service 97d2fb
			};
Packit Service 97d2fb
		      char *cp = stpcpy (mnebuf, fltcmpmne[rm]);
Packit Service 97d2fb
		      *cp++ = widthchar[width];
Packit Service 97d2fb
		      *cp = '\0';
Packit Service 97d2fb
		      mne = mnebuf;
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 0x18:
Packit Service 97d2fb
	      // BRANCH
Packit Service 97d2fb
	      rs1 = (word >> 15) & 0x1f;
Packit Service 97d2fb
	      op[0] = REG (rs1);
Packit Service 97d2fb
	      rs2 = (word >> 20) & 0x1f;
Packit Service 97d2fb
	      op[1] = REG (rs2);
Packit Service 97d2fb
	      opaddr = addr + (((UINT64_C (0) - (word >> 31)) << 12)
Packit Service 97d2fb
			       + ((word << 4) & 0x800)
Packit Service 97d2fb
			       + ((word >> 20) & 0x7e0)
Packit Service 97d2fb
			       + ((word >> 7) & 0x1e));
Packit Service 97d2fb
	      // TODO translate address
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr);
Packit Service 97d2fb
	      op[2] = addrbuf;
Packit Service 97d2fb
	      static const char *const branchmne[8] =
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  "beq", "bne", NULL, NULL, "blt", "bge", "bltu", "bgeu"
Packit Service 97d2fb
		};
Packit Service 97d2fb
	      func = (word >> 12) & 0x7;
Packit Service 97d2fb
	      mne = (char *) branchmne[func];
Packit Service 97d2fb
	      if (rs1 == 0 && func == 5)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  op[0] = op[1];
Packit Service 97d2fb
		  op[1] = op[2];
Packit Service 97d2fb
		  op[2] = NULL;
Packit Service 97d2fb
		  mne = "blez";
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else if (rs1 == 0 && func == 4)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  op[0] = op[1];
Packit Service 97d2fb
		  op[1] = op[2];
Packit Service 97d2fb
		  op[2] = NULL;
Packit Service 97d2fb
		  mne = "bgtz";
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else if (rs2 == 0)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  if (func == 0 || func == 1 || func == 4 || func == 5)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      op[1] = op[2];
Packit Service 97d2fb
		      op[2] = NULL;
Packit Service 97d2fb
		      strcpy (stpcpy (mnebuf, mne), "z");
Packit Service 97d2fb
		      mne = mnebuf;
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else if (func == 5 || func == 7)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  // binutils use these opcodes and the reverse parameter order
Packit Service 97d2fb
		  char *tmp = op[0];
Packit Service 97d2fb
		  op[0] = op[1];
Packit Service 97d2fb
		  op[1] = tmp;
Packit Service 97d2fb
		  mne = func == 5 ? "ble" : "bleu";
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 0x19:
Packit Service 97d2fb
	      // JALR
Packit Service 97d2fb
	      if ((word & 0x7000) == 0)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  rd = (word >> 7) & 0x1f;
Packit Service 97d2fb
		  rs1 = (word >> 15) & 0x1f;
Packit Service 97d2fb
		  opaddr = (int32_t) word >> 20;
Packit Service 97d2fb
		  size_t next = 0;
Packit Service 97d2fb
		  if (rd > 1)
Packit Service 97d2fb
		    op[next++] = REG (rd);
Packit Service 97d2fb
		  if (opaddr == 0)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      if (rs1 != 0 || next == 0)
Packit Service 97d2fb
			op[next] = REG (rs1);
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)", opaddr, REG (rs1));
Packit Service 97d2fb
		      op[next] = addrbuf;
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  mne = rd == 0 ? "jr" : "jalr";
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 0x1b:
Packit Service 97d2fb
	      // JAL
Packit Service 97d2fb
	      rd = (word >> 7) & 0x1f;
Packit Service 97d2fb
	      if (rd != 0)
Packit Service 97d2fb
		op[0] = REG (rd);
Packit Service 97d2fb
	      opaddr = addr + ((UINT64_C (0) - ((word >> 11) & 0x100000))
Packit Service 97d2fb
			       | (word & 0xff000)
Packit Service 97d2fb
			       | ((word >> 9) & 0x800)
Packit Service 97d2fb
			       | ((word >> 20) & 0x7fe));
Packit Service 97d2fb
	      // TODO translate address
Packit Service 97d2fb
	      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr);
Packit Service 97d2fb
	      op[rd != 0] = addrbuf;
Packit Service 97d2fb
	      mne = rd == 0 ? "j" : "jal";
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    case 0x1c:
Packit Service 97d2fb
	      // SYSTEM
Packit Service 97d2fb
	      rd = (word >> 7) & 0x1f;
Packit Service 97d2fb
	      rs1 = (word >> 15) & 0x1f;
Packit Service 97d2fb
	      if (word == 0x00000073)
Packit Service 97d2fb
		mne = "ecall";
Packit Service 97d2fb
	      else if (word == 0x00100073)
Packit Service 97d2fb
		mne = "ebreak";
Packit Service 97d2fb
	      else if (word == 0x00200073)
Packit Service 97d2fb
		mne = "uret";
Packit Service 97d2fb
	      else if (word == 0x10200073)
Packit Service 97d2fb
		mne = "sret";
Packit Service 97d2fb
	      else if (word == 0x30200073)
Packit Service 97d2fb
		mne = "mret";
Packit Service 97d2fb
	      else if (word == 0x10500073)
Packit Service 97d2fb
		mne = "wfi";
Packit Service 97d2fb
	      else if ((word & 0x3000) == 0x2000 && rs1 == 0)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  uint32_t csr = word >> 20;
Packit Service 97d2fb
		  if (/* csr >= 0x000 && */ csr <= 0x007)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      static const char *const unprivrw[4] =
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  NULL, "frflags", "frrm", "frsr",
Packit Service 97d2fb
			};
Packit Service 97d2fb
		      mne = (char *) unprivrw[csr - 0x000];
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else if (csr >= 0xc00 && csr <= 0xc03)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      static const char *const unprivrolow[3] =
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  "rdcycle", "rdtime", "rdinstret"
Packit Service 97d2fb
			};
Packit Service 97d2fb
		      mne = (char *) unprivrolow[csr - 0xc00];
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  op[0] = REG ((word >> 7) & 0x1f);
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      else if ((word & 0x3000) == 0x1000 && rd == 0)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  uint32_t csr = word >> 20;
Packit Service 97d2fb
		  if (/* csr >= 0x000 && */ csr <= 0x003)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      static const char *const unprivrs[4] =
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  NULL, "fsflags", "fsrm", "fssr",
Packit Service 97d2fb
			};
Packit Service 97d2fb
		      static const char *const unprivrsi[4] =
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  NULL, "fsflagsi", "fsrmi", NULL
Packit Service 97d2fb
			};
Packit Service 97d2fb
		      mne = (char *) ((word & 0x4000) == 0 ? unprivrs : unprivrsi)[csr - 0x000];
Packit Service 97d2fb
Packit Service 97d2fb
		      if ((word & 0x4000) == 0)
Packit Service 97d2fb
			op[0] = REG ((word >> 15) & 0x1f);
Packit Service 97d2fb
		      else
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  snprintf (immbuf, sizeof (immbuf), "%" PRIu32, (word >> 15) & 0x1f);
Packit Service 97d2fb
			  op[0] = immbuf;
Packit Service 97d2fb
			}
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      if (mne == NULL && (word & 0x3000) != 0)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  static const char *const mnecsr[8] =
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      NULL, "csrrw", "csrrs", "csrrc",
Packit Service 97d2fb
		      NULL, "csrrwi", "csrrsi", "csrrci"
Packit Service 97d2fb
		    };
Packit Service 97d2fb
		  static const struct known_csrs known[] =
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      // This list must remain sorted by NR.
Packit Service 97d2fb
		      { 0x000, "ustatus" },
Packit Service 97d2fb
		      { 0x001, "fflags" },
Packit Service 97d2fb
		      { 0x002, "fram" },
Packit Service 97d2fb
		      { 0x003, "fcsr" },
Packit Service 97d2fb
		      { 0x004, "uie" },
Packit Service 97d2fb
		      { 0x005, "utvec" },
Packit Service 97d2fb
		      { 0x040, "uscratch" },
Packit Service 97d2fb
		      { 0x041, "uepc" },
Packit Service 97d2fb
		      { 0x042, "ucause" },
Packit Service 97d2fb
		      { 0x043, "utval" },
Packit Service 97d2fb
		      { 0x044, "uip" },
Packit Service 97d2fb
		      { 0x100, "sstatus" },
Packit Service 97d2fb
		      { 0x102, "sedeleg" },
Packit Service 97d2fb
		      { 0x103, "sideleg" },
Packit Service 97d2fb
		      { 0x104, "sie" },
Packit Service 97d2fb
		      { 0x105, "stvec" },
Packit Service 97d2fb
		      { 0x106, "scounteren" },
Packit Service 97d2fb
		      { 0x140, "sscratch" },
Packit Service 97d2fb
		      { 0x141, "sepc" },
Packit Service 97d2fb
		      { 0x142, "scause" },
Packit Service 97d2fb
		      { 0x143, "stval" },
Packit Service 97d2fb
		      { 0x144, "sip" },
Packit Service 97d2fb
		      { 0x180, "satp" },
Packit Service 97d2fb
		      { 0x200, "vsstatus" },
Packit Service 97d2fb
		      { 0x204, "vsie" },
Packit Service 97d2fb
		      { 0x205, "vstvec" },
Packit Service 97d2fb
		      { 0x240, "vsscratch" },
Packit Service 97d2fb
		      { 0x241, "vsepc" },
Packit Service 97d2fb
		      { 0x242, "vscause" },
Packit Service 97d2fb
		      { 0x243, "vstval" },
Packit Service 97d2fb
		      { 0x244, "vsip" },
Packit Service 97d2fb
		      { 0x280, "vsatp" },
Packit Service 97d2fb
		      { 0x600, "hstatus" },
Packit Service 97d2fb
		      { 0x602, "hedeleg" },
Packit Service 97d2fb
		      { 0x603, "hideleg" },
Packit Service 97d2fb
		      { 0x605, "htimedelta" },
Packit Service 97d2fb
		      { 0x606, "hcounteren" },
Packit Service 97d2fb
		      { 0x615, "htimedeltah" },
Packit Service 97d2fb
		      { 0x680, "hgatp" },
Packit Service 97d2fb
		      { 0xc00, "cycle" },
Packit Service 97d2fb
		      { 0xc01, "time" },
Packit Service 97d2fb
		      { 0xc02, "instret" },
Packit Service 97d2fb
		      { 0xc03, "hpmcounter3" },
Packit Service 97d2fb
		      { 0xc04, "hpmcounter4" },
Packit Service 97d2fb
		      { 0xc05, "hpmcounter5" },
Packit Service 97d2fb
		      { 0xc06, "hpmcounter6" },
Packit Service 97d2fb
		      { 0xc07, "hpmcounter7" },
Packit Service 97d2fb
		      { 0xc08, "hpmcounter8" },
Packit Service 97d2fb
		      { 0xc09, "hpmcounter9" },
Packit Service 97d2fb
		      { 0xc0a, "hpmcounter10" },
Packit Service 97d2fb
		      { 0xc0b, "hpmcounter11" },
Packit Service 97d2fb
		      { 0xc0c, "hpmcounter12" },
Packit Service 97d2fb
		      { 0xc0d, "hpmcounter13" },
Packit Service 97d2fb
		      { 0xc0e, "hpmcounter14" },
Packit Service 97d2fb
		      { 0xc0f, "hpmcounter15" },
Packit Service 97d2fb
		      { 0xc10, "hpmcounter16" },
Packit Service 97d2fb
		      { 0xc11, "hpmcounter17" },
Packit Service 97d2fb
		      { 0xc12, "hpmcounter18" },
Packit Service 97d2fb
		      { 0xc13, "hpmcounter19" },
Packit Service 97d2fb
		      { 0xc14, "hpmcounter20" },
Packit Service 97d2fb
		      { 0xc15, "hpmcounter21" },
Packit Service 97d2fb
		      { 0xc16, "hpmcounter22" },
Packit Service 97d2fb
		      { 0xc17, "hpmcounter23" },
Packit Service 97d2fb
		      { 0xc18, "hpmcounter24" },
Packit Service 97d2fb
		      { 0xc19, "hpmcounter25" },
Packit Service 97d2fb
		      { 0xc1a, "hpmcounter26" },
Packit Service 97d2fb
		      { 0xc1b, "hpmcounter27" },
Packit Service 97d2fb
		      { 0xc1c, "hpmcounter28" },
Packit Service 97d2fb
		      { 0xc1d, "hpmcounter29" },
Packit Service 97d2fb
		      { 0xc1e, "hpmcounter30" },
Packit Service 97d2fb
		      { 0xc1f, "hpmcounter31" },
Packit Service 97d2fb
		      { 0xc80, "cycleh" },
Packit Service 97d2fb
		      { 0xc81, "timeh" },
Packit Service 97d2fb
		      { 0xc82, "instreth" },
Packit Service 97d2fb
		      { 0xc83, "hpmcounter3h" },
Packit Service 97d2fb
		      { 0xc84, "hpmcounter4h" },
Packit Service 97d2fb
		      { 0xc85, "hpmcounter5h" },
Packit Service 97d2fb
		      { 0xc86, "hpmcounter6h" },
Packit Service 97d2fb
		      { 0xc87, "hpmcounter7h" },
Packit Service 97d2fb
		      { 0xc88, "hpmcounter8h" },
Packit Service 97d2fb
		      { 0xc89, "hpmcounter9h" },
Packit Service 97d2fb
		      { 0xc8a, "hpmcounter10h" },
Packit Service 97d2fb
		      { 0xc8b, "hpmcounter11h" },
Packit Service 97d2fb
		      { 0xc8c, "hpmcounter12h" },
Packit Service 97d2fb
		      { 0xc8d, "hpmcounter13h" },
Packit Service 97d2fb
		      { 0xc8e, "hpmcounter14h" },
Packit Service 97d2fb
		      { 0xc8f, "hpmcounter15h" },
Packit Service 97d2fb
		      { 0xc90, "hpmcounter16h" },
Packit Service 97d2fb
		      { 0xc91, "hpmcounter17h" },
Packit Service 97d2fb
		      { 0xc92, "hpmcounter18h" },
Packit Service 97d2fb
		      { 0xc93, "hpmcounter19h" },
Packit Service 97d2fb
		      { 0xc94, "hpmcounter20h" },
Packit Service 97d2fb
		      { 0xc95, "hpmcounter21h" },
Packit Service 97d2fb
		      { 0xc96, "hpmcounter22h" },
Packit Service 97d2fb
		      { 0xc97, "hpmcounter23h" },
Packit Service 97d2fb
		      { 0xc98, "hpmcounter24h" },
Packit Service 97d2fb
		      { 0xc99, "hpmcounter25h" },
Packit Service 97d2fb
		      { 0xc9a, "hpmcounter26h" },
Packit Service 97d2fb
		      { 0xc9b, "hpmcounter27h" },
Packit Service 97d2fb
		      { 0xc9c, "hpmcounter28h" },
Packit Service 97d2fb
		      { 0xc9d, "hpmcounter29h" },
Packit Service 97d2fb
		      { 0xc9e, "hpmcounter30h" },
Packit Service 97d2fb
		      { 0xc9f, "hpmcounter31h" },
Packit Service 97d2fb
		    };
Packit Service 97d2fb
		  uint32_t csr = word >> 20;
Packit Service 97d2fb
		  uint32_t instr = (word >> 12) & 0x7;
Packit Service 97d2fb
		  size_t last = 0;
Packit Service 97d2fb
		  if (rd != 0)
Packit Service 97d2fb
		    op[last++] = REG (rd);
Packit Service 97d2fb
		  struct known_csrs key = { csr, NULL };
Packit Service 97d2fb
		  struct known_csrs *found = bsearch (&key, known,
Packit Service 97d2fb
						      sizeof (known) / sizeof (known[0]),
Packit Service 97d2fb
						      sizeof (known[0]),
Packit Service 97d2fb
						      compare_csr);
Packit Service 97d2fb
		  if (found)
Packit Service 97d2fb
		    op[last] = (char *) found->name;
Packit Service 97d2fb
		  else
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx32, csr);
Packit Service 97d2fb
		      op[last] = addrbuf;
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  ++last;
Packit Service 97d2fb
		  if ((word & 0x4000) == 0)
Packit Service 97d2fb
		    op[last] = REG ((word >> 15) & 0x1f);
Packit Service 97d2fb
		  else
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      snprintf (immbuf, sizeof (immbuf), "%" PRIu32, (word >> 15) & UINT32_C(0x1f));
Packit Service 97d2fb
		      op[last] = immbuf;
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  if (instr == 1 && rd == 0)
Packit Service 97d2fb
		    mne = "csrw";
Packit Service 97d2fb
		  else if (instr == 2 && rd == 0)
Packit Service 97d2fb
		    mne = "csrs";
Packit Service 97d2fb
		  else if (instr == 6 && rd == 0)
Packit Service 97d2fb
		    mne = "csrsi";
Packit Service 97d2fb
		  else if (instr == 2 && rs1 == 0)
Packit Service 97d2fb
		    mne = "csrr";
Packit Service 97d2fb
		  else if (instr == 3 && rd == 0)
Packit Service 97d2fb
		    mne = "csrc";
Packit Service 97d2fb
		  else
Packit Service 97d2fb
		    mne = (char *) mnecsr[instr];
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    default:
Packit Service 97d2fb
	      break;
Packit Service 97d2fb
	    }
Packit Service 97d2fb
Packit Service 97d2fb
	  if (strp == NULL && mne == NULL)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      len = snprintf (addrbuf, sizeof (addrbuf), "0x%08" PRIx32, word);
Packit Service 97d2fb
	      strp = addrbuf;
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	}
Packit Service 97d2fb
      else
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  // No instruction encodings defined for these sizes yet.
Packit Service 97d2fb
	  char *cp = stpcpy (mnebuf, "0x");
Packit Service 97d2fb
	  assert (length % 2 == 0);
Packit Service 97d2fb
	  for (size_t i = 0; i < length; i += 2)
Packit Service 97d2fb
	    cp += snprintf (cp, mnebuf + sizeof (mnebuf) - cp, "%04" PRIx16,
Packit Service 97d2fb
			    read_2ubyte_unaligned (data + i));
Packit Service 97d2fb
	  strp = mnebuf;
Packit Service 97d2fb
	  len = cp - mnebuf;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      if (strp == NULL)
Packit Service 97d2fb
	{
Packit Service 97d2fb
Packit Service 97d2fb
	  if (0)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      /* Resize the buffer.  */
Packit Service 97d2fb
	      char *oldbuf;
Packit Service 97d2fb
	    enomem:
Packit Service 97d2fb
	      oldbuf = buf;
Packit Service 97d2fb
	      if (buf == initbuf)
Packit Service 97d2fb
		buf = malloc (2 * bufsize);
Packit Service 97d2fb
	      else
Packit Service 97d2fb
		buf = realloc (buf, 2 * bufsize);
Packit Service 97d2fb
	      if (buf == NULL)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  buf = oldbuf;
Packit Service 97d2fb
		  retval = ENOMEM;
Packit Service 97d2fb
		  goto do_ret;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      bufsize *= 2;
Packit Service 97d2fb
Packit Service 97d2fb
	      bufcnt = 0;
Packit Service 97d2fb
	    }
Packit Service 97d2fb
Packit Service 97d2fb
	  unsigned long string_end_idx = 0;
Packit Service 97d2fb
	  fmt = save_fmt;
Packit Service 97d2fb
	  const char *deferred_start = NULL;
Packit Service 97d2fb
	  size_t deferred_len = 0;
Packit Service 97d2fb
	  // XXX Can we get this from color.c?
Packit Service 97d2fb
	  static const char color_off[] = "\e[0m";
Packit Service 97d2fb
	  while (*fmt != '\0')
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	      if (*fmt != '%')
Packit Service 97d2fb
		{
Packit Service 97d2fb
		  char ch = *fmt++;
Packit Service 97d2fb
		  if (ch == '\\')
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      switch ((ch = *fmt++))
Packit Service 97d2fb
			{
Packit Service 97d2fb
			case '0' ... '7':
Packit Service 97d2fb
			  {
Packit Service 97d2fb
			    int val = ch - '0';
Packit Service 97d2fb
			    ch = *fmt;
Packit Service 97d2fb
			    if (ch >= '0' && ch <= '7')
Packit Service 97d2fb
			      {
Packit Service 97d2fb
				val *= 8;
Packit Service 97d2fb
				val += ch - '0';
Packit Service 97d2fb
				ch = *++fmt;
Packit Service 97d2fb
				if (ch >= '0' && ch <= '7' && val < 32)
Packit Service 97d2fb
				  {
Packit Service 97d2fb
				    val *= 8;
Packit Service 97d2fb
				    val += ch - '0';
Packit Service 97d2fb
				    ++fmt;
Packit Service 97d2fb
				  }
Packit Service 97d2fb
			      }
Packit Service 97d2fb
			    ch = val;
Packit Service 97d2fb
			  }
Packit Service 97d2fb
			  break;
Packit Service 97d2fb
Packit Service 97d2fb
			case 'n':
Packit Service 97d2fb
			  ch = '\n';
Packit Service 97d2fb
			  break;
Packit Service 97d2fb
Packit Service 97d2fb
			case 't':
Packit Service 97d2fb
			  ch = '\t';
Packit Service 97d2fb
			  break;
Packit Service 97d2fb
Packit Service 97d2fb
			default:
Packit Service 97d2fb
			  retval = EINVAL;
Packit Service 97d2fb
			  goto do_ret;
Packit Service 97d2fb
			}
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else if (ch == '\e' && *fmt == '[')
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      deferred_start = fmt - 1;
Packit Service 97d2fb
		      do
Packit Service 97d2fb
			++fmt;
Packit Service 97d2fb
		      while (*fmt != 'm' && *fmt != '\0');
Packit Service 97d2fb
Packit Service 97d2fb
		      if (*fmt == 'm')
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  deferred_len = ++fmt - deferred_start;
Packit Service 97d2fb
			  continue;
Packit Service 97d2fb
			}
Packit Service 97d2fb
Packit Service 97d2fb
		      fmt = deferred_start + 1;
Packit Service 97d2fb
		      deferred_start = NULL;
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  ADD_CHAR (ch);
Packit Service 97d2fb
		  continue;
Packit Service 97d2fb
		}
Packit Service 97d2fb
	      ++fmt;
Packit Service 97d2fb
Packit Service 97d2fb
	      int width = 0;
Packit Service 97d2fb
	      while (isdigit (*fmt))
Packit Service 97d2fb
		width = width * 10 + (*fmt++ - '0');
Packit Service 97d2fb
Packit Service 97d2fb
	      int prec = 0;
Packit Service 97d2fb
	      if (*fmt == '.')
Packit Service 97d2fb
		while (isdigit (*++fmt))
Packit Service 97d2fb
		  prec = prec * 10 + (*fmt - '0');
Packit Service 97d2fb
Packit Service 97d2fb
	      size_t start_idx = bufcnt;
Packit Service 97d2fb
	      size_t non_printing = 0;
Packit Service 97d2fb
	      switch (*fmt++)
Packit Service 97d2fb
		{
Packit Service 97d2fb
		case 'm':
Packit Service 97d2fb
		  if (deferred_start != NULL)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      ADD_NSTRING (deferred_start, deferred_len);
Packit Service 97d2fb
		      non_printing += deferred_len;
Packit Service 97d2fb
		    }
Packit Service 97d2fb
Packit Service 97d2fb
		  ADD_STRING (mne);
Packit Service 97d2fb
Packit Service 97d2fb
		  if (deferred_start != NULL)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      ADD_STRING (color_off);
Packit Service 97d2fb
		      non_printing += strlen (color_off);
Packit Service 97d2fb
		    }
Packit Service 97d2fb
Packit Service 97d2fb
		  string_end_idx = bufcnt;
Packit Service 97d2fb
		  break;
Packit Service 97d2fb
Packit Service 97d2fb
		case 'o':
Packit Service 97d2fb
		  if (op[prec - 1] != NULL)
Packit Service 97d2fb
		    {
Packit Service 97d2fb
		      if (deferred_start != NULL)
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  ADD_NSTRING (deferred_start, deferred_len);
Packit Service 97d2fb
			  non_printing += deferred_len;
Packit Service 97d2fb
			}
Packit Service 97d2fb
Packit Service 97d2fb
		      ADD_STRING (op[prec - 1]);
Packit Service 97d2fb
Packit Service 97d2fb
		      if (deferred_start != NULL)
Packit Service 97d2fb
			{
Packit Service 97d2fb
			  ADD_STRING (color_off);
Packit Service 97d2fb
			  non_printing += strlen (color_off);
Packit Service 97d2fb
			}
Packit Service 97d2fb
Packit Service 97d2fb
		      string_end_idx = bufcnt;
Packit Service 97d2fb
		    }
Packit Service 97d2fb
		  else
Packit Service 97d2fb
		    bufcnt = string_end_idx;
Packit Service 97d2fb
		  break;
Packit Service 97d2fb
Packit Service 97d2fb
		case 'e':
Packit Service 97d2fb
		  string_end_idx = bufcnt;
Packit Service 97d2fb
		  break;
Packit Service 97d2fb
Packit Service 97d2fb
		case 'a':
Packit Service 97d2fb
		  /* Pad to requested column.  */
Packit Service 97d2fb
		  while (bufcnt - non_printing < (size_t) width)
Packit Service 97d2fb
		    ADD_CHAR (' ');
Packit Service 97d2fb
		  width = 0;
Packit Service 97d2fb
		  break;
Packit Service 97d2fb
Packit Service 97d2fb
		case 'l':
Packit Service 97d2fb
		  // TODO
Packit Service 97d2fb
		  break;
Packit Service 97d2fb
Packit Service 97d2fb
		default:
Packit Service 97d2fb
		  abort();
Packit Service 97d2fb
		}
Packit Service 97d2fb
Packit Service 97d2fb
	      /* Pad according to the specified width.  */
Packit Service 97d2fb
	      while (bufcnt - non_printing < start_idx + width)
Packit Service 97d2fb
		ADD_CHAR (' ');
Packit Service 97d2fb
	    }
Packit Service 97d2fb
Packit Service 97d2fb
	  strp = buf;
Packit Service 97d2fb
	  len = bufcnt;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      addr += length;
Packit Service 97d2fb
      *startp = data + length;
Packit Service 97d2fb
      retval = outcb (strp, len, outcbarg);
Packit Service 97d2fb
      if (retval != 0)
Packit Service 97d2fb
	break;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
 do_ret:
Packit Service 97d2fb
  if (buf != initbuf)
Packit Service 97d2fb
    free (buf);
Packit Service 97d2fb
Packit Service 97d2fb
  return retval;
Packit Service 97d2fb
}