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

Go to the source code of this file.

Classes

struct  mips_cp0sel_name
 
struct  mips_abi_choice
 
struct  mips_arch_choice
 

Macros

#define SYMTAB_AVAILABLE   1
 
#define INSNLEN   4
 
#define mips16_reg_names(rn)   mips_gpr_names[mips16_to_32_reg_map[rn]]
 

Functions

static const struct mips_abi_choicechoose_abi_by_name (const char *name, unsigned int namelen)
 
static const struct mips_arch_choicechoose_arch_by_name (const char *name, unsigned int namelen)
 
static const struct mips_arch_choicechoose_arch_by_number (unsigned long mach)
 
static int is_newabi (Elf_Internal_Ehdr *header)
 
static void set_default_mips_dis_options (struct disassemble_info *info)
 
static void parse_mips_dis_option (const char *option, unsigned int len)
 
void parse_mips_dis_options (const char *options)
 
static const struct mips_cp0sel_namelookup_mips_cp0sel_name (const struct mips_cp0sel_name *names, unsigned int len, unsigned int cp0reg, unsigned int sel)
 
static void print_insn_args (const char *d, register unsigned long int l, bfd_vma pc, struct disassemble_info *info, const struct mips_opcode *opp)
 
static int print_insn_mips (bfd_vma memaddr, unsigned long int word, struct disassemble_info *info)
 
static void print_mips16_insn_arg (char type, const struct mips_opcode *op, int l, bfd_boolean use_extend, int extend, bfd_vma memaddr, struct disassemble_info *info)
 
static int print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info)
 
static int _print_insn_mips (bfd_vma memaddr, struct disassemble_info *info, enum bfd_endian endianness)
 
int print_insn_big_mips (bfd_vma memaddr, struct disassemble_info *info)
 
int print_insn_little_mips (bfd_vma memaddr, struct disassemble_info *info)
 
void print_mips_disassembler_options (FILE *stream)
 

Variables

static const unsigned int mips16_to_32_reg_map []
 
static const char *const mips_gpr_names_numeric [32]
 
const char *const mips_gpr_names_oldabi [32]
 
const char *const mips_gpr_names_newabi [32]
 
static const char *const mips_fpr_names_numeric [32]
 
static const char *const mips_fpr_names_32 [32]
 
static const char *const mips_fpr_names_n32 [32]
 
static const char *const mips_fpr_names_64 [32]
 
static const char *const mips_cp0_names_numeric [32]
 
static const char *const mips_cp0_names_mips3264 [32]
 
static const struct mips_cp0sel_name mips_cp0sel_names_mips3264 []
 
static const char *const mips_cp0_names_mips3264r2 [32]
 
static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2 []
 
static const char *const mips_cp0_names_sb1 [32]
 
static const struct mips_cp0sel_name mips_cp0sel_names_sb1 []
 
static const char *const mips_hwr_names_numeric [32]
 
static const char *const mips_hwr_names_mips3264r2 [32]
 
struct mips_abi_choice mips_abi_choices []
 
const struct mips_arch_choice mips_arch_choices []
 
static int mips_processor
 
static int mips_isa
 
static const char *constmips_gpr_names
 
static const char *constmips_fpr_names
 
static const char *constmips_cp0_names
 
static const struct mips_cp0sel_namemips_cp0sel_names
 
static int mips_cp0sel_names_len
 
static const char *constmips_hwr_names
 
static int no_aliases
 

Macro Definition Documentation

◆ INSNLEN

#define INSNLEN   4

Definition at line 46 of file mips-dis.c.

◆ mips16_reg_names

#define mips16_reg_names (   rn)    mips_gpr_names[mips16_to_32_reg_map[rn]]

Definition at line 64 of file mips-dis.c.

◆ SYMTAB_AVAILABLE

#define SYMTAB_AVAILABLE   1

Definition at line 41 of file mips-dis.c.

Function Documentation

◆ _print_insn_mips()

static int _print_insn_mips ( bfd_vma  memaddr,
struct disassemble_info info,
enum bfd_endian  endianness 
)
static

Definition at line 2053 of file mips-dis.c.

2056 {
2058  int status;
2059 
2061  parse_mips_dis_options (info->disassembler_options);
2062 
2063 #if 1
2064  /* FIXME: If odd address, this is CLEARLY a mips 16 instruction. */
2065  /* Only a few tools will work this way. */
2066  if (memaddr & 0x01) {
2067  return print_insn_mips16 (memaddr, info);
2068  }
2069 #endif
2070 
2071 #if SYMTAB_AVAILABLE
2072  if (info->mach == bfd_mach_mips16 || (info->flavour == bfd_target_elf_flavour && info->symbols != NULL && ((*(elf_symbol_type **)info->symbols)->internal_elf_sym.st_other == STO_MIPS16))) {
2073  return print_insn_mips16 (memaddr, info);
2074  }
2075 #endif
2076 
2077  status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
2078  if (status == 0)
2079  {
2080  unsigned long insn;
2081 
2082  if (endianness == BFD_ENDIAN_BIG) {
2083  insn = (unsigned long)bfd_getb32 (buffer);
2084  } else {
2085  insn = (unsigned long)bfd_getl32 (buffer);
2086  }
2087 
2088  return print_insn_mips (memaddr, insn, info);
2089  }
2090  else
2091  {
2092  (*info->memory_error_func) (status, memaddr, info);
2093  return -1;
2094  }
2095 }
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
#define NULL
Definition: cris-opc.c:27
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
#define STO_MIPS16
Definition: mips.h:720
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
#define INSNLEN
Definition: mips-dis.c:46
static int print_insn_mips(bfd_vma memaddr, unsigned long int word, struct disassemble_info *info)
Definition: mips-dis.c:1276
void parse_mips_dis_options(const char *options)
Definition: mips-dis.c:704
static int print_insn_mips16(bfd_vma memaddr, struct disassemble_info *info)
Definition: mips-dis.c:1888
static void set_default_mips_dis_options(struct disassemble_info *info)
Definition: mips-dis.c:540
unsigned char bfd_byte
Definition: mybfd.h:176
@ bfd_target_elf_flavour
Definition: mybfd.h:4597
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
#define bfd_mach_mips16
Definition: mybfd.h:1651
Definition: buffer.h:15

References BFD_ENDIAN_BIG, bfd_getb32(), bfd_getl32(), bfd_mach_mips16, bfd_target_elf_flavour, info(), INSNLEN, long, NULL, parse_mips_dis_options(), print_insn_mips(), print_insn_mips16(), set_default_mips_dis_options(), status, and STO_MIPS16.

Referenced by print_insn_big_mips(), and print_insn_little_mips().

◆ choose_abi_by_name()

static const struct mips_abi_choice* choose_abi_by_name ( const char *  name,
unsigned int  namelen 
)
static

Definition at line 465 of file mips-dis.c.

466 {
467  const struct mips_abi_choice *c;
468  unsigned int i;
469 
470  for (i = 0, c = NULL; i < ARRAY_SIZE (mips_abi_choices) && !c; i++) {
471  if (strncmp (mips_abi_choices[i].name, name, namelen) == 0 && strlen (mips_abi_choices[i].name) == namelen) {
472  c = &mips_abi_choices[i];
473  }
474  }
475 
476  return c;
477 }
#define ARRAY_SIZE(a)
lzma_index ** i
Definition: index.h:629
struct mips_abi_choice mips_abi_choices[]
Definition: mips-dis.c:326
#define c(i)
Definition: sha256.c:43
Definition: z80asm.h:102

References ARRAY_SIZE, c, i, mips_abi_choices, and NULL.

Referenced by parse_mips_dis_option().

◆ choose_arch_by_name()

static const struct mips_arch_choice* choose_arch_by_name ( const char *  name,
unsigned int  namelen 
)
static

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

481 {
482  const struct mips_arch_choice *c = NULL;
483  unsigned int i;
484 
485  for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && !c; i++) {
486  if (strncmp (mips_arch_choices[i].name, name, namelen) == 0 && strlen (mips_arch_choices[i].name) == namelen) {
487  c = &mips_arch_choices[i];
488  }
489  }
490 
491  return c;
492 }
const struct mips_arch_choice mips_arch_choices[]
Definition: mips-dis.c:347

References ARRAY_SIZE, c, i, mips_arch_choices, and NULL.

Referenced by parse_mips_dis_option().

◆ choose_arch_by_number()

static const struct mips_arch_choice* choose_arch_by_number ( unsigned long  mach)
static

Definition at line 495 of file mips-dis.c.

496 {
497  static unsigned long hint_bfd_mach;
498  static const struct mips_arch_choice *hint_arch_choice;
499  const struct mips_arch_choice *c;
500  unsigned int i;
501 
502  /* We optimize this because even if the user specifies no
503  flags, this will be done for every instruction! */
504  if (hint_bfd_mach == mach && hint_arch_choice != NULL && hint_arch_choice->bfd_mach == hint_bfd_mach) {
505  return hint_arch_choice;
506  }
507 
508  for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && !c; i++)
509  {
511  && mips_arch_choices[i].bfd_mach == mach)
512  {
513  c = &mips_arch_choices[i];
514  hint_bfd_mach = mach;
515  hint_arch_choice = c;
516  }
517  }
518  return c;
519 }
unsigned long bfd_mach
Definition: mips-dis.c:338

References ARRAY_SIZE, mips_arch_choice::bfd_mach, mips_arch_choice::bfd_mach_valid, c, i, mips_arch_choices, and NULL.

Referenced by set_default_mips_dis_options().

◆ is_newabi()

static int is_newabi ( Elf_Internal_Ehdr header)
static

Definition at line 524 of file mips-dis.c.

525 {
526  /* There are no old-style ABIs which use 64-bit ELF. */
527  if (header->e_ident[EI_CLASS] == ELFCLASS64) {
528  return 1;
529  }
530 
531  /* If a 32-bit ELF file, n32 is a new-style ABI. */
532  if ((header->e_flags & EF_MIPS_ABI2) != 0) {
533  return 1;
534  }
535 
536  return 0;
537 }
#define EI_CLASS
Definition: common.h:51
#define ELFCLASS64
Definition: common.h:54
#define EF_MIPS_ABI2
#define header(is_bt, len_min, ret_op)

References EF_MIPS_ABI2, EI_CLASS, ELFCLASS64, and header.

Referenced by set_default_mips_dis_options().

◆ lookup_mips_cp0sel_name()

static const struct mips_cp0sel_name* lookup_mips_cp0sel_name ( const struct mips_cp0sel_name names,
unsigned int  len,
unsigned int  cp0reg,
unsigned int  sel 
)
static

Definition at line 736 of file mips-dis.c.

