Rizin
unix-like reverse engineering framework and cli tools
nios2-dis.c File Reference
#include "sysdep.h"
#include "disas-asm.h"
#include "opcode/nios2.h"
#include "libiberty.h"
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include "elf-bfd.h"

Go to the source code of this file.

Classes

struct  _nios2_opcode_hash
 

Macros

#define SYMTAB_AVAILABLE   1
 
#define INSNLEN   4
 
#define NUMREGNAMES   32
 

Typedefs

typedef struct _nios2_opcode_hash nios2_opcode_hash
 

Functions

static void nios2_init_opcode_hash (void)
 
const struct nios2_opcodenios2_find_opcode_hash (unsigned long opcode)
 
static struct nios2_regnios2_coprocessor_regs (void)
 
static struct nios2_regnios2_control_regs (void)
 
static int nios2_print_insn_arg (const char *argptr, unsigned long opcode, bfd_vma address, disassemble_info *info)
 
static int nios2_disassemble (bfd_vma address, unsigned long opcode, disassemble_info *info)
 
static int print_insn_nios2 (bfd_vma address, disassemble_info *info, enum bfd_endian endianness)
 
int print_insn_big_nios2 (bfd_vma address, disassemble_info *info)
 
int print_insn_little_nios2 (bfd_vma address, disassemble_info *info)
 

Variables

static bfd_boolean nios2_hash_init = 0
 
static nios2_opcode_hashnios2_hash [(OP_MASK_OP)+1]
 
static nios2_opcode_hashnios2_ps_hash [(OP_MASK_OP)+1]
 

Macro Definition Documentation

◆ INSNLEN

#define INSNLEN   4

Definition at line 40 of file nios2-dis.c.

◆ NUMREGNAMES

#define NUMREGNAMES   32

Definition at line 156 of file nios2-dis.c.

◆ SYMTAB_AVAILABLE

#define SYMTAB_AVAILABLE   1

Definition at line 34 of file nios2-dis.c.

Typedef Documentation

◆ nios2_opcode_hash

Function Documentation

◆ nios2_control_regs()

static struct nios2_reg* nios2_control_regs ( void  )
static

Definition at line 180 of file nios2-dis.c.

181 {
182  static struct nios2_reg *cached = NULL;
183 
184  if (!cached)
185  {
186  int i;
187  for (i = NUMREGNAMES; i < nios2_num_regs; i++) {
188  if (!strcmp (nios2_regs[i].name, "status")) {
189  cached = nios2_regs + i;
190  break;
191  }
192  }
193  assert (cached);
194  }
195  return cached;
196 }
lzma_index ** i
Definition: index.h:629
#define NULL
Definition: cris-opc.c:27
assert(limit<=UINT32_MAX/2)
#define NUMREGNAMES
Definition: nios2-dis.c:156
struct nios2_reg * nios2_regs
Definition: nios2-opc.c:169
int nios2_num_regs
Definition: nios2-opc.c:170
Definition: z80asm.h:102

References assert(), i, nios2_num_regs, nios2_regs, NULL, and NUMREGNAMES.

Referenced by nios2_print_insn_arg().

◆ nios2_coprocessor_regs()

static struct nios2_reg* nios2_coprocessor_regs ( void  )
static

Definition at line 160 of file nios2-dis.c.

161 {
162  static struct nios2_reg *cached = NULL;
163 
164  if (!cached)
165  {
166  int i;
167  for (i = NUMREGNAMES; i < nios2_num_regs; i++) {
168  if (!strcmp (nios2_regs[i].name, "c0")) {
169  cached = nios2_regs + i;
170  break;
171  }
172  }
173  assert (cached);
174  }
175  return cached;
176 }

References assert(), i, nios2_num_regs, nios2_regs, NULL, and NUMREGNAMES.

Referenced by nios2_print_insn_arg().

◆ nios2_disassemble()

static int nios2_disassemble ( bfd_vma  address,
unsigned long  opcode,
disassemble_info info 
)
static

Definition at line 321 of file nios2-dis.c.

