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

Go to the source code of this file.

Classes

struct  sparc_opcode_hash
 

Macros

#define xmalloc   malloc
 
#define MASK_V9
 
#define V9_ONLY_P(insn)   (! ((insn)->architecture & ~MASK_V9))
 
#define V9_P(insn)   (((insn)->architecture & MASK_V9) != 0)
 
#define HASH_SIZE   256
 
#define HASH_INSN(INSN)    ((((INSN) >> 24) & 0xc0) | (((INSN) & opcode_bits[((INSN) >> 30) & 3]) >> 19))
 
#define SIGN_EXT(value, bits)
 
#define freg_names   (&reg_names[4 * 8])
 
#define X_RD(i)   (((i) >> 25) & 0x1f)
 
#define X_RS1(i)   (((i) >> 14) & 0x1f)
 
#define X_LDST_I(i)   (((i) >> 13) & 1)
 
#define X_ASI(i)   (((i) >> 5) & 0xff)
 
#define X_RS2(i)   (((i) >> 0) & 0x1f)
 
#define X_IMM(i, n)   (((i) >> 0) & ((1 << (n)) - 1))
 
#define X_SIMM(i, n)   SIGN_EXT (X_IMM ((i), (n)), (n))
 
#define X_DISP22(i)   (((i) >> 0) & 0x3fffff)
 
#define X_IMM22(i)   X_DISP22 (i)
 
#define X_DISP30(i)   (((i) >> 0) & 0x3fffffff)
 
#define X_DISP16(i)   (((((i) >> 20) & 3) << 14) | (((i) >> 0) & 0x3fff))
 
#define X_DISP19(i)   (((i) >> 0) & 0x7ffff)
 
#define X_MEMBAR(i)   ((i) & 0x7f)
 
#define reg(n)   (*info->fprintf_func) (stream, "%%%s", reg_names[n])
 
#define freg(n)   (*info->fprintf_func) (stream, "%%%s", freg_names[n])
 
#define fregx(n)   (*info->fprintf_func) (stream, "%%%s", freg_names[((n) & ~1) | (((n) & 1) << 5)])
 
#define creg(n)   (*info->fprintf_func) (stream, "%%c%u", (unsigned int) (n))
 

Typedefs

typedef struct sparc_opcode_hash sparc_opcode_hash
 

Functions

static int is_delayed_branch (unsigned long insn)
 
static int compute_arch_mask (unsigned long mach)
 
static int compare_opcodes (const void *a, const void *b)
 
static void build_hash_table (const sparc_opcode **opcode_table, sparc_opcode_hash **hash_table, int num_opcodes)
 
int print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
 

Variables

static const sparc_opcode ** sorted_opcodes
 
static int opcode_bits [4] = { 0x01c00000, 0x0, 0x01f80000, 0x01f80000 }
 
static sparc_opcode_hashopcode_hash_table [HASH_SIZE]
 
static char * reg_names []
 
static char * v9_priv_reg_names []
 
static char * v9_hpriv_reg_names []
 
static char * v9a_asr_reg_names []
 
static unsigned int current_arch_mask
 

Macro Definition Documentation

◆ creg

#define creg (   n)    (*info->fprintf_func) (stream, "%%c%u", (unsigned int) (n))

◆ freg

#define freg (   n)    (*info->fprintf_func) (stream, "%%%s", freg_names[n])

◆ freg_names

#define freg_names   (&reg_names[4 * 8])

Definition at line 95 of file sparc-dis.c.

◆ fregx

#define fregx (   n)    (*info->fprintf_func) (stream, "%%%s", freg_names[((n) & ~1) | (((n) & 1) << 5)])

◆ HASH_INSN

#define HASH_INSN (   INSN)     ((((INSN) >> 24) & 0xc0) | (((INSN) & opcode_bits[((INSN) >> 30) & 3]) >> 19))

Definition at line 63 of file sparc-dis.c.

◆ HASH_SIZE

#define HASH_SIZE   256

Definition at line 58 of file sparc-dis.c.

◆ MASK_V9

#define MASK_V9
Value:
@ SPARC_OPCODE_ARCH_V9B
Definition: sparc.h:52
@ SPARC_OPCODE_ARCH_V9
Definition: sparc.h:50
@ SPARC_OPCODE_ARCH_V9A
Definition: sparc.h:51

Definition at line 44 of file sparc-dis.c.

◆ reg

#define reg (   n)    (*info->fprintf_func) (stream, "%%%s", reg_names[n])

◆ SIGN_EXT

#define SIGN_EXT (   value,
  bits 
)
Value:
((((int)(value)) << ((8 * sizeof (int)) - (bits))) \
>> ((8 * sizeof (int)) - (bits)) )
int bits(struct state *s, int need)
Definition: blast.c:72
static int value
Definition: cmd_api.c:93
static int
Definition: sfsocketcall.h:114

Definition at line 74 of file sparc-dis.c.

◆ V9_ONLY_P

#define V9_ONLY_P (   insn)    (! ((insn)->architecture & ~MASK_V9))

Definition at line 48 of file sparc-dis.c.

◆ V9_P

#define V9_P (   insn)    (((insn)->architecture & MASK_V9) != 0)

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

◆ X_ASI

#define X_ASI (   i)    (((i) >> 5) & 0xff)

Definition at line 132 of file sparc-dis.c.

◆ X_DISP16

#define X_DISP16 (   i)    (((((i) >> 20) & 3) << 14) | (((i) >> 0) & 0x3fff))

Definition at line 141 of file sparc-dis.c.

◆ X_DISP19

#define X_DISP19 (   i)    (((i) >> 0) & 0x7ffff)

Definition at line 142 of file sparc-dis.c.