740 {
741  unsigned int i;
742 
743  for (i = 0; i < len; i++) {
744  if (names[i].cp0reg == cp0reg && names[i].sel == sel) {
745  return &names[i];
746  }
747  }
748  return NULL;
749 }
size_t len
Definition: 6502dis.c:15
static RzILOpEffect * sel(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1869
Definition: names.h:123

References mips_cp0sel_name::cp0reg, i, len, NULL, and sel().

Referenced by print_insn_args().

◆ parse_mips_dis_option()

static void parse_mips_dis_option ( const char *  option,
unsigned int  len 
)
static

Definition at line 588 of file mips-dis.c.

589 {
590  unsigned int i, optionlen, vallen;
591  const char *val;
592  const struct mips_abi_choice *chosen_abi;
593  const struct mips_arch_choice *chosen_arch;
594 
595  /* Try to match options that are simple flags
596  if (CONST_STRNEQ (option, "no-aliases"))
597  {
598  no_aliases = 1;
599  return;
600  } */
601 
602  /* Look for the = that delimits the end of the option name. */
603  for (i = 0; i < len; i++) {
604  if (option[i] == '=') {
605  break;
606  }
607  }
608 
609  if (i == 0) { /* Invalid option: no name before '='. */
610  return;
611  }
612  if (i == len) { /* Invalid option: no '='. */
613  return;
614  }
615  if (i == (len - 1)) { /* Invalid option: no value after '='. */
616  return;
617  }
618 
619  optionlen = i;
620  val = option + (optionlen + 1);
621  vallen = len - (optionlen + 1);
622 
623  if (strlen ("abi") == optionlen
624  && !strncmp ("abi", option, optionlen)) {
625  chosen_abi = choose_abi_by_name (val, vallen);
626  if (chosen_abi) {
627  mips_gpr_names = chosen_abi->gpr_names;
628  mips_fpr_names = chosen_abi->fpr_names;
629  }
630  return;
631  }
632 
633  if (strncmp ("gpr-names", option, optionlen) == 0
634  && strlen ("gpr-names") == optionlen)
635  {
636  chosen_abi = choose_abi_by_name (val, vallen);
637  if (chosen_abi != NULL) {
638  mips_gpr_names = chosen_abi->gpr_names;
639  }
640  return;
641  }
642 
643  if (strncmp ("fpr-names", option, optionlen) == 0
644  && strlen ("fpr-names") == optionlen)
645  {
646  chosen_abi = choose_abi_by_name (val, vallen);
647  if (chosen_abi != NULL) {
648  mips_fpr_names = chosen_abi->fpr_names;
649  }
650  return;
651  }
652 
653  if (strncmp ("cp0-names", option, optionlen) == 0
654  && strlen ("cp0-names") == optionlen)
655  {
656  chosen_arch = choose_arch_by_name (val, vallen);
657  if (chosen_arch != NULL)
658  {
659  mips_cp0_names = chosen_arch->cp0_names;
660  mips_cp0sel_names = chosen_arch->cp0sel_names;
662  }
663  return;
664  }
665 
666  if (strncmp ("hwr-names", option, optionlen) == 0
667  && strlen ("hwr-names") == optionlen)
668  {
669  chosen_arch = choose_arch_by_name (val, vallen);
670  if (chosen_arch != NULL) {
671  mips_hwr_names = chosen_arch->hwr_names;
672  }
673  return;
674  }
675 
676  if (strncmp ("reg-names", option, optionlen) == 0
677  && strlen ("reg-names") == optionlen)
678  {
679  /* We check both ABI and ARCH here unconditionally, so
680  that "numeric" will do the desirable thing: select
681  numeric register names for all registers. Other than
682  that, a given name probably won't match both. */
683  chosen_abi = choose_abi_by_name (val, vallen);
684  if (chosen_abi != NULL)
685  {
686  mips_gpr_names = chosen_abi->gpr_names;
687  mips_fpr_names = chosen_abi->fpr_names;
688  }
689  chosen_arch = choose_arch_by_name (val, vallen);
690  if (chosen_arch != NULL)
691  {
692  mips_cp0_names = chosen_arch->cp0_names;
693  mips_cp0sel_names = chosen_arch->cp0sel_names;
695  mips_hwr_names = chosen_arch->hwr_names;
696  }
697  return;
698  }
699 
700  /* Invalid option. */
701 }
ut16 val
Definition: armass64_const.h:6
static const struct mips_abi_choice * choose_abi_by_name(const char *name, unsigned int namelen)
Definition: mips-dis.c:465
static int mips_cp0sel_names_len
Definition: mips-dis.c:458
static const struct mips_arch_choice * choose_arch_by_name(const char *name, unsigned int namelen)
Definition: mips-dis.c:480
static const char *const * mips_fpr_names
Definition: mips-dis.c:455
static const struct mips_cp0sel_name * mips_cp0sel_names
Definition: mips-dis.c:457
static const char *const * mips_cp0_names
Definition: mips-dis.c:456
static const char *const * mips_hwr_names
Definition: mips-dis.c:459
static const char *const * mips_gpr_names
Definition: mips-dis.c:454
const char *const * gpr_names
Definition: mips-dis.c:322
const char *const * fpr_names
Definition: mips-dis.c:323
const char *const * hwr_names
Definition: mips-dis.c:344
const struct mips_cp0sel_name * cp0sel_names
Definition: mips-dis.c:342
const char *const * cp0_names
Definition: mips-dis.c:341
unsigned int cp0sel_names_len
Definition: mips-dis.c:343
Definition: getopt.h:84

References choose_abi_by_name(), choose_arch_by_name(), mips_arch_choice::cp0_names, mips_arch_choice::cp0sel_names, mips_arch_choice::cp0sel_names_len, mips_abi_choice::fpr_names, mips_abi_choice::gpr_names, mips_arch_choice::hwr_names, i, len, mips_cp0_names, mips_cp0sel_names, mips_cp0sel_names_len, mips_fpr_names, mips_gpr_names, mips_hwr_names, NULL, and val.

Referenced by parse_mips_dis_options().

◆ parse_mips_dis_options()

void parse_mips_dis_options ( const char *  options)

Definition at line 704 of file mips-dis.c.

705 {
706  const char *option_end;
707 
708  if (!options) {
709  return;
710  }
711 
712  while (*options != '\0')
713  {
714  /* Skip empty options. */
715  if (*options == ',')
716  {
717  options++;
718  continue;
719  }
720 
721  /* We know that *options is neither NUL or a comma. */
722  option_end = options + 1;
723  while (*option_end != ',' && *option_end != '\0') {
724  option_end++;
725  }
726 
727  parse_mips_dis_option (options, option_end - options);
728 
729  /* Go on to the next one. If option_end points to a comma, it
730  will be skipped above. */
731  options = option_end;
732  }
733 }
static const char struct stat static buf struct stat static buf static vhangup int options
Definition: sflib.h:145
static void parse_mips_dis_option(const char *option, unsigned int len)
Definition: mips-dis.c:588

References options, and parse_mips_dis_option().

Referenced by _print_insn_mips().

◆ print_insn_args()

static void print_insn_args ( const char *  d,
register unsigned long int  l,
bfd_vma  pc,
struct disassemble_info info,
const struct mips_opcode opp 
)
static

Definition at line 754 of file mips-dis.c.

759 {
760  int op, delta;
761  unsigned int lsb, msb, msbd;
762 
763  lsb = 0;
764 
765  for (; *d != '\0'; d++)
766  {
767  switch (*d)
768  {
769  case ',':
770  (*info->fprintf_func) (info->stream, "%c ", *d);
771  break;
772  case '(':
773  case ')':
774  case '[':
775  case ']':
776  (*info->fprintf_func) (info->stream, "%c", *d);
777  break;
778 
779  case '+':
780  /* Extension character; switch for second char. */
781  d++;
782  switch (*d)
783  {
784  case '\0':
785  /* xgettext:c-format */
786  (*info->fprintf_func) (info->stream,
787  _("# internal error, incomplete extension sequence (+)"));
788  return;
789 
790  case 'A':
791  lsb = (l >> OP_SH_SHAMT) & OP_MASK_SHAMT;
792  (*info->fprintf_func) (info->stream, "0x%x", lsb);
793  break;
794 
795  case 'B':
796  msb = (l >> OP_SH_INSMSB) & OP_MASK_INSMSB;
797  (*info->fprintf_func) (info->stream, "0x%x", msb - lsb + 1);
798  break;
799 
800  case '1':
801  (*info->fprintf_func) (info->stream, "0x%lx",
802  (l >> OP_SH_UDI1) & OP_MASK_UDI1);
803  break;
804 
805  case '2':
806  (*info->fprintf_func) (info->stream, "0x%lx",
807  (l >> OP_SH_UDI2) & OP_MASK_UDI2);
808  break;
809 
810  case '3':
811  (*info->fprintf_func) (info->stream, "0x%lx",
812  (l >> OP_SH_UDI3) & OP_MASK_UDI3);
813  break;
814 
815  case '4':
816  (*info->fprintf_func) (info->stream, "0x%lx",
817  (l >> OP_SH_UDI4) & OP_MASK_UDI4);
818  break;
819 
820  case 'C':
821  case 'H':
822  msbd = (l >> OP_SH_EXTMSBD) & OP_MASK_EXTMSBD;
823  (*info->fprintf_func) (info->stream, "0x%x", msbd + 1);
824  break;
825 
826  case 'D':
827  {
828  const struct mips_cp0sel_name *n;
829  unsigned int cp0reg, sel;
830 
831  cp0reg = (l >> OP_SH_RD) & OP_MASK_RD;
832  sel = (l >> OP_SH_SEL) & OP_MASK_SEL;
833 
834  /* CP0 register including 'sel' code for mtcN (et al.), to be
835  printed textually if known. If not known, print both
836  CP0 register name and sel numerically since CP0 register
837  with sel 0 may have a name unrelated to register being
838  printed. */
841  if (n != NULL) {
842  (*info->fprintf_func) (info->stream, "%s", n->name);
843  } else {
844  (*info->fprintf_func) (info->stream, "$%d,%d", cp0reg, sel);
845  }
846  break;
847  }
848 
849  case 'E':
850  lsb = ((l >> OP_SH_SHAMT) & OP_MASK_SHAMT) + 32;
851  (*info->fprintf_func) (info->stream, "0x%x", lsb);
852  break;
853 
854  case 'F':
855  msb = ((l >> OP_SH_INSMSB) & OP_MASK_INSMSB) + 32;
856  (*info->fprintf_func) (info->stream, "0x%x", msb - lsb + 1);
857  break;
858 
859  case 'G':
860  msbd = ((l >> OP_SH_EXTMSBD) & OP_MASK_EXTMSBD) + 32;
861  (*info->fprintf_func) (info->stream, "0x%x", msbd + 1);
862  break;
863 
864  case 't': /* Coprocessor 0 reg name */
865  (*info->fprintf_func) (info->stream, "%s",
866  mips_cp0_names[(l >> OP_SH_RT) &
867  OP_MASK_RT]);
868  break;
869 
870  case 'T': /* Coprocessor 0 reg name */
871  {
872  const struct mips_cp0sel_name *n;
873  unsigned int cp0reg, sel;
874 
875  cp0reg = (l >> OP_SH_RT) & OP_MASK_RT;
876  sel = (l >> OP_SH_SEL) & OP_MASK_SEL;
877 
878  /* CP0 register including 'sel' code for mftc0, to be
879  printed textually if known. If not known, print both
880  CP0 register name and sel numerically since CP0 register
881  with sel 0 may have a name unrelated to register being
882  printed. */
885  if (n != NULL) {
886  (*info->fprintf_func) (info->stream, "%s", n->name);
887  } else {
888  (*info->fprintf_func) (info->stream, "$%d,%d", cp0reg, sel);
889  }
890  break;
891  }
892 
893  default:
894  /* xgettext:c-format */
895  (*info->fprintf_func) (info->stream,
896  _("# internal error, undefined extension sequence (+%c)"),
897  *d);
898  return;
899  }
900  break;
901 
902  case '2':
903  (*info->fprintf_func) (info->stream, "0x%lx",
904  (l >> OP_SH_BP) & OP_MASK_BP);
905  break;
906 
907  case '3':
908  (*info->fprintf_func) (info->stream, "0x%lx",
909  (l >> OP_SH_SA3) & OP_MASK_SA3);
910  break;
911 
912  case '4':
913  (*info->fprintf_func) (info->stream, "0x%lx",
914  (l >> OP_SH_SA4) & OP_MASK_SA4);
915  break;
916 
917  case '5':
918  (*info->fprintf_func) (info->stream, "0x%lx",
919  (l >> OP_SH_IMM8) & OP_MASK_IMM8);
920  break;
921 
922  case '6':
923  (*info->fprintf_func) (info->stream, "0x%lx",
924  (l >> OP_SH_RS) & OP_MASK_RS);
925  break;
926 
927  case '7':
928  (*info->fprintf_func) (info->stream, "$ac%ld",
929  (l >> OP_SH_DSPACC) & OP_MASK_DSPACC);
930  break;
931 
932  case '8':
933  (*info->fprintf_func) (info->stream, "0x%lx",
934  (l >> OP_SH_WRDSP) & OP_MASK_WRDSP);
935  break;
936 
937  case '9':
938  (*info->fprintf_func) (info->stream, "$ac%ld",
940  break;
941 
942  case '0': /* dsp 6-bit signed immediate in bit 20 */
943  delta = ((l >> OP_SH_DSPSFT) & OP_MASK_DSPSFT);
944  if (delta & 0x20) { /* test sign bit */
945  delta |= ~OP_MASK_DSPSFT;
946  }
947  (*info->fprintf_func) (info->stream, "%d", delta);
948  break;
949 
950  case ':': /* dsp 7-bit signed immediate in bit 19 */
952  if (delta & 0x40) { /* test sign bit */
954  }
955  (*info->fprintf_func) (info->stream, "%d", delta);
956  break;
957 
958  case '\'':
959  (*info->fprintf_func) (info->stream, "0x%lx",
960  (l >> OP_SH_RDDSP) & OP_MASK_RDDSP);
961  break;
962 
963  case '@': /* dsp 10-bit signed immediate in bit 16 */
964  delta = ((l >> OP_SH_IMM10) & OP_MASK_IMM10);
965  if (delta & 0x200) { /* test sign bit */
966  delta |= ~OP_MASK_IMM10;
967  }
968  (*info->fprintf_func) (info->stream, "%d", delta);
969  break;
970 
971  case '!':
972  (*info->fprintf_func) (info->stream, "%ld",
973  (l >> OP_SH_MT_U) & OP_MASK_MT_U);
974  break;
975 
976  case '$':
977  (*info->fprintf_func) (info->stream, "%ld",
978  (l >> OP_SH_MT_H) & OP_MASK_MT_H);
979  break;
980 
981  case '*':
982  (*info->fprintf_func) (info->stream, "$ac%ld",
983  (l >> OP_SH_MTACC_T) & OP_MASK_MTACC_T);
984  break;
985 
986  case '&':
987  (*info->fprintf_func) (info->stream, "$ac%ld",
988  (l >> OP_SH_MTACC_D) & OP_MASK_MTACC_D);
989  break;
990 
991  case 'g':
992  /* Coprocessor register for CTTC1, MTTC2, MTHC2, CTTC2. */
993  (*info->fprintf_func) (info->stream, "$%ld",
994  (l >> OP_SH_RD) & OP_MASK_RD);
995  break;
996 
997  case 's':
998  case 'b':
999  case 'r':
1000  case 'v':
1001  (*info->fprintf_func) (info->stream, "%s",
1002  mips_gpr_names[(l >> OP_SH_RS) & OP_MASK_RS]);
1003  break;
1004 
1005  case 't':
1006  case 'w':
1007  (*info->fprintf_func) (info->stream, "%s",
1008  mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]);
1009  break;
1010 
1011  case 'i':
1012  case 'u':
1013  (*info->fprintf_func) (info->stream, "0x%lx",
1015  break;
1016 
1017  case 'j': /* Same as i, but sign-extended. */
1018  case 'o':
1019  delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
1020  if (delta & 0x8000) {
1021  delta |= ~0xffff;
1022  }
1023  (*info->fprintf_func) (info->stream, "%d",
1024  delta);
1025  break;
1026 
1027  case 'h':
1028  (*info->fprintf_func) (info->stream, "0x%x",
1029  (unsigned int) ((l >> OP_SH_PREFX)
1030  & OP_MASK_PREFX));
1031  break;
1032 
1033  case 'k':
1034  (*info->fprintf_func) (info->stream, "0x%x",
1035  (unsigned int) ((l >> OP_SH_CACHE)
1036  & OP_MASK_CACHE));
1037  break;
1038 
1039  case 'a':
1040  info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff)
1041  | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2));
1042  /* For gdb disassembler, force odd address on jalx. */
1043  //if (info->flavour == bfd_target_unknown_flavour
1044  // && strcmp (opp->name, "jalx") == 0)
1045  //info->target |= 1;
1046  (*info->print_address_func) (info->target, info);
1047  break;
1048 
1049  case 'p':
1050  /* Sign extend the displacement. */
1051  delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
1052  if (delta & 0x8000) {
1053  delta |= ~0xffff;
1054  }
1055  info->target = (delta << 2) + pc + INSNLEN;
1056  (*info->print_address_func) (info->target, info);
1057  break;
1058 
1059  case 'd':
1060  (*info->fprintf_func) (info->stream, "%s",
1061  mips_gpr_names[(l >> OP_SH_RD) & OP_MASK_RD]);
1062  break;
1063 
1064  case 'U':
1065  {
1066  /* First check for both rd and rt being equal. */
1067  unsigned int reg = (l >> OP_SH_RD) & OP_MASK_RD;
1068  if (reg == ((l >> OP_SH_RT) & OP_MASK_RT)) {
1069  (*info->fprintf_func) (info->stream, "%s",
1070  mips_gpr_names[reg]);
1071  } else {
1072  /* If one is zero use the other. */
1073  if (reg == 0) {
1074  (*info->fprintf_func) (info->stream, "%s",
1075  mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]);
1076  } else if (((l >> OP_SH_RT) & OP_MASK_RT) == 0) {
1077  (*info->fprintf_func) (info->stream, "%s",
1078  mips_gpr_names[reg]);
1079  } else { /* Bogus, result depends on processor. */
1080  (*info->fprintf_func) (info->stream, "%s or %s",
1082  mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]);
1083  }
1084  }
1085  }
1086  break;
1087 
1088  case 'z':
1089  (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[0]);
1090  break;
1091 
1092  case '<':
1093  (*info->fprintf_func) (info->stream, "0x%lx",
1094  (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
1095  break;
1096 
1097  case 'c':
1098  (*info->fprintf_func) (info->stream, "0x%lx",
1099  (l >> OP_SH_CODE) & OP_MASK_CODE);
1100  break;
1101 
1102  case 'q':
1103  (*info->fprintf_func) (info->stream, "0x%lx",
1104  (l >> OP_SH_CODE2) & OP_MASK_CODE2);
1105  break;
1106 
1107  case 'C':
1108  (*info->fprintf_func) (info->stream, "0x%lx",
1109  (l >> OP_SH_COPZ) & OP_MASK_COPZ);
1110  break;
1111 
1112  case 'B':
1113  (*info->fprintf_func) (info->stream, "0x%lx",
1114 
1115  (l >> OP_SH_CODE20) & OP_MASK_CODE20);
1116  break;
1117 
1118  case 'J':
1119  (*info->fprintf_func) (info->stream, "0x%lx",
1120  (l >> OP_SH_CODE19) & OP_MASK_CODE19);
1121  break;
1122 
1123  case 'S':
1124  case 'V':
1125  (*info->fprintf_func) (info->stream, "%s",
1126  mips_fpr_names[(l >> OP_SH_FS) & OP_MASK_FS]);
1127  break;
1128 
1129  case 'T':
1130  case 'W':
1131  (*info->fprintf_func) (info->stream, "%s",
1132  mips_fpr_names[(l >> OP_SH_FT) & OP_MASK_FT]);
1133  break;
1134 
1135  case 'D':
1136  (*info->fprintf_func) (info->stream, "%s",
1137  mips_fpr_names[(l >> OP_SH_FD) & OP_MASK_FD]);
1138  break;
1139 
1140  case 'R':
1141  (*info->fprintf_func) (info->stream, "%s",
1142  mips_fpr_names[(l >> OP_SH_FR) & OP_MASK_FR]);
1143  break;
1144 
1145  case 'E':
1146  /* Coprocessor register for lwcN instructions, et al.
1147 
1148  Note that there is no load/store cp0 instructions, and
1149  that FPU (cp1) instructions disassemble this field using
1150  'T' format. Therefore, until we gain understanding of
1151  cp2 register names, we can simply print the register
1152  numbers. */
1153  (*info->fprintf_func) (info->stream, "$%ld",
1154  (l >> OP_SH_RT) & OP_MASK_RT);
1155  break;
1156 
1157  case 'G':
1158  /* Coprocessor register for mtcN instructions, et al. Note
1159  that FPU (cp1) instructions disassemble this field using
1160  'S' format. Therefore, we only need to worry about cp0,
1161  cp2, and cp3. */
1162  op = (l >> OP_SH_OP) & OP_MASK_OP;
1163  if (op == OP_OP_COP0) {
1164  (*info->fprintf_func) (info->stream, "%s",
1165  mips_cp0_names[(l >> OP_SH_RD) & OP_MASK_RD]);
1166  } else {
1167  (*info->fprintf_func) (info->stream, "$%ld",
1168  (l >> OP_SH_RD) & OP_MASK_RD);
1169  }
1170  break;
1171 
1172  case 'K':
1173  (*info->fprintf_func) (info->stream, "%s",
1174  mips_hwr_names[(l >> OP_SH_RD) & OP_MASK_RD]);
1175  break;
1176 
1177  case 'N':
1178  (*info->fprintf_func) (info->stream,
1179  ((opp->pinfo & (FP_D | FP_S)) != 0
1180  ? "$fcc%ld" : "$cc%ld"),
1181  (l >> OP_SH_BCC) & OP_MASK_BCC);
1182  break;
1183 
1184  case 'M':
1185  (*info->fprintf_func) (info->stream, "$fcc%ld",
1186  (l >> OP_SH_CCC) & OP_MASK_CCC);
1187  break;
1188 
1189  case 'P':
1190  (*info->fprintf_func) (info->stream, "%ld",
1191  (l >> OP_SH_PERFREG) & OP_MASK_PERFREG);
1192  break;
1193 
1194  case 'e':
1195  (*info->fprintf_func) (info->stream, "%ld",
1196  (l >> OP_SH_VECBYTE) & OP_MASK_VECBYTE);
1197  break;
1198 
1199  case '%':
1200  (*info->fprintf_func) (info->stream, "%ld",
1201  (l >> OP_SH_VECALIGN) & OP_MASK_VECALIGN);
1202  break;
1203 
1204  case 'H':
1205  (*info->fprintf_func) (info->stream, "%ld",
1206  (l >> OP_SH_SEL) & OP_MASK_SEL);
1207  break;
1208 
1209  case 'O':
1210  (*info->fprintf_func) (info->stream, "%ld",
1211  (l >> OP_SH_ALN) & OP_MASK_ALN);
1212  break;
1213 
1214  case 'Q':
1215  {
1216  unsigned int vsel = (l >> OP_SH_VSEL) & OP_MASK_VSEL;
1217 
1218  if ((vsel & 0x10) == 0)
1219  {
1220  int fmt;
1221 
1222  vsel &= 0x0f;
1223  for (fmt = 0; fmt < 3; fmt++, vsel >>= 1) {
1224  if ((vsel & 1) == 0) {
1225  break;
1226  }
1227  }
1228  (*info->fprintf_func) (info->stream, "$v%ld[%d]",
1229  (l >> OP_SH_FT) & OP_MASK_FT,
1230  vsel >> 1);
1231  }
1232  else if ((vsel & 0x08) == 0)
1233  {
1234  (*info->fprintf_func) (info->stream, "$v%ld",
1235  (l >> OP_SH_FT) & OP_MASK_FT);
1236  }
1237  else
1238  {
1239  (*info->fprintf_func) (info->stream, "0x%lx",
1240  (l >> OP_SH_FT) & OP_MASK_FT);
1241  }
1242  }
1243  break;
1244 
1245  case 'X':
1246  (*info->fprintf_func) (info->stream, "$v%ld",
1247  (l >> OP_SH_FD) & OP_MASK_FD);
1248  break;
1249 
1250  case 'Y':
1251  (*info->fprintf_func) (info->stream, "$v%ld",
1252  (l >> OP_SH_FS) & OP_MASK_FS);
1253  break;
1254 
1255  case 'Z':
1256  (*info->fprintf_func) (info->stream, "$v%ld",
1257  (l >> OP_SH_FT) & OP_MASK_FT);
1258  break;
1259 
1260  default:
1261  /* xgettext:c-format */
1262  (*info->fprintf_func) (info->stream,
1263  _("# internal error, undefined modifier(%c)"),
1264  *d);
1265  return;
1266  }
1267  }
1268 }
ut8 op
Definition: 6502dis.c:13
#define reg(n)
#define OP_SH_CACHE
Definition: mips.h:83
#define OP_SH_MT_U
Definition: mips.h:178
#define OP_MASK_UDI2
Definition: mips.h:214
#define OP_SH_CCC
Definition: mips.h:91
#define OP_MASK_IMMEDIATE
Definition: mips.h:102
#define OP_SH_VSEL
Definition: mips.h:142
#define OP_MASK_CODE20
Definition: mips.h:92
#define OP_MASK_OP
Definition: mips.h:64
#define OP_MASK_VSEL
Definition: mips.h:143
#define OP_MASK_CODE19
Definition: mips.h:139
#define OP_MASK_RDDSP
Definition: mips.h:173
#define OP_SH_UDI4
Definition: mips.h:217
#define OP_SH_INSMSB
Definition: mips.h:149
#define OP_SH_MTACC_D
Definition: mips.h:184
#define OP_MASK_SA3
Definition: mips.h:163
#define OP_MASK_FT
Definition: mips.h:80
#define OP_SH_UDI1
Definition: mips.h:211
#define OP_SH_ALN
Definition: mips.h:140
#define OP_SH_VECALIGN
Definition: mips.h:147
#define OP_SH_DSPACC
Definition: mips.h:154
#define OP_MASK_UDI3
Definition: mips.h:216
#define OP_SH_CODE20
Definition: mips.h:93
#define OP_SH_SA3
Definition: mips.h:162
#define OP_MASK_DSPACC
Definition: mips.h:155
#define OP_MASK_CODE
Definition: mips.h:74
#define OP_MASK_SEL
Definition: mips.h:137
#define OP_MASK_SA4
Definition: mips.h:165
#define OP_MASK_RD
Definition: mips.h:84
#define OP_SH_DSPSFT_7
Definition: mips.h:160
#define OP_MASK_ALN
Definition: mips.h:141
#define OP_SH_IMM8
Definition: mips.h:166
#define OP_SH_RDDSP
Definition: mips.h:172
#define OP_SH_RS
Definition: mips.h:67
#define OP_SH_FD
Definition: mips.h:97
#define OP_MASK_MTACC_D
Definition: mips.h:185
#define OP_SH_DELTA
Definition: mips.h:105
#define OP_MASK_VECBYTE
Definition: mips.h:144
#define FP_D
Definition: mips.h:455
#define OP_MASK_WRDSP
Definition: mips.h:171
#define OP_SH_IMMEDIATE
Definition: mips.h:103
#define OP_MASK_FR
Definition: mips.h:68
#define OP_SH_RT
Definition: mips.h:79
#define OP_SH_EXTMSBD
Definition: mips.h:151
#define OP_MASK_TARGET
Definition: mips.h:98
#define OP_MASK_UDI4
Definition: mips.h:218
#define OP_MASK_MTACC_T
Definition: mips.h:183
#define OP_SH_TARGET
Definition: mips.h:99
#define OP_SH_FS
Definition: mips.h:87
#define OP_SH_COPZ
Definition: mips.h:101
#define OP_MASK_VECALIGN
Definition: mips.h:146
#define OP_MASK_RS
Definition: mips.h:66
#define OP_SH_WRDSP
Definition: mips.h:170
#define OP_SH_FR
Definition: mips.h:69
#define OP_MASK_IMM8
Definition: mips.h:167
#define OP_MASK_CCC
Definition: mips.h:90
#define OP_MASK_PREFX
Definition: mips.h:88
#define OP_SH_SEL
Definition: mips.h:136
#define OP_MASK_MT_U
Definition: mips.h:179
#define OP_MASK_FD
Definition: mips.h:96
#define OP_SH_IMM10
Definition: mips.h:168
#define OP_SH_OP
Definition: mips.h:65
#define OP_SH_MTACC_T
Definition: mips.h:182
#define OP_SH_FT
Definition: mips.h:81
#define OP_MASK_IMM10
Definition: mips.h:169
#define FP_S
Definition: mips.h:453
#define OP_MASK_UDI1
Definition: mips.h:212
#define OP_MASK_COPZ
Definition: mips.h:100
#define OP_MASK_BP
Definition: mips.h:175
#define OP_MASK_CACHE
Definition: mips.h:82
#define OP_SH_PREFX
Definition: mips.h:89
#define OP_MASK_FS
Definition: mips.h:86
#define OP_SH_MT_H
Definition: mips.h:180
#define OP_MASK_PERFREG
Definition: mips.h:134
#define OP_SH_UDI3
Definition: mips.h:215
#define OP_SH_DSPSFT
Definition: mips.h:158
#define OP_SH_CODE
Definition: mips.h:75
#define OP_MASK_DSPACC_S
Definition: mips.h:157
#define OP_SH_BCC
Definition: mips.h:73
#define OP_MASK_INSMSB
Definition: mips.h:148
#define OP_MASK_BCC
Definition: mips.h:72
#define OP_SH_SA4
Definition: mips.h:164
#define OP_SH_VECBYTE
Definition: mips.h:145
#define OP_SH_CODE2
Definition: mips.h:77
#define OP_MASK_CODE2
Definition: mips.h:76
#define OP_SH_SHAMT
Definition: mips.h:95
#define OP_MASK_RT
Definition: mips.h:78
#define OP_SH_CODE19
Definition: mips.h:138
#define OP_MASK_DELTA
Definition: mips.h:104
#define OP_OP_COP0
Definition: mips.h:187
#define OP_MASK_DSPSFT
Definition: mips.h:159
#define OP_SH_BP
Definition: mips.h:174
#define OP_MASK_DSPSFT_7
Definition: mips.h:161
#define OP_SH_PERFREG
Definition: mips.h:135
#define OP_MASK_SHAMT
Definition: mips.h:94
#define OP_MASK_MT_H
Definition: mips.h:181
#define OP_SH_RD
Definition: mips.h:85
#define OP_SH_DSPACC_S
Definition: mips.h:156
#define OP_SH_UDI2
Definition: mips.h:213
#define OP_MASK_EXTMSBD
Definition: mips.h:150
static const struct mips_cp0sel_name * lookup_mips_cp0sel_name(const struct mips_cp0sel_name *names, unsigned int len, unsigned int cp0reg, unsigned int sel)
Definition: mips-dis.c:736
int n
Definition: mipsasm.c:19
BFD_HOST_U_64_BIT bfd_vma
Definition: mybfd.h:111
#define _(String)
Definition: opintl.h:53
#define d(i)
Definition: sha256.c:44
unsigned int cp0reg
Definition: mips-dis.c:53
unsigned long pinfo
Definition: mips.h:240
Definition: dis.c:32
static st64 delta
Definition: vmenus.c:2425