323 {
324  const struct nios2_opcode *op;
325 
326  info->bytes_per_line = INSNLEN;
327  info->bytes_per_chunk = INSNLEN;
328  info->display_endian = info->endian;
329  info->insn_info_valid = 1;
330  info->branch_delay_insns = 0;
331  info->data_size = 0;
332  info->insn_type = dis_nonbranch;
333  info->target = 0;
334  info->target2 = 0;
335 
336  /* Find the major opcode and use this to disassemble
337  the instruction and its arguments. */
338  op = nios2_find_opcode_hash (opcode);
339 
340  if (op != NULL)
341  {
342  bfd_boolean is_nop = FALSE;
343  if (op->pinfo == NIOS2_INSN_MACRO_MOV)
344  {
345  /* Check for mov r0, r0 and change to nop. */
346  int dst, src;
347  dst = GET_INSN_FIELD (RRD, opcode);
348  src = GET_INSN_FIELD (RRS, opcode);
349  if (dst == 0 && src == 0)
350  {
351  (*info->fprintf_func) (info->stream, "nop");
352  is_nop = TRUE;
353  } else {
354  (*info->fprintf_func) (info->stream, "%s", op->name);
355  }
356  } else {
357  (*info->fprintf_func) (info->stream, "%s", op->name);
358  }
359 
360  if (!is_nop)
361  {
362  const char *argstr = op->args;
363  if (argstr != NULL && *argstr != '\0')
364  {
365  (*info->fprintf_func) (info->stream, " ");
366  while (*argstr != '\0')
367  {
368  nios2_print_insn_arg (argstr, opcode, address, info);
369  ++argstr;
370  }
371  }
372  }
373  }
374  else
375  {
376  /* Handle undefined instructions. */
377  info->insn_type = dis_noninsn;
378  (*info->fprintf_func) (info->stream, "0x%lx", opcode);
379  }
380  /* Tell the caller how far to advance the program counter. */
381  return INSNLEN;
382 }
ut8 op
Definition: 6502dis.c:13
lzma_index * src
Definition: index.h:567
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
@ dis_noninsn
Definition: disas-asm.h:48
@ dis_nonbranch
Definition: disas-asm.h:49
char * dst
Definition: lz4.h:724
int bfd_boolean
Definition: mybfd.h:98
#define TRUE
Definition: mybfd.h:103
#define FALSE
Definition: mybfd.h:102
#define INSNLEN
Definition: nios2-dis.c:40
const struct nios2_opcode * nios2_find_opcode_hash(unsigned long opcode)
Definition: nios2-dis.c:126
static int nios2_print_insn_arg(const char *argptr, unsigned long opcode, bfd_vma address, disassemble_info *info)
Definition: nios2-dis.c:202
#define GET_INSN_FIELD(X, i)
Definition: nios2.h:126
#define NIOS2_INSN_MACRO_MOV
Definition: nios2.h:102
Definition: dis.c:32

References dis_nonbranch, dis_noninsn, dst, FALSE, GET_INSN_FIELD, info(), INSNLEN, nios2_find_opcode_hash(), NIOS2_INSN_MACRO_MOV, nios2_print_insn_arg(), NULL, op, src, and TRUE.

Referenced by print_insn_nios2().

◆ nios2_find_opcode_hash()

const struct nios2_opcode* nios2_find_opcode_hash ( unsigned long  opcode)

Definition at line 126 of file nios2-dis.c.

127 {
129 
130  /* Build a hash table to shorten the search time. */
131  if (!nios2_hash_init) {
133  }
134 
135  /* First look in the pseudo-op hashtable. */
136  for (entry = nios2_ps_hash[(opcode >> OP_SH_OP) & OP_MASK_OP];
137  entry; entry = entry->next) {
138  if (entry->opcode->match == (opcode & entry->opcode->mask)) {
139  return entry->opcode;
140  }
141  }
142 
143  /* Otherwise look in the main hashtable. */
144  for (entry = nios2_hash[(opcode >> OP_SH_OP) & OP_MASK_OP];
145  entry; entry = entry->next) {
146  if (entry->opcode->match == (opcode & entry->opcode->mask)) {
147  return entry->opcode;
148  }
149  }
150 
151  return NULL;
152 }
#define OP_MASK_OP
Definition: mips.h:64
#define OP_SH_OP
Definition: mips.h:65
static void nios2_init_opcode_hash(void)
Definition: nios2-dis.c:57
static nios2_opcode_hash * nios2_ps_hash[(OP_MASK_OP)+1]
Definition: nios2-dis.c:53
static bfd_boolean nios2_hash_init
Definition: nios2-dis.c:49
static nios2_opcode_hash * nios2_hash[(OP_MASK_OP)+1]
Definition: nios2-dis.c:50
Definition: zipcmp.c:77