◆ X_DISP22

#define X_DISP22 (   i)    (((i) >> 0) & 0x3fffff)

Definition at line 136 of file sparc-dis.c.

◆ X_DISP30

#define X_DISP30 (   i)    (((i) >> 0) & 0x3fffffff)

Definition at line 138 of file sparc-dis.c.

◆ X_IMM

#define X_IMM (   i,
  n 
)    (((i) >> 0) & ((1 << (n)) - 1))

Definition at line 134 of file sparc-dis.c.

◆ X_IMM22

#define X_IMM22 (   i)    X_DISP22 (i)

Definition at line 137 of file sparc-dis.c.

◆ X_LDST_I

#define X_LDST_I (   i)    (((i) >> 13) & 1)

Definition at line 131 of file sparc-dis.c.

◆ X_MEMBAR

#define X_MEMBAR (   i)    ((i) & 0x7f)

Definition at line 143 of file sparc-dis.c.

◆ X_RD

#define X_RD (   i)    (((i) >> 25) & 0x1f)

Definition at line 129 of file sparc-dis.c.

◆ X_RS1

#define X_RS1 (   i)    (((i) >> 14) & 0x1f)

Definition at line 130 of file sparc-dis.c.

◆ X_RS2

#define X_RS2 (   i)    (((i) >> 0) & 0x1f)

Definition at line 133 of file sparc-dis.c.

◆ X_SIMM

#define X_SIMM (   i,
  n 
)    SIGN_EXT (X_IMM ((i), (n)), (n))

Definition at line 135 of file sparc-dis.c.

◆ xmalloc

#define xmalloc   malloc

Definition at line 23 of file sparc-dis.c.

Typedef Documentation

◆ sparc_opcode_hash

Function Documentation

◆ build_hash_table()

static void build_hash_table ( const sparc_opcode **  opcode_table,
sparc_opcode_hash **  hash_table,
int  num_opcodes 
)
static

Definition at line 420 of file sparc-dis.c.

423 {
424  int i;
425  int hash_count[HASH_SIZE];
426  static sparc_opcode_hash *hash_buf = NULL;
427 
428  /* Start at the end of the table and work backwards so that each
429  chain is sorted. */
430 
431  memset (hash_table, 0, HASH_SIZE * sizeof (hash_table[0]));
432  memset (hash_count, 0, HASH_SIZE * sizeof (hash_count[0]));
433  if (hash_buf != NULL) {
434  free (hash_buf);
435  }
436  hash_buf = calloc (sizeof (* hash_buf), num_opcodes);
437  if (!hash_buf) {
438  return;
439  }
440  for (i = num_opcodes - 1; i >= 0; --i)
441  {
442  int hash = HASH_INSN (opcode_table[i]->match);
443  sparc_opcode_hash *h = &hash_buf[i];
444 
445  h->next = hash_table[hash];
446  h->opcode = opcode_table[i];
447  hash_table[hash] = h;
448  ++hash_count[hash];
449  }
450 
451 #if 0 /* for debugging */
452  {
453  int min_count = num_opcodes, max_count = 0;
454  int total;
455 
456  for (i = 0; i < HASH_SIZE; i++)
457  {
458  if (hash_count[i] < min_count)
459  min_count = hash_count[i];
460  if (hash_count[i] > max_count)
461  max_count = hash_count[i];
462  total += hash_count[i];
463  }
464 
465  printf ("Opcode hash table stats: min %d, max %d, ave %f\n",
466  min_count, max_count, (double) total / HASH_SIZE);
467  }
468 #endif
469 }
lzma_index ** i
Definition: index.h:629
#define NULL
Definition: cris-opc.c:27
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
return memset(p, 0, total)
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
static size_t max_count
Definition: malloc.c:67
#define hash_table
#define h(i)
Definition: sha256.c:48
#define HASH_INSN(INSN)
Definition: sparc-dis.c:63
#define HASH_SIZE
Definition: sparc-dis.c:58
Definition: engine.c:71

References calloc(), free(), h, HASH_INSN, HASH_SIZE, hash_table, i, max_count, memset(), NULL, and printf().

Referenced by print_insn_sparc().

◆ compare_opcodes()

static int compare_opcodes ( const void *  a,
const void *  b 
)
static

Definition at line 262 of file sparc-dis.c.