References _, mips_cp0sel_name::cp0reg, d, delta, FP_D, FP_S, info(), INSNLEN, lookup_mips_cp0sel_name(), mips_cp0_names, mips_cp0sel_names, mips_cp0sel_names_len, mips_fpr_names, mips_gpr_names, mips_hwr_names, n, NULL, op, OP_MASK_ALN, OP_MASK_BCC, OP_MASK_BP, OP_MASK_CACHE, OP_MASK_CCC, OP_MASK_CODE, OP_MASK_CODE19, OP_MASK_CODE2, OP_MASK_CODE20, OP_MASK_COPZ, OP_MASK_DELTA, OP_MASK_DSPACC, OP_MASK_DSPACC_S, OP_MASK_DSPSFT, OP_MASK_DSPSFT_7, OP_MASK_EXTMSBD, OP_MASK_FD, OP_MASK_FR, OP_MASK_FS, OP_MASK_FT, OP_MASK_IMM10, OP_MASK_IMM8, OP_MASK_IMMEDIATE, OP_MASK_INSMSB, OP_MASK_MT_H, OP_MASK_MT_U, OP_MASK_MTACC_D, OP_MASK_MTACC_T, OP_MASK_OP, OP_MASK_PERFREG, OP_MASK_PREFX, OP_MASK_RD, OP_MASK_RDDSP, OP_MASK_RS, OP_MASK_RT, OP_MASK_SA3, OP_MASK_SA4, OP_MASK_SEL, OP_MASK_SHAMT, OP_MASK_TARGET, OP_MASK_UDI1, OP_MASK_UDI2, OP_MASK_UDI3, OP_MASK_UDI4, OP_MASK_VECALIGN, OP_MASK_VECBYTE, OP_MASK_VSEL, OP_MASK_WRDSP, OP_OP_COP0, OP_SH_ALN, OP_SH_BCC, OP_SH_BP, OP_SH_CACHE, OP_SH_CCC, OP_SH_CODE, OP_SH_CODE19, OP_SH_CODE2, OP_SH_CODE20, OP_SH_COPZ, OP_SH_DELTA, OP_SH_DSPACC, OP_SH_DSPACC_S, OP_SH_DSPSFT, OP_SH_DSPSFT_7, OP_SH_EXTMSBD, OP_SH_FD, OP_SH_FR, OP_SH_FS, OP_SH_FT, OP_SH_IMM10, OP_SH_IMM8, OP_SH_IMMEDIATE, OP_SH_INSMSB, OP_SH_MT_H, OP_SH_MT_U, OP_SH_MTACC_D, OP_SH_MTACC_T, OP_SH_OP, OP_SH_PERFREG, OP_SH_PREFX, OP_SH_RD, OP_SH_RDDSP, OP_SH_RS, OP_SH_RT, OP_SH_SA3, OP_SH_SA4, OP_SH_SEL, OP_SH_SHAMT, OP_SH_TARGET, OP_SH_UDI1, OP_SH_UDI2, OP_SH_UDI3, OP_SH_UDI4, OP_SH_VECALIGN, OP_SH_VECBYTE, OP_SH_VSEL, OP_SH_WRDSP, pc, mips_opcode::pinfo, reg, and sel().