References nios2_hash, nios2_hash_init, nios2_init_opcode_hash(), nios2_ps_hash, NULL, OP_MASK_OP, and OP_SH_OP.

Referenced by nios2_disassemble().

◆ nios2_init_opcode_hash()

static void nios2_init_opcode_hash ( void  )
static

Definition at line 57 of file nios2-dis.c.

58 {
59  unsigned int i;
60  register const struct nios2_opcode *op;
61 
62  for (i = 0; i <= OP_MASK_OP; ++i) {
63  nios2_hash[0] = NULL;
64  }
65  for (i = 0; i <= OP_MASK_OP; i++) {
66  for (op = nios2_opcodes; op < &nios2_opcodes[NUMOPCODES]; op++) {
67  nios2_opcode_hash *new_hash;
68  nios2_opcode_hash **bucket = NULL;
69 
70  if ((op->pinfo & NIOS2_INSN_MACRO) == NIOS2_INSN_MACRO) {
71  if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP) && (op->pinfo & (NIOS2_INSN_MACRO_MOV | NIOS2_INSN_MACRO_MOVI) & 0x7fffffff)) {
72  bucket = &(nios2_ps_hash[i]);
73  }
74  } else if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP)) {
75  bucket = &(nios2_hash[i]);
76  }
77 
78  if (bucket) {
79  new_hash =
81  if (!new_hash) {
82  fprintf (stderr,
83  "error allocating memory...broken disassembler\n");
84  abort ();
85  }
86  new_hash->opcode = op;
87  new_hash->next = NULL;
88  while (*bucket) {
89  bucket = &((*bucket)->next);
90  }
91  *bucket = new_hash;
92  }
93  }
94  }
95  nios2_hash_init = 1;
96 #ifdef DEBUG_HASHTABLE
97  for (i = 0; i <= OP_MASK_OP; ++i)
98  {
99  nios2_opcode_hash *tmp_hash = nios2_hash[i];
100  printf ("index: 0x%02X ops: ", i);
101  while (tmp_hash != NULL)
102  {
103  printf ("%s ", tmp_hash->opcode->name);
104  tmp_hash = tmp_hash->next;
105  }
106  printf ("\n");
107  }
108 
109  for (i = 0; i <= OP_MASK_OP; ++i)
110  {
111  nios2_opcode_hash *tmp_hash = nios2_ps_hash[i];
112  printf ("index: 0x%02X ops: ", i);
113  while (tmp_hash != NULL)
114  {
115  printf ("%s ", tmp_hash->opcode->name);
116  tmp_hash = tmp_hash->next;
117  }
118  printf ("\n");
119  }
120 #endif /* DEBUG_HASHTABLE */
121 }
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
#define NUMOPCODES
Definition: hppa.h:1079
void * malloc(size_t size)
Definition: malloc.c:123
#define NIOS2_INSN_MACRO
Definition: nios2.h:101
#define NIOS2_INSN_MACRO_MOVI
Definition: nios2.h:103
struct nios2_opcode * nios2_opcodes
Definition: nios2-opc.c:412
struct _nios2_opcode_hash * next
Definition: nios2-dis.c:46
const struct nios2_opcode * opcode
Definition: nios2-dis.c:45
const char * name
Definition: nios2.h:81

References i, malloc(), nios2_opcode::name, _nios2_opcode_hash::next, nios2_hash, nios2_hash_init, NIOS2_INSN_MACRO, NIOS2_INSN_MACRO_MOV, NIOS2_INSN_MACRO_MOVI, nios2_opcodes, nios2_ps_hash, NULL, NUMOPCODES, op, OP_MASK_OP, OP_SH_OP, _nios2_opcode_hash::opcode, and printf().

Referenced by nios2_find_opcode_hash().

◆ nios2_print_insn_arg()

static int nios2_print_insn_arg ( const char *  argptr,
unsigned long  opcode,
bfd_vma  address,
disassemble_info info 
)
static