263 {
264  sparc_opcode *op0 = * (sparc_opcode **) a;
265  sparc_opcode *op1 = * (sparc_opcode **) b;
266  unsigned long int match0 = op0->match, match1 = op1->match;
267  unsigned long int lose0 = op0->lose, lose1 = op1->lose;
268  register unsigned int i;
269 
270  /* If one (and only one) insn isn't supported by the current architecture,
271  prefer the one that is. If neither are supported, but they're both for
272  the same architecture, continue processing. Otherwise (both unsupported
273  and for different architectures), prefer lower numbered arch's (fudged
274  by comparing the bitmasks). */
275  if (op0->architecture & current_arch_mask)
276  {
277  if (!(op1->architecture & current_arch_mask)) {
278  return -1;
279  }
280  }
281  else
282  {
283  if (op1->architecture & current_arch_mask) {
284  return 1;
285  } else if (op0->architecture != op1->architecture) {
286  return op0->architecture - op1->architecture;
287  }
288  }
289 
290  /* If a bit is set in both match and lose, there is something
291  wrong with the opcode table. */
292  if (match0 & lose0)
293  {
294  fprintf
295  (stderr,
296  /* xgettext:c-format */
297  _("Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"),
298  op0->name, match0, lose0);
299  op0->lose &= ~op0->match;
300  lose0 = op0->lose;
301  }
302 
303  if (match1 & lose1)
304  {
305  fprintf
306  (stderr,
307  /* xgettext:c-format */
308  _("Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"),
309  op1->name, match1, lose1);
310  op1->lose &= ~op1->match;
311  lose1 = op1->lose;
312  }
313 
314  /* Because the bits that are variable in one opcode are constant in
315  another, it is important to order the opcodes in the right order. */
316  for (i = 0; i < 32; i++)
317  {
318  unsigned long int x = 1 << i;
319  int x0 = (match0 & x) != 0;
320  int x1 = (match1 & x) != 0;
321 
322  if (x0 != x1) {
323  return x1 - x0;
324  }
325  }
326 
327  for (i = 0; i < 32; i++)
328  {
329  unsigned long int x = 1 << i;
330  int x0 = (lose0 & x) != 0;
331  int x1 = (lose1 & x) != 0;
332 
333  if (x0 != x1) {
334  return x1 - x0;
335  }
336  }
337 
338  /* They are functionally equal. So as long as the opcode table is
339  valid, we can put whichever one first we want, on aesthetic grounds. */
340 
341  /* Our first aesthetic ground is that aliases defer to real insns. */
342  {
343  int alias_diff = (op0->flags & F_ALIAS) - (op1->flags & F_ALIAS);
344 
345  if (alias_diff != 0) {
346  /* Put the one that isn't an alias first. */
347  return alias_diff;
348  }
349  }
350 
351  /* Except for aliases, two "identical" instructions had
352  better have the same opcode. This is a sanity check on the table. */
353  i = strcmp (op0->name, op1->name);
354  if (i)
355  {
356  if (op0->flags & F_ALIAS) { /* If they're both aliases, be arbitrary. */
357  return i;
358  } else {
359  fprintf (stderr,
360  /* xgettext:c-format */
361  _ ("Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n"),
362  op0->name, op1->name);
363  }
364  }
365 
366  /* Fewer arguments are preferred. */
367  {
368  int length_diff = strlen (op0->args) - strlen (op1->args);
369 
370  if (length_diff != 0) {
371  /* Put the one with fewer arguments first. */
372  return length_diff;
373  }
374  }
375 
376  /* Put 1+i before i+1. */
377  {
378  char *p0 = (char *) strchr (op0->args, '+');
379  char *p1 = (char *) strchr (op1->args, '+');
380 
381  if (p0 && p1)
382  {
383  /* There is a plus in both operands. Note that a plus
384  sign cannot be the first character in args,
385  so the following [-1]'s are valid. */
386  if (p0[-1] == 'i' && p1[1] == 'i') {
387  /* op0 is i+1 and op1 is 1+i, so op1 goes first. */
388  return 1;
389  }
390  if (p0[1] == 'i' && p1[-1] == 'i') {
391  /* op0 is 1+i and op1 is i+1, so op0 goes first. */
392  return -1;
393  }
394  }
395  }
396 
397  /* Put 1,i before i,1. */
398  {
399  int i0 = strncmp (op0->args, "i,1", 3) == 0;
400  int i1 = strncmp (op1->args, "i,1", 3) == 0;
401 
402  if (i0 ^ i1) {
403  return i0 - i1;
404  }
405  }
406 
407  /* They are, as far as we can tell, identical.
408  Since qsort may have rearranged the table partially, there is
409  no way to tell which one was first in the opcode table as
410  written, so just say there are equal. */
411  /* ??? This is no longer true now that we sort a vector of pointers,
412  not the table itself. */
413  return 0;
414 }
#define F_ALIAS
Definition: aarch64.h:722
int x
Definition: mipsasm.c:20
#define _(String)
Definition: opintl.h:53
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
static unsigned int current_arch_mask
Definition: sparc-dis.c:225
short architecture
Definition: sparc.h:99
const char * name
Definition: sparc.h:93
unsigned long lose
Definition: sparc.h:95
unsigned long match
Definition: sparc.h:94
const char * args
Definition: sparc.h:96
char flags
Definition: sparc.h:98

References _, a, sparc_opcode::architecture, sparc_opcode::args, b, current_arch_mask, F_ALIAS, sparc_opcode::flags, i, i0, sparc_opcode::lose, sparc_opcode::match, sparc_opcode::name, x, x0, and x1.

Referenced by print_insn_sparc().

◆ compute_arch_mask()

static int compute_arch_mask ( unsigned long  mach)
static

Definition at line 230 of file sparc-dis.c.

231 {
232  switch (mach)
233  {
234  case 0 :
235  case bfd_mach_sparc :
241  /* sparclites insns are recognized by default (because that's how
242  they've always been treated, for better or worse). Kludge this by
243  indicating generic v8 is also selected. */
246  case bfd_mach_sparc_v8plus :
247  case bfd_mach_sparc_v9 :
250  case bfd_mach_sparc_v9a :
253  case bfd_mach_sparc_v9b :
255  }
256  abort ();
257 }
@ SPARC_OPCODE_ARCH_SPARCLITE
Definition: sparc.h:48
@ SPARC_OPCODE_ARCH_V8
Definition: sparc.h:46
@ SPARC_OPCODE_ARCH_SPARCLET
Definition: sparc.h:47
#define SPARC_OPCODE_ARCH_MASK(arch)
Definition: sparc.h:61
#define bfd_mach_sparc_sparclet
Definition: mybfd.h:1615
#define bfd_mach_sparc_v8plusa
Definition: mybfd.h:1618
#define bfd_mach_sparc_v8plusb
Definition: mybfd.h:1622
#define bfd_mach_sparc_v9b
Definition: mybfd.h:1623
#define bfd_mach_sparc_sparclite_le
Definition: mybfd.h:1619
#define bfd_mach_sparc_v8plus
Definition: mybfd.h:1617
#define bfd_mach_sparc_sparclite
Definition: mybfd.h:1616
#define bfd_mach_sparc_v9
Definition: mybfd.h:1620
#define bfd_mach_sparc
Definition: mybfd.h:1613
#define bfd_mach_sparc_v9a
Definition: mybfd.h:1621