Referenced by print_insn_mips().

◆ print_insn_big_mips()

int print_insn_big_mips ( bfd_vma  memaddr,
struct disassemble_info info 
)

Definition at line 2098 of file mips-dis.c.

2099 {
2100  return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG);
2101 }
static int _print_insn_mips(bfd_vma memaddr, struct disassemble_info *info, enum bfd_endian endianness)
Definition: mips-dis.c:2053

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

Referenced by disassemble().

◆ print_insn_little_mips()

int print_insn_little_mips ( bfd_vma  memaddr,
struct disassemble_info info 
)

Definition at line 2104 of file mips-dis.c.

2105 {
2106  return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE);
2107 }
@ BFD_ENDIAN_LITTLE
Definition: mybfd.h:4618

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

Referenced by disassemble().

◆ print_insn_mips()

static int print_insn_mips ( bfd_vma  memaddr,
unsigned long int  word,
struct disassemble_info info 
)
static

Definition at line 1276 of file mips-dis.c.

1279 {
1280  const struct mips_opcode *op;
1281  static bfd_boolean init = 0;
1282  static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
1283 
1284  /* Build a hash table to shorten the search time. */
1285  if (! init)
1286  {
1287  unsigned int i;
1288 
1289  for (i = 0; i <= OP_MASK_OP; i++)
1290  {
1291  for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
1292  {
1293  if (op->pinfo == INSN_MACRO || (no_aliases && (op->pinfo2 & INSN2_ALIAS))) {
1294  continue;
1295  }
1296  if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP)) {
1297  mips_hash[i] = op;
1298  break;
1299  }
1300  }
1301  }
1302 
1303  init = 1;
1304  }
1305 
1306  info->bytes_per_chunk = INSNLEN;
1307  info->display_endian = info->endian;
1308  info->insn_info_valid = 1;
1309  info->branch_delay_insns = 0;
1310  info->data_size = 0;
1311  info->insn_type = dis_nonbranch;
1312  info->target = 0;
1313  info->target2 = 0;
1314 
1315  op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
1316  if (op != NULL)
1317  {
1318  for (; op < &mips_opcodes[NUMOPCODES]; op++)
1319  {
1320  if (op->pinfo != INSN_MACRO
1321  && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
1322  && (word & op->mask) == op->match)
1323  {
1324  const char *d;
1325 
1326  /* We always allow to disassemble the jalx instruction. */
1327  if (!OPCODE_IS_MEMBER (op, mips_isa, mips_processor) && strcmp (op->name, "jalx")) {
1328  continue;
1329  }
1330 
1331  /* Figure out instruction type and branch delay information. */
1332  if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
1333  {
1334  if ((info->insn_type & INSN_WRITE_GPR_31) != 0) {
1335  info->insn_type = dis_jsr;
1336  } else {
1337  info->insn_type = dis_branch;
1338  }
1339  info->branch_delay_insns = 1;
1340  }
1341  else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
1342  | INSN_COND_BRANCH_LIKELY)) != 0)
1343  {
1344  if ((info->insn_type & INSN_WRITE_GPR_31) != 0) {
1345  info->insn_type = dis_condjsr;
1346  } else {
1347  info->insn_type = dis_condbranch;
1348  }
1349  info->branch_delay_insns = 1;
1350  } else if ((op->pinfo & (INSN_STORE_MEMORY | INSN_LOAD_MEMORY_DELAY)) != 0) {
1351  info->insn_type = dis_dref;
1352  }
1353 
1354  (*info->fprintf_func) (info->stream, "%s", op->name);
1355 
1356  d = op->args;
1357  if (d != NULL && *d != '\0') {
1358  (*info->fprintf_func) (info->stream, " ");
1359  print_insn_args (d, word, memaddr, info, op);
1360  }
1361 
1362  return INSNLEN;
1363  }
1364  }
1365  }
1366 
1367  /* Plugin undefined instructions. */
1368  info->insn_type = dis_noninsn;
1369  (*info->fprintf_func) (info->stream, "0x%lx", word);
1370  return INSNLEN;
1371 }
@ 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_condjsr
Definition: disas-asm.h:53
@ dis_branch
Definition: disas-asm.h:50
#define NUMOPCODES
Definition: hppa.h:1079
#define INSN_WRITE_GPR_31
Definition: mips.h:401
#define INSN_STORE_MEMORY
Definition: mips.h:451
#define INSN_UNCOND_BRANCH_DELAY
Definition: mips.h:431
#define OPCODE_IS_MEMBER(insn, isa, cpu)
Definition: mips.h:618
#define INSN_LOAD_MEMORY_DELAY
Definition: mips.h:427
struct mips_opcode * mips_opcodes
Definition: mips-opc.c:2015
#define INSN_MACRO
Definition: mips.h:473
#define INSN2_ALIAS
Definition: mips.h:465
#define INSN_COND_BRANCH_DELAY
Definition: mips.h:433
#define INSN_COND_BRANCH_LIKELY
Definition: mips.h:435
static void print_insn_args(const char *d, register unsigned long int l, bfd_vma pc, struct disassemble_info *info, const struct mips_opcode *opp)
Definition: mips-dis.c:754
static int mips_processor
Definition: mips-dis.c:452
static int no_aliases
Definition: mips-dis.c:462
static int mips_isa
Definition: mips-dis.c:453
int bfd_boolean
Definition: mybfd.h:98
bool init
Definition: core.c:77