Definition at line 202 of file nios2-dis.c.

205 {
206  unsigned long i = 0;
207  struct nios2_reg *reg_base;
208 
209  switch (*argptr)
210  {
211  case ',':
212  case '(':
213  case ')':
214  (*info->fprintf_func) (info->stream, "%c", *argptr);
215  break;
216  case 'd':
217  i = GET_INSN_FIELD (RRD, opcode);
218 
219  if (GET_INSN_FIELD (OP, opcode) == OP_MATCH_CUSTOM && GET_INSN_FIELD (CUSTOM_C, opcode) == 0) {
220  reg_base = nios2_coprocessor_regs ();
221  } else {
222  reg_base = nios2_regs;
223  }
224 
225  if (i < NUMREGNAMES) {
226  (*info->fprintf_func) (info->stream, "%s", reg_base[i].name);
227  } else {
228  (*info->fprintf_func) (info->stream, "unknown");
229  }
230  break;
231  case 's':
232  i = GET_INSN_FIELD (RRS, opcode);
233 
234  if (GET_INSN_FIELD (OP, opcode) == OP_MATCH_CUSTOM && GET_INSN_FIELD (CUSTOM_A, opcode) == 0) {
235  reg_base = nios2_coprocessor_regs ();
236  } else {
237  reg_base = nios2_regs;
238  }
239 
240  if (i < NUMREGNAMES) {
241  (*info->fprintf_func) (info->stream, "%s", reg_base[i].name);
242  } else {
243  (*info->fprintf_func) (info->stream, "unknown");
244  }
245  break;
246  case 't':
247  i = GET_INSN_FIELD (RRT, opcode);
248 
249  if (GET_INSN_FIELD (OP, opcode) == OP_MATCH_CUSTOM && GET_INSN_FIELD (CUSTOM_B, opcode) == 0) {
250  reg_base = nios2_coprocessor_regs ();
251  } else {
252  reg_base = nios2_regs;
253  }
254 
255  if (i < NUMREGNAMES) {
256  (*info->fprintf_func) (info->stream, "%s", reg_base[i].name);
257  } else {
258  (*info->fprintf_func) (info->stream, "unknown");
259  }
260  break;
261  case 'i':
262  /* 16-bit signed immediate. */
263  i = (int) (GET_INSN_FIELD (IMM16, opcode) << 16) >> 16;
264  (*info->fprintf_func) (info->stream, "%ld", i);
265  break;
266  case 'u':
267  /* 16-bit unsigned immediate. */
268  i = GET_INSN_FIELD (IMM16, opcode);
269  (*info->fprintf_func) (info->stream, "%ld", i);
270  break;
271  case 'o':
272  /* 16-bit signed immediate address offset. */
273  i = (int) (GET_INSN_FIELD (IMM16, opcode) << 16) >> 16;
274  address = address + 4 + i;
275  (*info->print_address_func) (address, info);
276  break;
277  case 'p':
278  /* 5-bit unsigned immediate. */
279  i = GET_INSN_FIELD (CACHE_OPX, opcode);
280  (*info->fprintf_func) (info->stream, "%ld", i);
281  break;
282  case 'j':
283  /* 5-bit unsigned immediate. */
284  i = GET_INSN_FIELD (IMM5, opcode);
285  (*info->fprintf_func) (info->stream, "%ld", i);
286  break;
287  case 'l':
288  /* 8-bit unsigned immediate. */
289  /* FIXME - not yet implemented */
290  i = GET_INSN_FIELD (CUSTOM_N, opcode);
291  (*info->fprintf_func) (info->stream, "%lu", i);
292  break;
293  case 'm':
294  /* 26-bit unsigned immediate. */
295  i = GET_INSN_FIELD (IMM26, opcode);
296  /* This translates to an address because it's only used in call
297  instructions. */
298  address = (address & 0xf0000000) | (i << 2);
299  (*info->print_address_func) (address, info);
300  break;
301  case 'c':
302  /* Control register index. */
303  i = GET_INSN_FIELD (IMM5, opcode);
304  reg_base = nios2_control_regs ();
305  (*info->fprintf_func) (info->stream, "%s", reg_base[i].name);
306  break;
307  case 'b':
308  i = GET_INSN_FIELD (IMM5, opcode);
309  (*info->fprintf_func) (info->stream, "%ld", i);
310  break;
311  default:
312  (*info->fprintf_func) (info->stream, "unknown");
313  break;
314  }
315  return 0;
316 }
#define OP(v, w, x, y, z)
static struct nios2_reg * nios2_coprocessor_regs(void)
Definition: nios2-dis.c:160
static struct nios2_reg * nios2_control_regs(void)
Definition: nios2-dis.c:180
#define OP_MATCH_CUSTOM
Definition: nios2.h:398
static int
Definition: sfsocketcall.h:114
#define IMM5(instr)
Definition: v810_disas.h:12