References bfd_mach_sparc, bfd_mach_sparc_sparclet, bfd_mach_sparc_sparclite, bfd_mach_sparc_sparclite_le, bfd_mach_sparc_v8plus, bfd_mach_sparc_v8plusa, bfd_mach_sparc_v8plusb, bfd_mach_sparc_v9, bfd_mach_sparc_v9a, bfd_mach_sparc_v9b, SPARC_OPCODE_ARCH_MASK, SPARC_OPCODE_ARCH_SPARCLET, SPARC_OPCODE_ARCH_SPARCLITE, SPARC_OPCODE_ARCH_V8, SPARC_OPCODE_ARCH_V9, SPARC_OPCODE_ARCH_V9A, and SPARC_OPCODE_ARCH_V9B.

Referenced by print_insn_sparc().

◆ is_delayed_branch()

static int is_delayed_branch ( unsigned long  insn)
static

Definition at line 206 of file sparc-dis.c.

207 {
209 
210  for (op = opcode_hash_table[HASH_INSN (insn)]; op; op = op->next)
211  {
212  const sparc_opcode *opcode = op->opcode;
213 
214  if ((opcode->match & insn) == opcode->match && (opcode->lose & insn) == 0) {
215  return opcode->flags & F_DELAYED;
216  }
217  }
218  return 0;
219 }
ut8 op
Definition: 6502dis.c:13
#define F_DELAYED
Definition: sparc.h:102
static sparc_opcode_hash * opcode_hash_table[HASH_SIZE]
Definition: sparc-dis.c:71
Definition: dis.c:32

References F_DELAYED, sparc_opcode::flags, HASH_INSN, sparc_opcode::lose, sparc_opcode::match, op, sparc_opcode_hash::opcode, and opcode_hash_table.

Referenced by print_insn_sparc().

◆ print_insn_sparc()

int print_insn_sparc ( bfd_vma  memaddr,
disassemble_info info 
)

Definition at line 480 of file sparc-dis.c.