References d, dis_branch, dis_condbranch, dis_condjsr, dis_dref, dis_jsr, dis_nonbranch, dis_noninsn, i, info(), init, INSN2_ALIAS, INSN_COND_BRANCH_DELAY, INSN_COND_BRANCH_LIKELY, INSN_LOAD_MEMORY_DELAY, INSN_MACRO, INSN_STORE_MEMORY, INSN_UNCOND_BRANCH_DELAY, INSN_WRITE_GPR_31, INSNLEN, mips_isa, mips_opcodes, mips_processor, no_aliases, NULL, NUMOPCODES, op, OP_MASK_OP, OP_SH_OP, OPCODE_IS_MEMBER, and print_insn_args().

Referenced by _print_insn_mips().

◆ print_insn_mips16()

static int print_insn_mips16 ( bfd_vma  memaddr,
struct disassemble_info info 
)
static

Definition at line 1888 of file mips-dis.c.

1889 {
1890  int status;
1891  bfd_byte buffer[2];
1892  int length;
1893  int insn;
1894  bfd_boolean use_extend;
1895  int extend = 0;
1896  const struct mips_opcode *op, *opend;
1897 
1898  info->bytes_per_chunk = 2;
1899  info->display_endian = info->endian;
1900  info->insn_info_valid = 1;
1901  info->branch_delay_insns = 0;
1902  info->data_size = 0;
1903  info->insn_type = dis_nonbranch;
1904  info->target = 0;
1905  info->target2 = 0;
1906 
1907  status = (*info->read_memory_func) (memaddr, buffer, 2, info);
1908  if (status != 0)
1909  {
1910  (*info->memory_error_func) (status, memaddr, info);
1911  return -1;
1912  }
1913 
1914  length = 2;
1915 
1916  if (info->endian == BFD_ENDIAN_BIG) {
1917  insn = bfd_getb16 (buffer);
1918  } else {
1919  insn = bfd_getl16 (buffer);
1920  }
1921 
1922  /* Plugin the extend opcode specially. */
1923  use_extend = FALSE;
1924  if ((insn & 0xf800) == 0xf000)
1925  {
1926  use_extend = TRUE;
1927  extend = insn & 0x7ff;
1928 
1929  memaddr += 2;
1930 
1931  status = (*info->read_memory_func) (memaddr, buffer, 2, info);
1932  if (status != 0)
1933  {
1934  (*info->fprintf_func) (info->stream, "extend 0x%x",
1935  (unsigned int) extend);
1936  (*info->memory_error_func) (status, memaddr, info);
1937  return -1;
1938  }
1939 
1940  if (info->endian == BFD_ENDIAN_BIG) {
1941  insn = bfd_getb16 (buffer);
1942  } else {
1943  insn = bfd_getl16 (buffer);
1944  }
1945 
1946  /* Check for an extend opcode followed by an extend opcode. */
1947  if ((insn & 0xf800) == 0xf000) {
1948  (*info->fprintf_func) (info->stream, "extend 0x%x",
1949  (unsigned int)extend);
1950  info->insn_type = dis_noninsn;
1951  return length;
1952  }
1953 
1954  length += 2;
1955  }
1956 
1957  /* FIXME: Should probably use a hash table on the major opcode here. */
1958 
1960  for (op = mips16_opcodes; op < opend; op++)
1961  {
1962  if (op->pinfo != INSN_MACRO
1963  && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
1964  && (insn & op->mask) == op->match)
1965  {
1966  const char *s;
1967 
1968  if (strchr (op->args, 'a') != NULL)
1969  {
1970  if (use_extend)
1971  {
1972  (*info->fprintf_func) (info->stream, "extend 0x%x",
1973  (unsigned int) extend);
1974  info->insn_type = dis_noninsn;
1975  return length - 2;
1976  }
1977 
1978  use_extend = FALSE;
1979 
1980  memaddr += 2;
1981 
1982  status = (*info->read_memory_func) (memaddr, buffer, 2,
1983  info);
1984  if (status == 0)
1985  {
1986  use_extend = TRUE;
1987  if (info->endian == BFD_ENDIAN_BIG) {
1988  extend = bfd_getb16 (buffer);
1989  } else {
1990  extend = bfd_getl16 (buffer);
1991  }
1992  length += 2;
1993  }
1994  }
1995 
1996  (*info->fprintf_func) (info->stream, "%s", op->name);
1997  if (op->args[0] != '\0') {
1998  (*info->fprintf_func) (info->stream, " ");
1999  }
2000 
2001  for (s = op->args; *s != '\0'; s++)
2002  {
2003  if (*s == ','
2004  && s[1] == 'w'
2005  && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
2006  == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
2007  {
2008  /* Skip the register and the comma. */
2009  ++s;
2010  continue;
2011  }
2012  if (*s == ','
2013  && s[1] == 'v'
2014  && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
2015  == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
2016  {
2017  /* Skip the register and the comma. */
2018  ++s;
2019  continue;
2020  }
2021  print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
2022  info);
2023  }
2024 
2025  if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
2026  {
2027  info->branch_delay_insns = 1;
2028  if (info->insn_type != dis_jsr) {
2029  info->insn_type = dis_branch;
2030  }
2031  }
2032 
2033  return length;
2034  }
2035  }
2036 
2037  if (use_extend) {
2038  (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
2039  }
2040  (*info->fprintf_func) (info->stream, "0x%x", insn);
2041  info->insn_type = dis_noninsn;
2042 
2043  return length;
2044 }
static RzILOpBitVector * extend(ut32 dst_bits, arm64_extender ext, RZ_OWN RzILOpBitVector *v, ut32 v_bits)
Definition: arm_il64.c:270
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 static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
#define MIPS16OP_MASK_RZ
Definition: mips.h:915
#define MIPS16OP_MASK_RX
Definition: mips.h:907
#define MIPS16OP_MASK_RY
Definition: mips.h:911
const int bfd_mips16_num_opcodes
Definition: mips16-opc.c:243
#define MIPS16OP_SH_RY
Definition: mips.h:912
#define MIPS16OP_SH_RZ
Definition: mips.h:916
#define MIPS16OP_SH_RX
Definition: mips.h:908
const struct mips_opcode mips16_opcodes[]
Definition: mips16-opc.c:67
static void print_mips16_insn_arg(char type, const struct mips_opcode *op, int l, bfd_boolean use_extend, int extend, bfd_vma memaddr, struct disassemble_info *info)
Definition: mips-dis.c:1376
static bfd_vma bfd_getb16(const void *p)
Definition: mybfd.h:4974
static bfd_vma bfd_getl16(const void *p)
Definition: mybfd.h:4969
#define TRUE
Definition: mybfd.h:103
#define FALSE
Definition: mybfd.h:102
static RzSocket * s
Definition: rtr.c:28

References BFD_ENDIAN_BIG, bfd_getb16(), bfd_getl16(), bfd_mips16_num_opcodes, dis_branch, dis_jsr, dis_nonbranch, dis_noninsn, extend(), FALSE, info(), INSN2_ALIAS, INSN_MACRO, INSN_UNCOND_BRANCH_DELAY, length, mips16_opcodes, MIPS16OP_MASK_RX, MIPS16OP_MASK_RY, MIPS16OP_MASK_RZ, MIPS16OP_SH_RX, MIPS16OP_SH_RY, MIPS16OP_SH_RZ, no_aliases, NULL, op, print_mips16_insn_arg(), s, status, and TRUE.

Referenced by _print_insn_mips().

◆ print_mips16_insn_arg()

static void print_mips16_insn_arg ( char  type,
const struct mips_opcode op,
int  l,
bfd_boolean  use_extend,
int  extend,
bfd_vma  memaddr,
struct disassemble_info info 
)
static

Definition at line 1376 of file mips-dis.c.

1383 {
1384  switch (type)
1385  {
1386  case ',':
1387  case '(':
1388  case ')':
1389  (*info->fprintf_func) (info->stream, "%c", type);
1390  break;
1391 
1392  case 'y':
1393  case 'w':
1394  (*info->fprintf_func) (info->stream, "%s",
1396  & MIPS16OP_MASK_RY)));
1397  break;
1398 
1399  case 'x':
1400  case 'v':
1401  (*info->fprintf_func) (info->stream, "%s",
1403  & MIPS16OP_MASK_RX)));
1404  break;
1405 
1406  case 'z':
1407  (*info->fprintf_func) (info->stream, "%s",
1409  & MIPS16OP_MASK_RZ)));
1410  break;
1411 
1412  case 'Z':
1413  (*info->fprintf_func) (info->stream, "%s",
1415  & MIPS16OP_MASK_MOVE32Z)));
1416  break;
1417 
1418  case '0':
1419  (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[0]);
1420  break;
1421 
1422  case 'S':
1423  (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[29]);
1424  break;
1425 
1426  case 'P':
1427  (*info->fprintf_func) (info->stream, "$pc");
1428  break;
1429 
1430  case 'R':
1431  (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[31]);
1432  break;
1433 
1434  case 'X':
1435  (*info->fprintf_func) (info->stream, "%s",
1437  & MIPS16OP_MASK_REGR32)]);
1438  break;
1439 
1440  case 'Y':
1441  (*info->fprintf_func) (info->stream, "%s",
1443  break;
1444 
1445  case '<':
1446  case '>':
1447  case '[':
1448  case ']':
1449  case '4':
1450  case '5':
1451  case 'H':
1452  case 'W':
1453  case 'D':
1454  case 'j':
1455  case '6':
1456  case '8':
1457  case 'V':
1458  case 'C':
1459  case 'U':
1460  case 'k':
1461  case 'K':
1462  case 'p':
1463  case 'q':
1464  case 'A':
1465  case 'B':
1466  case 'E':
1467  {
1468  int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
1469 
1470  shift = 0;
1471  signedp = 0;
1472  extbits = 16;
1473  pcrel = 0;
1474  extu = 0;
1475  branch = 0;
1476  switch (type)
1477  {
1478  case '<':
1479  nbits = 3;
1480  immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
1481  extbits = 5;
1482  extu = 1;
1483  break;
1484  case '>':
1485  nbits = 3;
1486  immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
1487  extbits = 5;
1488  extu = 1;
1489  break;
1490  case '[':
1491  nbits = 3;
1492  immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
1493  extbits = 6;
1494  extu = 1;
1495  break;
1496  case ']':
1497  nbits = 3;
1498  immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
1499  extbits = 6;
1500  extu = 1;
1501  break;
1502  case '4':
1503  nbits = 4;
1504  immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
1505  signedp = 1;
1506  extbits = 15;
1507  break;
1508  case '5':
1509  nbits = 5;
1510  immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1511  info->insn_type = dis_dref;
1512  info->data_size = 1;
1513  break;
1514  case 'H':
1515  nbits = 5;
1516  shift = 1;
1517  immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1518  info->insn_type = dis_dref;
1519  info->data_size = 2;
1520  break;
1521  case 'W':
1522  nbits = 5;
1523  shift = 2;
1524  immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1525  if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
1526  && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
1527  {
1528  info->insn_type = dis_dref;
1529  info->data_size = 4;
1530  }
1531  break;
1532  case 'D':
1533  nbits = 5;
1534  shift = 3;
1535  immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1536  info->insn_type = dis_dref;
1537  info->data_size = 8;
1538  break;
1539  case 'j':
1540  nbits = 5;
1541  immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1542  signedp = 1;
1543  break;
1544  case '6':
1545  nbits = 6;
1546  immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
1547  break;
1548  case '8':
1549  nbits = 8;
1550  immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1551  break;
1552  case 'V':
1553  nbits = 8;
1554  shift = 2;
1555  immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1556  /* FIXME: This might be lw, or it might be addiu to $sp or
1557  $pc. We assume it's load. */
1558  info->insn_type = dis_dref;
1559  info->data_size = 4;
1560  break;
1561  case 'C':
1562  nbits = 8;
1563  shift = 3;
1564  immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1565  info->insn_type = dis_dref;
1566  info->data_size = 8;
1567  break;
1568  case 'U':
1569  nbits = 8;
1570  immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1571  extu = 1;
1572  break;
1573  case 'k':
1574  nbits = 8;
1575  immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1576  signedp = 1;
1577  break;
1578  case 'K':
1579  nbits = 8;
1580  shift = 3;
1581  immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1582  signedp = 1;
1583  break;
1584  case 'p':
1585  nbits = 8;
1586  immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1587  signedp = 1;
1588  pcrel = 1;
1589  branch = 1;
1590  info->insn_type = dis_condbranch;
1591  break;
1592  case 'q':
1593  nbits = 11;
1594  immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
1595  signedp = 1;
1596  pcrel = 1;
1597  branch = 1;
1598  info->insn_type = dis_branch;
1599  break;
1600  case 'A':
1601  nbits = 8;
1602  shift = 2;
1603  immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1604  pcrel = 1;
1605  /* FIXME: This can be lw or la. We assume it is lw. */
1606  info->insn_type = dis_dref;
1607  info->data_size = 4;
1608  break;
1609  case 'B':
1610  nbits = 5;
1611  shift = 3;
1612  immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1613  pcrel = 1;
1614  info->insn_type = dis_dref;
1615  info->data_size = 8;
1616  break;
1617  case 'E':
1618  nbits = 5;
1619  shift = 2;
1620  immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1621  pcrel = 1;
1622  break;
1623  default:
1624  abort ();
1625  }
1626 
1627  if (! use_extend)
1628  {
1629  if (signedp && immed >= (1 << (nbits - 1))) {
1630  immed -= 1 << nbits;
1631  }
1632  immed <<= shift;
1633  if ((type == '<' || type == '>' || type == '[' || type == ']') && immed == 0) {
1634  immed = 8;
1635  }
1636  }
1637  else
1638  {
1639  if (extbits == 16) {
1640  immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
1641  } else if (extbits == 15) {
1642  immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
1643  } else {
1644  immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
1645  }
1646  immed &= (1 << extbits) - 1;
1647  if (!extu && immed >= (1 << (extbits - 1))) {
1648  immed -= 1 << extbits;
1649  }
1650  }
1651 
1652  if (!pcrel) {
1653  (*info->fprintf_func) (info->stream, "%d", immed);
1654  } else {
1655  bfd_vma baseaddr;
1656 
1657  if (branch) {
1658  immed *= 2;
1659  baseaddr = memaddr + 2;
1660  } else if (use_extend) {
1661  baseaddr = memaddr - 2;
1662  } else {
1663  int status;
1664  bfd_byte buffer[2];
1665 
1666  baseaddr = memaddr;
1667 
1668  /* If this instruction is in the delay slot of a jr
1669  instruction, the base address is the address of the
1670  jr instruction. If it is in the delay slot of jalr
1671  instruction, the base address is the address of the
1672  jalr instruction. This test is unreliable: we have
1673  no way of knowing whether the previous word is
1674  instruction or data. */
1675  status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
1676  info);
1677  if (status == 0 && (((info->endian == BFD_ENDIAN_BIG
1678  ? bfd_getb16 (buffer)
1679  : bfd_getl16 (buffer)) &
1680  0xf800) == 0x1800)) {
1681  baseaddr = memaddr - 4;
1682  } else {
1683  status = (*info->read_memory_func) (memaddr - 2, buffer,
1684  2, info);
1685  if (status == 0 && (((info->endian == BFD_ENDIAN_BIG
1686  ? bfd_getb16 (buffer)
1687  : bfd_getl16 (buffer)) &
1688  0xf81f) == 0xe800)) {
1689  baseaddr = memaddr - 2;
1690  }
1691  }
1692  }
1693  info->target = (baseaddr & ~((1 << shift) - 1)) + immed;
1694  if (pcrel && branch && info->flavour == bfd_target_unknown_flavour) {
1695  /* For gdb disassembler, maintain odd address. */
1696  info->target |= 1;
1697  }
1698  (*info->print_address_func) (info->target, info);
1699  }
1700  }
1701  break;
1702 
1703  case 'a':
1704  {
1705  int jalx = l & 0x400;
1706 
1707  if (!use_extend) {
1708  extend = 0;
1709  }
1710  l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
1711  if (!jalx && info->flavour == bfd_target_unknown_flavour) {
1712  /* For gdb disassembler, maintain odd address. */
1713  l |= 1;
1714  }
1715  }
1716  info->target = ((memaddr + 4) & ~(bfd_vma) 0x0fffffff) | l;
1717  (*info->print_address_func) (info->target, info);
1718  info->insn_type = dis_jsr;
1719  info->branch_delay_insns = 1;
1720  break;
1721 
1722  case 'l':
1723  case 'L':
1724  {
1725  int need_comma, amask, smask;
1726 
1727  need_comma = 0;
1728 
1729  l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
1730 
1731  amask = (l >> 3) & 7;
1732 
1733  if (amask > 0 && amask < 5)
1734  {
1735  (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[4]);
1736  if (amask > 1) {
1737  (*info->fprintf_func) (info->stream, "-%s",
1738  mips_gpr_names[amask + 3]);
1739  }
1740  need_comma = 1;
1741  }
1742 
1743  smask = (l >> 1) & 3;
1744  if (smask == 3)
1745  {
1746  (*info->fprintf_func) (info->stream, "%s??",
1747  need_comma ? ", " : "");
1748  need_comma = 1;
1749  }
1750  else if (smask > 0)
1751  {
1752  (*info->fprintf_func) (info->stream, "%s%s",
1753  need_comma ? ", " : "",
1754  mips_gpr_names[16]);
1755  if (smask > 1) {
1756  (*info->fprintf_func) (info->stream, "-%s",
1757  mips_gpr_names[smask + 15]);
1758  }
1759  need_comma = 1;
1760  }
1761 
1762  if (l & 1)
1763  {
1764  (*info->fprintf_func) (info->stream, "%s%s",
1765  need_comma ? ", " : "",
1766  mips_gpr_names[31]);
1767  need_comma = 1;
1768  }
1769 
1770  if (amask == 5 || amask == 6)
1771  {
1772  (*info->fprintf_func) (info->stream, "%s$f0",
1773  need_comma ? ", " : "");
1774  if (amask == 6) {
1775  (*info->fprintf_func) (info->stream, "-$f1");
1776  }
1777  }
1778  }
1779  break;
1780 
1781  case 'm':
1782  case 'M':
1783  /* MIPS16e save/restore. */
1784  {
1785  int need_comma = 0;
1786  int amask, args, statics;
1787  int nsreg, smask;
1788  int framesz;
1789  int i, j;
1790 
1791  l = l & 0x7f;
1792  if (use_extend) {
1793  l |= extend << 16;
1794  }
1795 
1796  amask = (l >> 16) & 0xf;
1797  if (amask == MIPS16_ALL_ARGS)
1798  {
1799  args = 4;
1800  statics = 0;
1801  }
1802  else if (amask == MIPS16_ALL_STATICS)
1803  {
1804  args = 0;
1805  statics = 4;
1806  }
1807  else
1808  {
1809  args = amask >> 2;
1810  statics = amask & 3;
1811  }
1812 
1813  if (args > 0) {
1814  (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[4]);
1815  if (args > 1) {
1816  (*info->fprintf_func) (info->stream, "-%s",
1817  mips_gpr_names[4 + args - 1]);
1818  }
1819  need_comma = 1;
1820  }
1821 
1822  framesz = (((l >> 16) & 0xf0) | (l & 0x0f)) * 8;
1823  if (framesz == 0 && !use_extend) {
1824  framesz = 128;
1825  }
1826 
1827  (*info->fprintf_func) (info->stream, "%s%d",
1828  need_comma ? ", " : "",
1829  framesz);
1830 
1831  if (l & 0x40) { /* $ra */
1832  (*info->fprintf_func) (info->stream, ", %s", mips_gpr_names[31]);
1833  }
1834 
1835  nsreg = (l >> 24) & 0x7;
1836  smask = 0;
1837  if (l & 0x20) { /* $s0 */
1838  smask |= 1 << 0;
1839  }
1840  if (l & 0x10) { /* $s1 */
1841  smask |= 1 << 1;
1842  }
1843  if (nsreg > 0) { /* $s2-$s8 */
1844  smask |= ((1 << nsreg) - 1) << 2;
1845  }
1846 
1847  /* Find first set static reg bit. */
1848  for (i = 0; i < 9; i++)
1849  {
1850  if (smask & (1 << i))
1851  {
1852  (*info->fprintf_func) (info->stream, ", %s",
1853  mips_gpr_names[i == 8 ? 30 : (16 + i)]);
1854  /* Skip over string of set bits. */
1855  for (j = i; smask & (2 << j); j++) {}
1856  if (j > i) {
1857  (*info->fprintf_func) (info->stream, "-%s",
1858  mips_gpr_names[j == 8 ? 30 : (16 + j)]);
1859  }
1860  i = j + 1;
1861  }
1862  }
1863 
1864  /* Statics $ax - $a3. */
1865  if (statics == 1) {
1866  (*info->fprintf_func) (info->stream, ", %s", mips_gpr_names[7]);
1867  } else if (statics > 0) {
1868  (*info->fprintf_func) (info->stream, ", %s-%s",
1869  mips_gpr_names[7 - statics + 1],
1870  mips_gpr_names[7]);
1871  }
1872  }
1873  break;
1874 
1875  default:
1876  /* xgettext:c-format */
1877  (*info->fprintf_func)
1878  (info->stream,
1879  _("# internal disassembler error, unrecognised modifier (%c)"),
1880  type);
1881  abort ();
1882  }
1883 }
static RZ_NULLABLE RzILOpBitVector * shift(RzILOpBitVector *val, RZ_NULLABLE RzILOpBool **carry_out, arm_shifter type, RZ_OWN RzILOpBitVector *dist)
Definition: arm_il32.c:190
#define MIPS16OP_SH_MOVE32Z
Definition: mips.h:925
#define MIPS16OP_SH_REGR32
Definition: mips.h:920
#define MIPS16OP_MASK_REGR32
Definition: mips.h:919
#define MIPS16OP_MASK_IMM6
Definition: mips.h:926
#define MIPS16OP_MASK_IMM4
Definition: mips.h:917
#define MIPS16_ALL_STATICS
Definition: mips.h:983
#define MIPS16OP_SH_IMM6
Definition: mips.h:927
#define MIPS16OP_MASK_MOVE32Z
Definition: mips.h:924
#define MIPS16OP_EXTRACT_REG32R(i)
Definition: mips.h:923
#define MIPS16OP_SH_IMM8
Definition: mips.h:910
#define MIPS16OP_MASK_IMM11
Definition: mips.h:905
#define MIPS16_INSN_READ_PC
Definition: mips.h:1015
#define MIPS16OP_SH_IMM11
Definition: mips.h:906
#define MIPS16OP_MASK_IMM5
Definition: mips.h:913
#define MIPS16OP_SH_IMM5
Definition: mips.h:914
#define MIPS16_ALL_ARGS
Definition: mips.h:982
#define MIPS16OP_SH_IMM4
Definition: mips.h:918
#define MIPS16_INSN_READ_SP
Definition: mips.h:1011
#define MIPS16OP_MASK_IMM8
Definition: mips.h:909
#define mips16_reg_names(rn)
Definition: mips-dis.c:64
int args
Definition: mipsasm.c:18
int type
Definition: mipsasm.c:17
@ bfd_target_unknown_flavour
Definition: mybfd.h:4592
static int baseaddr
Definition: z80asm.c:79