References GET_INSN_FIELD, i, IMM5, info(), int, nios2_reg::name, nios2_control_regs(), nios2_coprocessor_regs(), nios2_regs, NUMREGNAMES, OP, and OP_MATCH_CUSTOM.

Referenced by nios2_disassemble().

◆ print_insn_big_nios2()

int print_insn_big_nios2 ( bfd_vma  address,
disassemble_info info 
)

Definition at line 422 of file nios2-dis.c.

423 {
424  return print_insn_nios2 (address, info, BFD_ENDIAN_BIG);
425 }
@ BFD_ENDIAN_BIG
Definition: mybfd.h:4617
static int print_insn_nios2(bfd_vma address, disassemble_info *info, enum bfd_endian endianness)
Definition: nios2-dis.c:394

References BFD_ENDIAN_BIG, info(), and print_insn_nios2().

Referenced by disassemble().

◆ print_insn_little_nios2()

int print_insn_little_nios2 ( bfd_vma  address,
disassemble_info info 
)

Definition at line 428 of file nios2-dis.c.

429 {
430  return print_insn_nios2 (address, info, BFD_ENDIAN_LITTLE);
431 }
@ BFD_ENDIAN_LITTLE
Definition: mybfd.h:4618

References BFD_ENDIAN_LITTLE, info(), and print_insn_nios2().

Referenced by disassemble().

◆ print_insn_nios2()

static int print_insn_nios2 ( bfd_vma  address,
disassemble_info info,
enum bfd_endian  endianness 
)
static

Definition at line 394 of file nios2-dis.c.

396 {
398  int status;
399 
400  status = (*info->read_memory_func) (address, buffer, INSNLEN, info);
401  if (status == 0)
402  {
403  unsigned long insn;
404  if (endianness == BFD_ENDIAN_BIG) {
405  insn = (unsigned long)bfd_getb32 (buffer);
406  } else {
407  insn = (unsigned long)bfd_getl32 (buffer);
408  }
409  status = nios2_disassemble (address, insn, info);
410  }
411  else
412  {
413  (*info->memory_error_func) (status, address, info);
414  status = -1;
415  }
416  return status;
417 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags long
Definition: sflib.h:79
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
unsigned char bfd_byte
Definition: mybfd.h:176
static bfd_vma bfd_getb32(const void *p)
Definition: mybfd.h:4979
static bfd_vma bfd_getl32(const void *p)
Definition: mybfd.h:4990
static int nios2_disassemble(bfd_vma address, unsigned long opcode, disassemble_info *info)
Definition: nios2-dis.c:321
Definition: buffer.h:15

References BFD_ENDIAN_BIG, bfd_getb32(), bfd_getl32(), info(), INSNLEN, long, nios2_disassemble(), and status.

Referenced by print_insn_big_nios2(), and print_insn_little_nios2().

Variable Documentation

◆ nios2_hash

nios2_opcode_hash* nios2_hash[(OP_MASK_OP)+1]
static

Definition at line 50 of file nios2-dis.c.

Referenced by nios2_find_opcode_hash(), and nios2_init_opcode_hash().

◆ nios2_hash_init

bfd_boolean nios2_hash_init = 0
static

Definition at line 49 of file nios2-dis.c.

Referenced by nios2_find_opcode_hash(), and nios2_init_opcode_hash().

◆ nios2_ps_hash

nios2_opcode_hash* nios2_ps_hash[(OP_MASK_OP)+1]
static

Definition at line 53 of file nios2-dis.c.

Referenced by nios2_find_opcode_hash(), and nios2_init_opcode_hash().