481 {
482  FILE *stream = info->stream;
483  bfd_byte buffer[4];
484  unsigned long insn;
486  /* Nonzero of opcode table has been initialized. */
487  static int opcodes_initialized = 0;
488  /* bfd mach number of last call. */
489  static unsigned long current_mach = 0;
490  bfd_vma (*getword) (const void *);
491 
492  if (!opcodes_initialized
493  || info->mach != current_mach)
494  {
495  int i;
496 
498 
499  if (!opcodes_initialized) {
501  xmalloc (sparc_num_opcodes * sizeof (sparc_opcode *));
502  }
503  /* Reset the sorted table so we can resort it. */
504  for (i = 0; i < sparc_num_opcodes; i++) {
506  }
508  sizeof (sorted_opcodes[0]), compare_opcodes);
509 
511  current_mach = info->mach;
512  opcodes_initialized = 1;
513  }
514 
515  {
516  int status =
517  (*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info);
518 
519  if (status != 0)
520  {
521  (*info->memory_error_func) (status, memaddr, info);
522  return -1;
523  }
524  }
525 
526  /* On SPARClite variants such as DANlite (sparc86x), instructions
527  are always big-endian even when the machine is in little-endian mode. */
528  if (info->endian == BFD_ENDIAN_BIG || info->mach == bfd_mach_sparc_sparclite) {
529  getword = bfd_getb32;
530  } else {
531  getword = bfd_getl32;
532  }
533 
534  insn = getword (buffer);
535 
536  info->insn_info_valid = 1; /* We do return this info. */
537  info->insn_type = dis_nonbranch; /* Assume non branch insn. */
538  info->branch_delay_insns = 0; /* Assume no delay. */
539  info->target = 0; /* Assume no target known. */
540 
541  for (op = opcode_hash_table[HASH_INSN (insn)]; op; op = op->next)
542  {
543  const sparc_opcode *opcode = op->opcode;
544 
545  /* If the insn isn't supported by the current architecture, skip it. */
546  if (!(opcode->architecture & current_arch_mask)) {
547  continue;
548  }
549 
550  if ((opcode->match & insn) == opcode->match
551  && (opcode->lose & insn) == 0)
552  {
553  /* Nonzero means that we have found an instruction which has
554  the effect of adding or or'ing the imm13 field to rs1. */
555  int imm_added_to_rs1 = 0;
556  int imm_ored_to_rs1 = 0;
557 
558  /* Nonzero means that we have found a plus sign in the args
559  field of the opcode table. */
560  int found_plus = 0;
561 
562  /* Nonzero means we have an annulled branch. */
563  int is_annulled = 0;
564 
565  /* Do we have an `add' or `or' instruction combining an
566  immediate with rs1? */
567  if (opcode->match == 0x80102000) { /* or */
568  imm_ored_to_rs1 = 1;
569  }
570  if (opcode->match == 0x80002000) { /* add */
571  imm_added_to_rs1 = 1;
572  }
573 
574  if (X_RS1 (insn) != X_RD (insn) && strchr (opcode->args, 'r') != 0) {
575  /* Can't do simple format if source and dest are different. */
576  continue;
577  }
578  if (X_RS2 (insn) != X_RD (insn) && strchr (opcode->args, 'O') != 0) {
579  /* Can't do simple format if source and dest are different. */
580  continue;
581  }
582 
583  (*info->fprintf_func) (stream, "%s", opcode->name);
584 
585  {
586  const char *s;
587  int brackets = 0;
588 
589  for (s = opcode->args; *s != '\0'; s++)
590  {
591  while (*s == ',')
592  {
593  (*info->fprintf_func) (stream, ",");
594  ++s;
595  switch (*s)
596  {
597  case 'a':
598  (*info->fprintf_func) (stream, "a");
599  is_annulled = 1;
600  ++s;
601  continue;
602  case 'N':
603  (*info->fprintf_func) (stream, "pn");
604  ++s;
605  continue;
606 
607  case 'T':
608  (*info->fprintf_func) (stream, "pt");
609  ++s;
610  continue;
611 
612  default:
613  break;
614  }
615  }
616 
617  if (*s != '[' && !brackets) {
618  (*info->fprintf_func) (stream, " ");
619  } else if (*s == ']') {
620  (*info->fprintf_func) (stream, "%c", *s);
621  brackets = 0;
622  continue;
623  } else if (*s == '[') {
624  (*info->fprintf_func) (stream, " %c", *s);
625  brackets = 1;
626  continue;
627  }
628 
629  switch (*s)
630  {
631  case '+':
632  found_plus = 1;
633  /* Fall through. */
634 
635  default:
636  (*info->fprintf_func) (stream, "%c", *s);
637  break;
638 
639  case '#':
640  (*info->fprintf_func) (stream, "0");
641  break;
642 
643 #define reg(n) (*info->fprintf_func) (stream, "%%%s", reg_names[n])
644  case '1':
645  case 'r':
646  reg (X_RS1 (insn));
647  break;
648 
649  case '2':
650  case 'O':
651  reg (X_RS2 (insn));
652  break;
653 
654  case 'd':
655  reg (X_RD (insn));
656  break;
657 #undef reg
658 
659 #define freg(n) (*info->fprintf_func) (stream, "%%%s", freg_names[n])
660 #define fregx(n) (*info->fprintf_func) (stream, "%%%s", freg_names[((n) & ~1) | (((n) & 1) << 5)])
661  case 'e':
662  freg (X_RS1 (insn));
663  break;
664  case 'v': /* Double/even. */
665  case 'V': /* Quad/multiple of 4. */
666  fregx (X_RS1 (insn));
667  break;
668 
669  case 'f':
670  freg (X_RS2 (insn));
671  break;
672  case 'B': /* Double/even. */
673  case 'R': /* Quad/multiple of 4. */
674  fregx (X_RS2 (insn));
675  break;
676 
677  case 'g':
678  freg (X_RD (insn));
679  break;
680  case 'H': /* Double/even. */
681  case 'J': /* Quad/multiple of 4. */
682  fregx (X_RD (insn));
683  break;
684 #undef freg
685 #undef fregx
686 
687 #define creg(n) (*info->fprintf_func) (stream, "%%c%u", (unsigned int) (n))
688  case 'b':
689  creg (X_RS1 (insn));
690  break;
691 
692  case 'c':
693  creg (X_RS2 (insn));
694  break;
695 
696  case 'D':
697  creg (X_RD (insn));
698  break;
699 #undef creg
700 
701  case 'h':
702  (*info->fprintf_func) (stream, "%%hi(%#x)",
703  ((unsigned) 0xFFFFFFFF
704  & ((int) X_IMM22 (insn) << 10)));
705  break;
706 
707  case 'i': /* 13 bit immediate. */
708  case 'I': /* 11 bit immediate. */
709  case 'j': /* 10 bit immediate. */
710  {
711  int imm;
712 
713  if (*s == 'i') {
714  imm = X_SIMM (insn, 13);
715  } else if (*s == 'I') {
716  imm = X_SIMM (insn, 11);
717  } else {
718  imm = X_SIMM (insn, 10);
719  }
720 
721  /* Check to see whether we have a 1+i, and take
722  note of that fact.
723 
724  Note: because of the way we sort the table,
725  we will be matching 1+i rather than i+1,
726  so it is OK to assume that i is after +,
727  not before it. */
728  if (found_plus) {
729  imm_added_to_rs1 = 1;
730  }
731 
732  if (imm <= 9) {
733  (*info->fprintf_func) (stream, "%d", imm);
734  } else {
735  (*info->fprintf_func) (stream, "%#x", imm);
736  }
737  }
738  break;
739 
740  case 'X': /* 5 bit unsigned immediate. */
741  case 'Y': /* 6 bit unsigned immediate. */
742  {
743  int imm = X_IMM (insn, *s == 'X' ? 5 : 6);
744 
745  if (imm <= 9) {
746  (info->fprintf_func) (stream, "%d", imm);
747  } else {
748  (info->fprintf_func) (stream, "%#x", (unsigned)imm);
749  }
750  }
751  break;
752 
753  case '3':
754  (info->fprintf_func) (stream, "%ld", X_IMM (insn, 3));
755  break;
756 
757  case 'K':
758  {
759  int mask = X_MEMBAR (insn);
760  int bit = 0x40, printed_one = 0;
761  const char *name;
762 
763  if (mask == 0) {
764  (info->fprintf_func) (stream, "0");
765  } else {
766  while (bit) {
767  if (mask & bit) {
768  if (printed_one) {
769  (info->fprintf_func) (stream, "|");
770  }
772  (info->fprintf_func) (stream, "%s", name);
773  printed_one = 1;
774  }
775  bit >>= 1;
776  }
777  }
778  break;
779  }
780 
781  case 'k':
782  info->target = memaddr + SIGN_EXT (X_DISP16 (insn), 16) * 4;
783  (*info->print_address_func) (info->target, info);
784  break;
785 
786  case 'G':
787  info->target = memaddr + SIGN_EXT (X_DISP19 (insn), 19) * 4;
788  (*info->print_address_func) (info->target, info);
789  break;
790 
791  case '6':
792  case '7':
793  case '8':
794  case '9':
795  (*info->fprintf_func) (stream, "%%fcc%c", *s - '6' + '0');
796  break;
797 
798  case 'z':
799  (*info->fprintf_func) (stream, "%%icc");
800  break;
801 
802  case 'Z':
803  (*info->fprintf_func) (stream, "%%xcc");
804  break;
805 
806  case 'E':
807  (*info->fprintf_func) (stream, "%%ccr");
808  break;
809 
810  case 's':
811  (*info->fprintf_func) (stream, "%%fprs");
812  break;
813 
814  case 'o':
815  (*info->fprintf_func) (stream, "%%asi");
816  break;
817 
818  case 'W':
819  (*info->fprintf_func) (stream, "%%tick");
820  break;
821 
822  case 'P':
823  (*info->fprintf_func) (stream, "%%pc");
824  break;
825 
826  case '?':
827  if (X_RS1 (insn) == 31) {
828  (*info->fprintf_func) (stream, "%%ver");
829  } else if ((unsigned)X_RS1 (insn) < 17) {
830  (*info->fprintf_func) (stream, "%%%s",
831  v9_priv_reg_names[X_RS1 (insn)]);
832  } else {
833  (*info->fprintf_func) (stream, "%%reserved");
834  }
835  break;
836 
837  case '!':
838  if ((unsigned)X_RD (insn) < 17) {
839  (*info->fprintf_func) (stream, "%%%s",
840  v9_priv_reg_names[X_RD (insn)]);
841  } else {
842  (*info->fprintf_func) (stream, "%%reserved");
843  }
844  break;
845 
846  case '$':
847  if ((unsigned)X_RS1 (insn) < 32) {
848  (*info->fprintf_func) (stream, "%%%s",
849  v9_hpriv_reg_names[X_RS1 (insn)]);
850  } else {
851  (*info->fprintf_func) (stream, "%%reserved");
852  }
853  break;
854 
855  case '%':
856  if ((unsigned)X_RD (insn) < 32) {
857  (*info->fprintf_func) (stream, "%%%s",
858  v9_hpriv_reg_names[X_RD (insn)]);
859  } else {
860  (*info->fprintf_func) (stream, "%%reserved");
861  }
862  break;
863 
864  case '/':
865  if (X_RS1 (insn) < 16 || X_RS1 (insn) > 25) {
866  (*info->fprintf_func) (stream, "%%reserved");
867  } else {
868  (*info->fprintf_func) (stream, "%%%s",
869  v9a_asr_reg_names[X_RS1 (insn) - 16]);
870  }
871  break;
872 
873  case '_':
874  if (X_RD (insn) < 16 || X_RD (insn) > 25) {
875  (*info->fprintf_func) (stream, "%%reserved");
876  } else {
877  (*info->fprintf_func) (stream, "%%%s",
878  v9a_asr_reg_names[X_RD (insn) - 16]);
879  }
880  break;
881 
882  case '*':
883  {
884  const char *name = sparc_decode_prefetch (X_RD (insn));
885 
886  if (name) {
887  (*info->fprintf_func) (stream, "%s", name);
888  } else {
889  (*info->fprintf_func) (stream, "%ld", X_RD (insn));
890  }
891  break;
892  }
893 
894  case 'M':
895  (*info->fprintf_func) (stream, "%%asr%ld", X_RS1 (insn));
896  break;
897 
898  case 'm':
899  (*info->fprintf_func) (stream, "%%asr%ld", X_RD (insn));
900  break;
901 
902  case 'L':
903  info->target = memaddr + SIGN_EXT (X_DISP30 (insn), 30) * 4;
904  (*info->print_address_func) (info->target, info);
905  break;
906 
907  case 'n':
908  (*info->fprintf_func)
909  (stream, "%#x", SIGN_EXT (X_DISP22 (insn), 22));
910  break;
911 
912  case 'l':
913  info->target = memaddr + SIGN_EXT (X_DISP22 (insn), 22) * 4;
914  (*info->print_address_func) (info->target, info);
915  break;
916 
917  case 'A':
918  {
919  const char *name = sparc_decode_asi (X_ASI (insn));
920 
921  if (name) {
922  (*info->fprintf_func) (stream, "%s", name);
923  } else {
924  (*info->fprintf_func) (stream, "(%ld)", X_ASI (insn));
925  }
926  break;
927  }
928 
929  case 'C':
930  (*info->fprintf_func) (stream, "%%csr");
931  break;
932 
933  case 'F':
934  (*info->fprintf_func) (stream, "%%fsr");
935  break;
936 
937  case 'p':
938  (*info->fprintf_func) (stream, "%%psr");
939  break;
940 
941  case 'q':
942  (*info->fprintf_func) (stream, "%%fq");
943  break;
944 
945  case 'Q':
946  (*info->fprintf_func) (stream, "%%cq");
947  break;
948 
949  case 't':
950  (*info->fprintf_func) (stream, "%%tbr");
951  break;
952 
953  case 'w':
954  (*info->fprintf_func) (stream, "%%wim");
955  break;
956 
957  case 'x':
958  (*info->fprintf_func) (stream, "%ld",
959  ((X_LDST_I (insn) << 8)
960  + X_ASI (insn)));
961  break;
962 
963  case 'y':
964  (*info->fprintf_func) (stream, "%%y");
965  break;
966 
967  case 'u':
968  case 'U':
969  {
970  int val = *s == 'U' ? X_RS1 (insn) : X_RD (insn);
971  const char *name = sparc_decode_sparclet_cpreg (val);
972 
973  if (name) {
974  (*info->fprintf_func) (stream, "%s", name);
975  } else {
976  (*info->fprintf_func) (stream, "%%cpreg(%d)", val);
977  }
978  break;
979  }
980  }
981  }
982  }
983 
984  /* If we are adding or or'ing something to rs1, then
985  check to see whether the previous instruction was
986  a sethi to the same register as in the sethi.
987  If so, attempt to print the result of the add or
988  or (in this context add and or do the same thing)
989  and its symbolic value. */
990  if (imm_ored_to_rs1 || imm_added_to_rs1)
991  {
992  unsigned long prev_insn;
993  int errcode;
994 
995  if (memaddr >= 4) {
996  errcode =
997  (*info->read_memory_func) (memaddr - 4, buffer, sizeof (buffer), info);
998  } else {
999  errcode = 1;
1000  }
1001 
1002  prev_insn = getword (buffer);
1003 
1004  if (errcode == 0)
1005  {
1006  /* If it is a delayed branch, we need to look at the
1007  instruction before the delayed branch. This handles
1008  sequences such as:
1009 
1010  sethi %o1, %hi(_foo), %o1
1011  call _printf
1012  or %o1, %lo(_foo), %o1 */
1013 
1014  if (is_delayed_branch (prev_insn))
1015  {
1016  if (memaddr >= 8) {
1017  errcode = (*info->read_memory_func) (memaddr - 8, buffer, sizeof (buffer), info);
1018  } else {
1019  errcode = 1;
1020  }
1021 
1022  prev_insn = getword (buffer);
1023  }
1024  }
1025 
1026  /* If there was a problem reading memory, then assume
1027  the previous instruction was not sethi. */
1028  if (errcode == 0)
1029  {
1030  /* Is it sethi to the same register? */
1031  if ((prev_insn & 0xc1c00000) == 0x01000000
1032  && X_RD (prev_insn) == X_RS1 (insn))
1033  {
1034  (*info->fprintf_func) (stream, "\t! ");
1035  info->target =
1036  ((unsigned) 0xFFFFFFFF
1037  & ((int) X_IMM22 (prev_insn) << 10));
1038  if (imm_added_to_rs1) {
1039  info->target += X_SIMM (insn, 13);
1040  } else {
1041  info->target |= X_SIMM (insn, 13);
1042  }
1043  (*info->print_address_func) (info->target, info);
1044  info->insn_type = dis_dref;
1045  info->data_size = 4; /* FIXME!!! */
1046  }
1047  }
1048  }
1049 
1050  if (opcode->flags & (F_UNBR|F_CONDBR|F_JSR))
1051  {
1052  /* FIXME -- check is_annulled flag. */
1053  (void) is_annulled;
1054  if (opcode->flags & F_UNBR) {
1055  info->insn_type = dis_branch;
1056  }
1057  if (opcode->flags & F_CONDBR) {
1058  info->insn_type = dis_condbranch;
1059  }
1060  if (opcode->flags & F_JSR) {
1061  info->insn_type = dis_jsr;
1062  }
1063  if (opcode->flags & F_DELAYED) {
1064  info->branch_delay_insns = 1;
1065  }
1066  }
1067 
1068  return sizeof (buffer);
1069  }
1070  }
1071 
1072  info->insn_type = dis_noninsn; /* Mark as non-valid instruction. */
1073  (*info->fprintf_func) (stream, _("unknown"));
1074  return sizeof (buffer);
1075 }
#define mask()
#define imm
ut16 val
Definition: armass64_const.h:6
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
struct buffer buffer
RzCryptoSelector bit
Definition: crypto.c:16
@ dis_dref
Definition: disas-asm.h:54
@ dis_noninsn
Definition: disas-asm.h:48
@ dis_nonbranch
Definition: disas-asm.h:49
@ dis_condbranch
Definition: disas-asm.h:51
@ dis_jsr
Definition: disas-asm.h:52
@ dis_branch
Definition: disas-asm.h:50
voidpf stream
Definition: ioapi.h:138
#define F_UNBR
Definition: lanai.h:126
#define F_CONDBR
Definition: lanai.h:125
#define F_JSR
Definition: lanai.h:100
const int sparc_num_opcodes
Definition: sparc-opc.c:1831
const char * sparc_decode_asi(int)
Definition: sparc-opc.c:2051
const struct sparc_opcode sparc_opcodes[]
Definition: sparc-opc.c:177
const char * sparc_decode_membar(int)
Definition: sparc-opc.c:2081
const char * sparc_decode_prefetch(int)
Definition: sparc-opc.c:2115
const char * sparc_decode_sparclet_cpreg(int)
Definition: sparc-opc.c:2145
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
static void struct sockaddr socklen_t static fromlen static backlog static fork char char char static envp int struct rusage static rusage struct utsname static buf struct sembuf unsigned
Definition: sflib.h:97
unsigned char bfd_byte
Definition: mybfd.h:176
BFD_HOST_U_64_BIT bfd_vma
Definition: mybfd.h:111
static bfd_vma bfd_getb32(const void *p)
Definition: mybfd.h:4979
@ BFD_ENDIAN_BIG
Definition: mybfd.h:4617
static bfd_vma bfd_getl32(const void *p)
Definition: mybfd.h:4990
string FILE
Definition: benchmark.py:21
const char * name
Definition: op.c:541
void qsort(void *a, size_t n, size_t es, int(*cmp)(const void *, const void *))
Definition: qsort.h:130
static RzSocket * s
Definition: rtr.c:28
#define fregx(n)
#define X_MEMBAR(i)
Definition: sparc-dis.c:143
static int compare_opcodes(const void *a, const void *b)
Definition: sparc-dis.c:262
#define X_DISP30(i)
Definition: sparc-dis.c:138
#define X_RS2(i)
Definition: sparc-dis.c:133
static int is_delayed_branch(unsigned long insn)
Definition: sparc-dis.c:206
#define xmalloc
Definition: sparc-dis.c:23
#define X_DISP22(i)
Definition: sparc-dis.c:136
static void build_hash_table(const sparc_opcode **opcode_table, sparc_opcode_hash **hash_table, int num_opcodes)
Definition: sparc-dis.c:420
#define creg(n)
#define X_DISP16(i)
Definition: sparc-dis.c:141
#define X_RD(i)
Definition: sparc-dis.c:129
#define X_LDST_I(i)
Definition: sparc-dis.c:131
#define X_SIMM(i, n)
Definition: sparc-dis.c:135
static int compute_arch_mask(unsigned long mach)
Definition: sparc-dis.c:230
#define reg(n)
#define X_RS1(i)
Definition: sparc-dis.c:130
#define SIGN_EXT(value, bits)
Definition: sparc-dis.c:74
#define X_DISP19(i)
Definition: sparc-dis.c:142
#define freg(n)
#define X_ASI(i)
Definition: sparc-dis.c:132
#define X_IMM22(i)
Definition: sparc-dis.c:137
static char * v9_priv_reg_names[]
Definition: sparc-dis.c:99
static char * v9a_asr_reg_names[]
Definition: sparc-dis.c:120
static char * v9_hpriv_reg_names[]
Definition: sparc-dis.c:109
static const sparc_opcode ** sorted_opcodes
Definition: sparc-dis.c:53
#define X_IMM(i, n)
Definition: sparc-dis.c:134
Definition: buffer.h:15
Definition: z80asm.h:102