References _, args, baseaddr, BFD_ENDIAN_BIG, bfd_getb16(), bfd_getl16(), bfd_target_unknown_flavour, test-lz4-speed::branch, dis_branch, dis_condbranch, dis_dref, dis_jsr, extend(), i, info(), MIPS16_ALL_ARGS, MIPS16_ALL_STATICS, MIPS16_INSN_READ_PC, MIPS16_INSN_READ_SP, mips16_reg_names, MIPS16OP_EXTRACT_REG32R, MIPS16OP_MASK_IMM11, MIPS16OP_MASK_IMM4, MIPS16OP_MASK_IMM5, MIPS16OP_MASK_IMM6, MIPS16OP_MASK_IMM8, MIPS16OP_MASK_MOVE32Z, MIPS16OP_MASK_REGR32, MIPS16OP_MASK_RX, MIPS16OP_MASK_RY, MIPS16OP_MASK_RZ, MIPS16OP_SH_IMM11, MIPS16OP_SH_IMM4, MIPS16OP_SH_IMM5, MIPS16OP_SH_IMM6, MIPS16OP_SH_IMM8, MIPS16OP_SH_MOVE32Z, MIPS16OP_SH_REGR32, MIPS16OP_SH_RX, MIPS16OP_SH_RY, MIPS16OP_SH_RZ, mips_gpr_names, shift(), status, and type.

Referenced by print_insn_mips16().

◆ print_mips_disassembler_options()

void print_mips_disassembler_options ( FILE *  stream)

Definition at line 2110 of file mips-dis.c.

2111 {
2112  unsigned int i;
2113 
2114  fprintf (stream, _("\n\
2115 The following MIPS specific disassembler options are supported for use\n\
2116 with the -M switch (multiple options should be separated by commas):\n"));
2117 
2118  fprintf (stream, _("\n\
2119  gpr-names=ABI Print GPR names according to specified ABI.\n\
2120  Default: based on binary being disassembled.\n"));
2121 
2122  fprintf (stream, _("\n\
2123  fpr-names=ABI Print FPR names according to specified ABI.\n\
2124  Default: numeric.\n"));
2125 
2126  fprintf (stream, _("\n\
2127  cp0-names=ARCH Print CP0 register names according to\n\
2128  specified architecture.\n\
2129  Default: based on binary being disassembled.\n"));
2130 
2131  fprintf (stream, _("\n\
2132  hwr-names=ARCH Print HWR names according to specified \n\
2133  architecture.\n\
2134  Default: based on binary being disassembled.\n"));
2135 
2136  fprintf (stream, _("\n\
2137  reg-names=ABI Print GPR and FPR names according to\n\
2138  specified ABI.\n"));
2139 
2140  fprintf (stream, _("\n\
2141  reg-names=ARCH Print CP0 register and HWR names according to\n\
2142  specified architecture.\n"));
2143 
2144  fprintf (stream, _("\n\
2145  For the options above, the following values are supported for \"ABI\":\n\
2146  "));
2147  for (i = 0; i < ARRAY_SIZE (mips_abi_choices); i++) {
2148  fprintf (stream, " %s", mips_abi_choices[i].name);
2149  }
2150  fprintf (stream, _("\n"));
2151 
2152  fprintf (stream, _("\n\
2153  For the options above, The following values are supported for \"ARCH\":\n\
2154  "));
2155  for (i = 0; i < ARRAY_SIZE (mips_arch_choices); i++) {
2156  if (*mips_arch_choices[i].name != '\0') {
2157  fprintf (stream, " %s", mips_arch_choices[i].name);
2158  }
2159  }
2160  fprintf (stream, _("\n"));
2161 
2162  fprintf (stream, _("\n"));
2163 }
voidpf stream
Definition: ioapi.h:138