References _, sparc_opcode::architecture, sparc_opcode::args, BFD_ENDIAN_BIG, bfd_getb32(), bfd_getl32(), bfd_mach_sparc_sparclite, bit, build_hash_table(), compare_opcodes(), compute_arch_mask(), creg, current_arch_mask, dis_branch, dis_condbranch, dis_dref, dis_jsr, dis_nonbranch, dis_noninsn, F_CONDBR, F_DELAYED, F_JSR, F_UNBR, benchmark::FILE, sparc_opcode::flags, freg, fregx, HASH_INSN, i, imm, info(), is_delayed_branch(), sparc_opcode::lose, mask, sparc_opcode::match, name, sparc_opcode::name, op, sparc_opcode_hash::opcode, opcode_hash_table, qsort(), reg, s, SIGN_EXT, sorted_opcodes, sparc_decode_asi(), sparc_decode_membar(), sparc_decode_prefetch(), sparc_decode_sparclet_cpreg(), sparc_num_opcodes, sparc_opcodes, status, unsigned, v9_hpriv_reg_names, v9_priv_reg_names, v9a_asr_reg_names, val, X_ASI, X_DISP16, X_DISP19, X_DISP22, X_DISP30, X_IMM, X_IMM22, X_LDST_I, X_MEMBAR, X_RD, X_RS1, X_RS2, X_SIMM, and xmalloc.

Referenced by disassemble().

Variable Documentation

◆ current_arch_mask

unsigned int current_arch_mask
static

Definition at line 225 of file sparc-dis.c.

Referenced by compare_opcodes(), and print_insn_sparc().

◆ opcode_bits

int opcode_bits[4] = { 0x01c00000, 0x0, 0x01f80000, 0x01f80000 }
static

Definition at line 62 of file sparc-dis.c.

◆ opcode_hash_table

sparc_opcode_hash* opcode_hash_table[HASH_SIZE]
static

Definition at line 71 of file sparc-dis.c.

Referenced by is_delayed_branch(), and print_insn_sparc().

◆ reg_names

char* reg_names[]
static
Initial value:
=
{ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
"o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
"l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
"i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
"f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39",
"f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47",
"f48", "f49", "f50", "f51", "f52", "f53", "f54", "f55",
"f56", "f57", "f58", "f59", "f60", "f61", "f62", "f63",
"y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr"
}

Definition at line 78 of file sparc-dis.c.

◆ sorted_opcodes

const sparc_opcode** sorted_opcodes
static

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

Referenced by print_insn_sparc().

◆ v9_hpriv_reg_names

char* v9_hpriv_reg_names[]
static
Initial value:
=
{
"hpstate", "htstate", "resv2", "hintp", "resv4", "htba", "hver",
"resv7", "resv8", "resv9", "resv10", "resv11", "resv12", "resv13",
"resv14", "resv15", "resv16", "resv17", "resv18", "resv19", "resv20",
"resv21", "resv22", "resv23", "resv24", "resv25", "resv26", "resv27",
"resv28", "resv29", "resv30", "hstick_cmpr"
}

Definition at line 109 of file sparc-dis.c.

Referenced by print_insn_sparc().

◆ v9_priv_reg_names

char* v9_priv_reg_names[]
static
Initial value:
=
{
"tpc", "tnpc", "tstate", "tt", "tick", "tba", "pstate", "tl",
"pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin",
"wstate", "fq", "gl"
}

Definition at line 99 of file sparc-dis.c.

Referenced by print_insn_sparc().

◆ v9a_asr_reg_names

char* v9a_asr_reg_names[]
static
Initial value:
=
{
"pcr", "pic", "dcr", "gsr", "set_softint", "clear_softint",
"softint", "tick_cmpr", "stick", "stick_cmpr"
}

Definition at line 120 of file sparc-dis.c.

Referenced by print_insn_sparc().