References _, ARRAY_SIZE, i, mips_abi_choices, and mips_arch_choices.

◆ set_default_mips_dis_options()

static void set_default_mips_dis_options ( struct disassemble_info info)
static

Definition at line 540 of file mips-dis.c.

541 {
542  const struct mips_arch_choice *chosen_arch;
543 
544  /* Defaults: mipsIII/r3000 (?!), (o)32-style ("oldabi") GPR names,
545  and numeric FPR, CP0 register, and HWR names. */
547  mips_processor = CPU_LOONGSON_2F; // R3000
554  no_aliases = 0;
555 
556  /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
557  if (info->flavour == bfd_target_elf_flavour && info->section != NULL)
558  {
560 
561  header = elf_elfheader (info->section->owner);
562  if (is_newabi (header)) {
564  }
565  }
566 
567  /* Set ISA, architecture, and cp0 register names as best we can. */
568 #if ! SYMTAB_AVAILABLE
569  /* This is running out on a target machine, not in a host tool.
570  FIXME: Where does mips_target_info come from? */
571  target_processor = mips_target_info.processor;
572  mips_isa = mips_target_info.isa;
573 #else
574  chosen_arch = choose_arch_by_number (info->mach);
575  if (chosen_arch != NULL)
576  {
577  mips_processor = chosen_arch->processor;
578  mips_isa = chosen_arch->isa;
579  mips_cp0_names = chosen_arch->cp0_names;
580  mips_cp0sel_names = chosen_arch->cp0sel_names;
582  mips_hwr_names = chosen_arch->hwr_names;
583  }
584 #endif
585 }
#define elf_elfheader(bfd)
Definition: elf-bfd.h:1369
#define CPU_LOONGSON_2F
Definition: mips.h:610
#define ISA_MIPS3
Definition: mips.h:569
static const char *const mips_hwr_names_numeric[32]
Definition: mips-dis.c:302
const char *const mips_gpr_names_newabi[32]
Definition: mips-dis.c:83
static const struct mips_arch_choice * choose_arch_by_number(unsigned long mach)
Definition: mips-dis.c:495
static int is_newabi(Elf_Internal_Ehdr *header)
Definition: mips-dis.c:524
const char *const mips_gpr_names_oldabi[32]
Definition: mips-dis.c:75
static const char *const mips_cp0_names_numeric[32]
Definition: mips-dis.c:123
static const char *const mips_fpr_names_numeric[32]
Definition: mips-dis.c:91

References bfd_target_elf_flavour, choose_arch_by_number(), mips_arch_choice::cp0_names, mips_arch_choice::cp0sel_names, mips_arch_choice::cp0sel_names_len, CPU_LOONGSON_2F, elf_elfheader, header, mips_arch_choice::hwr_names, info(), is_newabi(), mips_arch_choice::isa, ISA_MIPS3, mips_cp0_names, mips_cp0_names_numeric, mips_cp0sel_names, mips_cp0sel_names_len, mips_fpr_names, mips_fpr_names_numeric, mips_gpr_names, mips_gpr_names_newabi, mips_gpr_names_oldabi, mips_hwr_names, mips_hwr_names_numeric, mips_isa, mips_processor, no_aliases, NULL, and mips_arch_choice::processor.

Referenced by _print_insn_mips().

Variable Documentation

◆ mips16_to_32_reg_map

const unsigned int mips16_to_32_reg_map[]
static
Initial value:
=
{
16, 17, 2, 3, 4, 5, 6, 7
}

Definition at line 59 of file mips-dis.c.

◆ mips_abi_choices

struct mips_abi_choice mips_abi_choices[]
Initial value:
=
{
}
static const char *const mips_fpr_names_n32[32]
Definition: mips-dis.c:107
static const char *const mips_fpr_names_32[32]
Definition: mips-dis.c:99
static const char *const mips_gpr_names_numeric[32]
Definition: mips-dis.c:67
static const char *const mips_fpr_names_64[32]
Definition: mips-dis.c:115

Definition at line 310 of file mips-dis.c.

Referenced by choose_abi_by_name(), and print_mips_disassembler_options().

◆ mips_arch_choices

const struct mips_arch_choice mips_arch_choices[]

◆ mips_cp0_names

const char* const* mips_cp0_names
static

◆ mips_cp0_names_mips3264

const char* const mips_cp0_names_mips3264[32]
static
Initial value:
=
{
"c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
"c0_context", "c0_pagemask", "c0_wired", "$7",
"c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
"c0_status", "c0_cause", "c0_epc", "c0_prid",
"c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
"c0_xcontext", "$21", "$22", "c0_debug",
"c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
"c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
}

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

◆ mips_cp0_names_mips3264r2

const char* const mips_cp0_names_mips3264r2[32]
static
Initial value:
=
{
"c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
"c0_context", "c0_pagemask", "c0_wired", "c0_hwrena",
"c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
"c0_status", "c0_cause", "c0_epc", "c0_prid",
"c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
"c0_xcontext", "$21", "$22", "c0_debug",
"c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
"c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
}

Definition at line 176 of file mips-dis.c.

◆ mips_cp0_names_numeric

const char* const mips_cp0_names_numeric[32]
static
Initial value:
=
{
"$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
"$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
"$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
}

Definition at line 123 of file mips-dis.c.

Referenced by set_default_mips_dis_options().

◆ mips_cp0_names_sb1

const char* const mips_cp0_names_sb1[32]
static
Initial value:
=
{
"c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
"c0_context", "c0_pagemask", "c0_wired", "$7",
"c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
"c0_status", "c0_cause", "c0_epc", "c0_prid",
"c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
"c0_xcontext", "$21", "$22", "c0_debug",
"c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
"c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
}

Definition at line 265 of file mips-dis.c.

◆ mips_cp0sel_names

const struct mips_cp0sel_name* mips_cp0sel_names
static

◆ mips_cp0sel_names_len

int mips_cp0sel_names_len
static

◆ mips_cp0sel_names_mips3264

const struct mips_cp0sel_name mips_cp0sel_names_mips3264[]
static

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

◆ mips_cp0sel_names_mips3264r2

const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2[]
static

Definition at line 176 of file mips-dis.c.

◆ mips_cp0sel_names_sb1

const struct mips_cp0sel_name mips_cp0sel_names_sb1[]
static
Initial value:
=
{
{ 16, 1, "c0_config1" },
{ 18, 1, "c0_watchlo,1" },
{ 19, 1, "c0_watchhi,1" },
{ 22, 0, "c0_perftrace" },
{ 23, 3, "c0_edebug" },
{ 25, 1, "c0_perfcnt,1" },
{ 25, 2, "c0_perfcnt,2" },
{ 25, 3, "c0_perfcnt,3" },
{ 25, 4, "c0_perfcnt,4" },
{ 25, 5, "c0_perfcnt,5" },
{ 25, 6, "c0_perfcnt,6" },
{ 25, 7, "c0_perfcnt,7" },
{ 26, 1, "c0_buserr_pa" },
{ 27, 1, "c0_cacheerr_d" },
{ 27, 3, "c0_cacheerr_d_pa" },
{ 28, 1, "c0_datalo_i" },
{ 28, 2, "c0_taglo_d" },
{ 28, 3, "c0_datalo_d" },
{ 29, 1, "c0_datahi_i" },
{ 29, 2, "c0_taghi_d" },
{ 29, 3, "c0_datahi_d" },
}

Definition at line 265 of file mips-dis.c.

◆ mips_fpr_names

const char* const* mips_fpr_names
static

◆ mips_fpr_names_32

const char* const mips_fpr_names_32[32]
static
Initial value:
=
{
"fv0", "fv0f", "fv1", "fv1f", "ft0", "ft0f", "ft1", "ft1f",
"ft2", "ft2f", "ft3", "ft3f", "fa0", "fa0f", "fa1", "fa1f",
"ft4", "ft4f", "ft5", "ft5f", "fs0", "fs0f", "fs1", "fs1f",
"fs2", "fs2f", "fs3", "fs3f", "fs4", "fs4f", "fs5", "fs5f"
}

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

◆ mips_fpr_names_64

const char* const mips_fpr_names_64[32]
static
Initial value:
=
{
"fv0", "ft12", "fv1", "ft13", "ft0", "ft1", "ft2", "ft3",
"ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
"fa4", "fa5", "fa6", "fa7", "ft8", "ft9", "ft10", "ft11",
"fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7"
}

Definition at line 115 of file mips-dis.c.

◆ mips_fpr_names_n32

const char* const mips_fpr_names_n32[32]
static
Initial value:
=
{
"fv0", "ft14", "fv1", "ft15", "ft0", "ft1", "ft2", "ft3",
"ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
"fa4", "fa5", "fa6", "fa7", "fs0", "ft8", "fs1", "ft9",
"fs2", "ft10", "fs3", "ft11", "fs4", "ft12", "fs5", "ft13"
}

Definition at line 107 of file mips-dis.c.

◆ mips_fpr_names_numeric

const char* const mips_fpr_names_numeric[32]
static
Initial value:
=
{
"$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"
}

Definition at line 91 of file mips-dis.c.

Referenced by set_default_mips_dis_options().

◆ mips_gpr_names

const char* const* mips_gpr_names
static

◆ mips_gpr_names_newabi

const char* const mips_gpr_names_newabi[32]
Initial value:
=
{
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
}

Definition at line 83 of file mips-dis.c.

Referenced by set_default_mips_dis_options().

◆ mips_gpr_names_numeric

const char* const mips_gpr_names_numeric[32]
static
Initial value:
=
{
"$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
"$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
"$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
}

Definition at line 67 of file mips-dis.c.

◆ mips_gpr_names_oldabi

const char* const mips_gpr_names_oldabi[32]
Initial value:
=
{
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
}

Definition at line 75 of file mips-dis.c.

Referenced by set_default_mips_dis_options().

◆ mips_hwr_names

const char* const* mips_hwr_names
static

◆ mips_hwr_names_mips3264r2

const char* const mips_hwr_names_mips3264r2[32]
static
Initial value:
=
{
"hwr_cpunum", "hwr_synci_step", "hwr_cc", "hwr_ccres",
"$4", "$5", "$6", "$7",
"$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
"$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
}

Definition at line 310 of file mips-dis.c.

◆ mips_hwr_names_numeric

const char* const mips_hwr_names_numeric[32]
static
Initial value:
=
{
"$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
"$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
"$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
}

Definition at line 302 of file mips-dis.c.

Referenced by set_default_mips_dis_options().

◆ mips_isa

int mips_isa
static

Definition at line 453 of file mips-dis.c.

Referenced by print_insn_mips(), and set_default_mips_dis_options().

◆ mips_processor

int mips_processor
static

Definition at line 452 of file mips-dis.c.

Referenced by print_insn_mips(), and set_default_mips_dis_options().

◆ no_aliases

int no_aliases
static

Definition at line 462 of file mips-dis.c.

Referenced by print_insn_mips(), print_insn_mips16(), and set_default_mips_dis_options().