print_insn_sparc (bfd_vma memaddr, disassemble_info *info)

{

  FILE *stream = info->stream;

  bfd_byte buffer[4];

  unsigned long insn;

  sparc_opcode_hash *op;

  /* Nonzero of opcode table has been initialized.  */

  static int opcodes_initialized = 0;

  /* bfd mach number of last call.  */

  static unsigned long current_mach = 0;

  bfd_vma (*getword) (const unsigned char *);



  if (!opcodes_initialized

      || info->mach != current_mach)

    {

      int i;



      current_arch_mask = compute_arch_mask (info->mach);



      if (!opcodes_initialized)

        sorted_opcodes =

          malloc (sparc_num_opcodes * sizeof (sparc_opcode *));

      /* Reset the sorted table so we can resort it.  */

      for (i = 0; i < sparc_num_opcodes; ++i)

        sorted_opcodes[i] = &sparc_opcodes[i];

      qsort ((char *) sorted_opcodes, sparc_num_opcodes,

             sizeof (sorted_opcodes[0]), compare_opcodes);



      build_hash_table (sorted_opcodes, opcode_hash_table, sparc_num_opcodes);

      current_mach = info->mach;

      opcodes_initialized = 1;

    }



  {

    int status =

      (*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info);



    if (status != 0)

      {

        (*info->memory_error_func) (status, memaddr, info);

        return -1;

      }

  }



  /* On SPARClite variants such as DANlite (sparc86x), instructions

     are always big-endian even when the machine is in little-endian mode.  */

  if (info->endian == BFD_ENDIAN_BIG || info->mach == bfd_mach_sparc_sparclite)

    getword = bfd_getb32;

  else

    getword = bfd_getl32;



  insn = getword (buffer);



  info->insn_info_valid = 1;                    /* We do return this info.  */

  info->insn_type = dis_nonbranch;              /* Assume non branch insn.  */

  info->branch_delay_insns = 0;                 /* Assume no delay.  */

  info->target = 0;                             /* Assume no target known.  */



  for (op = opcode_hash_table[HASH_INSN (insn)]; op; op = op->next)

    {

      const sparc_opcode *opcode = op->opcode;



      /* If the insn isn't supported by the current architecture, skip it.  */

      if (! (opcode->architecture & current_arch_mask))

        continue;



      if ((opcode->match & insn) == opcode->match

          && (opcode->lose & insn) == 0)

        {

          /* Nonzero means that we have found an instruction which has

             the effect of adding or or'ing the imm13 field to rs1.  */

          int imm_added_to_rs1 = 0;

          int imm_ored_to_rs1 = 0;



          /* Nonzero means that we have found a plus sign in the args

             field of the opcode table.  */

          int found_plus = 0;



          /* Nonzero means we have an annulled branch.  */

          /* int is_annulled = 0; */ /* see FIXME below */



          /* Do we have an `add' or `or' instruction combining an

             immediate with rs1?  */

          if (opcode->match == 0x80102000) /* or */

            imm_ored_to_rs1 = 1;

          if (opcode->match == 0x80002000) /* add */

            imm_added_to_rs1 = 1;



          if (X_RS1 (insn) != X_RD (insn)

              && strchr (opcode->args, 'r') != NULL)

              /* Can't do simple format if source and dest are different.  */

              continue;

          if (X_RS2 (insn) != X_RD (insn)

              && strchr (opcode->args, 'O') != NULL)

              /* Can't do simple format if source and dest are different.  */

              continue;



          (*info->fprintf_func) (stream, "%s", opcode->name);



          {

            const char *s;



            if (opcode->args[0] != ',')

              (*info->fprintf_func) (stream, " ");



            for (s = opcode->args; *s != '\0'; ++s)

              {

                while (*s == ',')

                  {

                    (*info->fprintf_func) (stream, ",");

                    ++s;

                    switch (*s)

                      {

                      case 'a':

                        (*info->fprintf_func) (stream, "a");

                        /* is_annulled = 1; */ /* see FIXME below */

                        ++s;

                        continue;

                      case 'N':

                        (*info->fprintf_func) (stream, "pn");

                        ++s;

                        continue;



                      case 'T':

                        (*info->fprintf_func) (stream, "pt");

                        ++s;

                        continue;



                      default:

                        break;

                      }

                  }



                (*info->fprintf_func) (stream, " ");



                switch (*s)

                  {

                  case '+':

                    found_plus = 1;

                    /* Fall through.  */



                  default:

                    (*info->fprintf_func) (stream, "%c", *s);

                    break;



                  case '#':

                    (*info->fprintf_func) (stream, "0");

                    break;



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

                  case '1':

                  case 'r':

                    reg (X_RS1 (insn));

                    break;



                  case '2':

                  case 'O':

                    reg (X_RS2 (insn));

                    break;



                  case 'd':

                    reg (X_RD (insn));

                    break;

#undef  reg



#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)])

                  case 'e':

                    freg (X_RS1 (insn));

                    break;

                  case 'v':     /* Double/even.  */

                  case 'V':     /* Quad/multiple of 4.  */

                    fregx (X_RS1 (insn));

                    break;



                  case 'f':

                    freg (X_RS2 (insn));

                    break;

                  case 'B':     /* Double/even.  */

                  case 'R':     /* Quad/multiple of 4.  */

                    fregx (X_RS2 (insn));

                    break;



                  case 'g':

                    freg (X_RD (insn));

                    break;

                  case 'H':     /* Double/even.  */

                  case 'J':     /* Quad/multiple of 4.  */

                    fregx (X_RD (insn));

                    break;

#undef  freg

#undef  fregx



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

                  case 'b':

                    creg (X_RS1 (insn));

                    break;



                  case 'c':

                    creg (X_RS2 (insn));

                    break;



                  case 'D':

                    creg (X_RD (insn));

                    break;

#undef  creg



                  case 'h':

                    (*info->fprintf_func) (stream, "%%hi(%#x)",

                                           ((unsigned) 0xFFFFFFFF

                                            & ((int) X_IMM22 (insn) << 10)));

                    break;



                  case 'i':     /* 13 bit immediate.  */

                  case 'I':     /* 11 bit immediate.  */

                  case 'j':     /* 10 bit immediate.  */

                    {

                      int imm;



                      if (*s == 'i')

                        imm = X_SIMM (insn, 13);

                      else if (*s == 'I')

                        imm = X_SIMM (insn, 11);

                      else

                        imm = X_SIMM (insn, 10);



                      /* Check to see whether we have a 1+i, and take

                         note of that fact.



                         Note: because of the way we sort the table,

                         we will be matching 1+i rather than i+1,

                         so it is OK to assume that i is after +,

                         not before it.  */

                      if (found_plus)

                        imm_added_to_rs1 = 1;



                      if (imm <= 9)

                        (*info->fprintf_func) (stream, "%d", imm);

                      else

                        (*info->fprintf_func) (stream, "%#x", imm);

                    }

                    break;



                  case 'X':     /* 5 bit unsigned immediate.  */

                  case 'Y':     /* 6 bit unsigned immediate.  */

                    {

                      int imm = X_IMM (insn, *s == 'X' ? 5 : 6);



                      if (imm <= 9)

                        (info->fprintf_func) (stream, "%d", imm);

                      else

                        (info->fprintf_func) (stream, "%#x", (unsigned) imm);

                    }

                    break;



                  case '3':

                    (info->fprintf_func) (stream, "%ld", X_IMM (insn, 3));

                    break;



                  case 'K':

                    {

                      int mask = X_MEMBAR (insn);

                      int bit = 0x40, printed_one = 0;

                      const char *name;



                      if (mask == 0)

                        (info->fprintf_func) (stream, "0");

                      else

                        while (bit)

                          {

                            if (mask & bit)

                              {

                                if (printed_one)

                                  (info->fprintf_func) (stream, "|");

                                name = sparc_decode_membar (bit);

                                (info->fprintf_func) (stream, "%s", name);

                                printed_one = 1;

                              }

                            bit >>= 1;

                          }

                      break;

                    }



                  case 'k':

                    info->target = memaddr + SEX (X_DISP16 (insn), 16) * 4;

                    (*info->print_address_func) (info->target, info);

                    break;



                  case 'G':

                    info->target = memaddr + SEX (X_DISP19 (insn), 19) * 4;

                    (*info->print_address_func) (info->target, info);

                    break;



                  case '6':

                  case '7':

                  case '8':

                  case '9':

                    (*info->fprintf_func) (stream, "%%fcc%c", *s - '6' + '0');

                    break;



                  case 'z':

                    (*info->fprintf_func) (stream, "%%icc");

                    break;



                  case 'Z':

                    (*info->fprintf_func) (stream, "%%xcc");

                    break;



                  case 'E':

                    (*info->fprintf_func) (stream, "%%ccr");

                    break;



                  case 's':

                    (*info->fprintf_func) (stream, "%%fprs");

                    break;



                  case 'o':

                    (*info->fprintf_func) (stream, "%%asi");

                    break;



                  case 'W':

                    (*info->fprintf_func) (stream, "%%tick");

                    break;



                  case 'P':

                    (*info->fprintf_func) (stream, "%%pc");

                    break;



                  case '?':

                    if (X_RS1 (insn) == 31)

                      (*info->fprintf_func) (stream, "%%ver");

                    else if ((unsigned) X_RS1 (insn) < 17)

                      (*info->fprintf_func) (stream, "%%%s",

                                             v9_priv_reg_names[X_RS1 (insn)]);

                    else

                      (*info->fprintf_func) (stream, "%%reserved");

                    break;



                  case '!':

                    if ((unsigned) X_RD (insn) < 17)

                      (*info->fprintf_func) (stream, "%%%s",

                                             v9_priv_reg_names[X_RD (insn)]);

                    else

                      (*info->fprintf_func) (stream, "%%reserved");

                    break;



                  case '$':

                    if ((unsigned) X_RS1 (insn) < 32)

                      (*info->fprintf_func) (stream, "%%%s",

                                             v9_hpriv_reg_names[X_RS1 (insn)]);

                    else

                      (*info->fprintf_func) (stream, "%%reserved");

                    break;



                  case '%':

                    if ((unsigned) X_RD (insn) < 32)

                      (*info->fprintf_func) (stream, "%%%s",

                                             v9_hpriv_reg_names[X_RD (insn)]);

                    else

                      (*info->fprintf_func) (stream, "%%reserved");

                    break;



                  case '/':

                    if (X_RS1 (insn) < 16 || X_RS1 (insn) > 25)

                      (*info->fprintf_func) (stream, "%%reserved");

                    else

                      (*info->fprintf_func) (stream, "%%%s",

                                             v9a_asr_reg_names[X_RS1 (insn)-16]);

                    break;



                  case '_':

                    if (X_RD (insn) < 16 || X_RD (insn) > 25)

                      (*info->fprintf_func) (stream, "%%reserved");

                    else

                      (*info->fprintf_func) (stream, "%%%s",

                                             v9a_asr_reg_names[X_RD (insn)-16]);

                    break;



                  case '*':

                    {

                      const char *name = sparc_decode_prefetch (X_RD (insn));



                      if (name)

                        (*info->fprintf_func) (stream, "%s", name);

                      else

                        (*info->fprintf_func) (stream, "%ld", X_RD (insn));

                      break;

                    }



                  case 'M':

                    (*info->fprintf_func) (stream, "%%asr%ld", X_RS1 (insn));

                    break;



                  case 'm':

                    (*info->fprintf_func) (stream, "%%asr%ld", X_RD (insn));

                    break;



                  case 'L':

                    info->target = memaddr + SEX (X_DISP30 (insn), 30) * 4;

                    (*info->print_address_func) (info->target, info);

                    break;



                  case 'n':

                    (*info->fprintf_func)

                      (stream, "%#x", SEX (X_DISP22 (insn), 22));

                    break;



                  case 'l':

                    info->target = memaddr + SEX (X_DISP22 (insn), 22) * 4;

                    (*info->print_address_func) (info->target, info);

                    break;



                  case 'A':

                    {

                      const char *name;



                      if ((info->mach == bfd_mach_sparc_v8plusa) ||

                          ((info->mach >= bfd_mach_sparc_v9) &&

                           (info->mach <= bfd_mach_sparc_v9b)))

                        name = sparc_decode_asi_v9 (X_ASI (insn));

                      else

                        name = sparc_decode_asi_v8 (X_ASI (insn));



                      if (name)

                        (*info->fprintf_func) (stream, "%s", name);

                      else

                        (*info->fprintf_func) (stream, "(%ld)", X_ASI (insn));

                      break;

                    }



                  case 'C':

                    (*info->fprintf_func) (stream, "%%csr");

                    break;



                  case 'F':

                    (*info->fprintf_func) (stream, "%%fsr");

                    break;



                  case 'p':

                    (*info->fprintf_func) (stream, "%%psr");

                    break;



                  case 'q':

                    (*info->fprintf_func) (stream, "%%fq");

                    break;



                  case 'Q':

                    (*info->fprintf_func) (stream, "%%cq");

                    break;



                  case 't':

                    (*info->fprintf_func) (stream, "%%tbr");

                    break;



                  case 'w':

                    (*info->fprintf_func) (stream, "%%wim");

                    break;



                  case 'x':

                    (*info->fprintf_func) (stream, "%ld",

                                           ((X_LDST_I (insn) << 8)

                                            + X_ASI (insn)));

                    break;



                  case 'y':

                    (*info->fprintf_func) (stream, "%%y");

                    break;



                  case 'u':

                  case 'U':

                    {

                      int val = *s == 'U' ? X_RS1 (insn) : X_RD (insn);

                      const char *name = sparc_decode_sparclet_cpreg (val);



                      if (name)

                        (*info->fprintf_func) (stream, "%s", name);

                      else

                        (*info->fprintf_func) (stream, "%%cpreg(%d)", val);

                      break;

                    }

                  }

              }

          }



          /* If we are adding or or'ing something to rs1, then

             check to see whether the previous instruction was

             a sethi to the same register as in the sethi.

             If so, attempt to print the result of the add or

             or (in this context add and or do the same thing)

             and its symbolic value.  */

          if (imm_ored_to_rs1 || imm_added_to_rs1)

            {

              unsigned long prev_insn;

              int errcode;



              if (memaddr >= 4)

                errcode =

                  (*info->read_memory_func)

                  (memaddr - 4, buffer, sizeof (buffer), info);

              else

                errcode = 1;



              prev_insn = getword (buffer);



              if (errcode == 0)

                {

                  /* If it is a delayed branch, we need to look at the

                     instruction before the delayed branch.  This handles

                     sequences such as:



                     sethi %o1, %hi(_foo), %o1

                     call _printf

                     or %o1, %lo(_foo), %o1  */



                  if (is_delayed_branch (prev_insn))

                    {

                      if (memaddr >= 8)

                        errcode = (*info->read_memory_func)

                          (memaddr - 8, buffer, sizeof (buffer), info);

                      else

                        errcode = 1;



                      prev_insn = getword (buffer);

                    }

                }



              /* If there was a problem reading memory, then assume

                 the previous instruction was not sethi.  */

              if (errcode == 0)

                {

                  /* Is it sethi to the same register?  */

                  if ((prev_insn & 0xc1c00000) == 0x01000000

                      && X_RD (prev_insn) == X_RS1 (insn))

                    {

                      (*info->fprintf_func) (stream, "\t! ");

                      info->target =

                        ((unsigned) 0xFFFFFFFF

                         & ((int) X_IMM22 (prev_insn) << 10));

                      if (imm_added_to_rs1)

                        info->target += X_SIMM (insn, 13);

                      else

                        info->target |= X_SIMM (insn, 13);

                      (*info->print_address_func) (info->target, info);

                      info->insn_type = dis_dref;

                      info->data_size = 4;  /* FIXME!!! */

                    }

                }

            }



          if (opcode->flags & (F_UNBR|F_CONDBR|F_JSR))

            {

                /* FIXME -- check is_annulled flag.  */

              if (opcode->flags & F_UNBR)

                info->insn_type = dis_branch;

              if (opcode->flags & F_CONDBR)

                info->insn_type = dis_condbranch;

              if (opcode->flags & F_JSR)

                info->insn_type = dis_jsr;

              if (opcode->flags & F_DELAYED)

                info->branch_delay_insns = 1;

            }



          return sizeof (buffer);

        }

    }



  info->insn_type = dis_noninsn;        /* Mark as non-valid instruction.  */

  (*info->fprintf_func) (stream, _("unknown"));

  return sizeof (buffer);

}

print_insn_sparc (bfd_vma memaddr, disassemble_info *info)

{

  FILE *stream = info->stream;

  bfd_byte buffer[4];

  unsigned long insn;

  sparc_opcode_hash *op;

  

  static int opcodes_initialized = 0;

  

  static unsigned long current_mach = 0;

  bfd_vma (*getword) (const unsigned char *);



  if (!opcodes_initialized

      || info->mach != current_mach)

    {

      int i;



      current_arch_mask = compute_arch_mask (info->mach);



      if (!opcodes_initialized)

        sorted_opcodes =

          malloc (sparc_num_opcodes * sizeof (sparc_opcode *));

      

      for (i = 0; i < sparc_num_opcodes; ++i)

        sorted_opcodes[i] = &sparc_opcodes[i];

      qsort ((char *) sorted_opcodes, sparc_num_opcodes,

             sizeof (sorted_opcodes[0]), compare_opcodes);



      build_hash_table (sorted_opcodes, opcode_hash_table, sparc_num_opcodes);

      current_mach = info->mach;

      opcodes_initialized = 1;

    }



  {

    int status =

      (*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info);



    if (status != 0)

      {

        (*info->memory_error_func) (status, memaddr, info);

        return -1;

      }

  }



  



  if (info->endian == BFD_ENDIAN_BIG || info->mach == bfd_mach_sparc_sparclite)

    getword = bfd_getb32;

  else

    getword = bfd_getl32;



  insn = getword (buffer);



  info->insn_info_valid = 1;                    

  info->insn_type = dis_nonbranch;              

  info->branch_delay_insns = 0;                 

  info->target = 0;                             



  for (op = opcode_hash_table[HASH_INSN (insn)]; op; op = op->next)

    {

      const sparc_opcode *opcode = op->opcode;



      

      if (! (opcode->architecture & current_arch_mask))

        continue;



      if ((opcode->match & insn) == opcode->match

          && (opcode->lose & insn) == 0)

        {

          



          int imm_added_to_rs1 = 0;

          int imm_ored_to_rs1 = 0;



          



          int found_plus = 0;



          

           



          



          if (opcode->match == 0x80102000) 

            imm_ored_to_rs1 = 1;

          if (opcode->match == 0x80002000) 

            imm_added_to_rs1 = 1;



          if (X_RS1 (insn) != X_RD (insn)

              && strchr (opcode->args, 'r') != NULL)

              

              continue;

          if (X_RS2 (insn) != X_RD (insn)

              && strchr (opcode->args, 'O') != NULL)

              

              continue;



          (*info->fprintf_func) (stream, "%s", opcode->name);



          {

            const char *s;



            if (opcode->args[0] != ',')

              (*info->fprintf_func) (stream, " ");



            for (s = opcode->args; *s != '\0'; ++s)

              {

                while (*s == ',')

                  {

                    (*info->fprintf_func) (stream, ",");

                    ++s;

                    switch (*s)

                      {

                      case 'a':

                        (*info->fprintf_func) (stream, "a");

                         

                        ++s;

                        continue;

                      case 'N':

                        (*info->fprintf_func) (stream, "pn");

                        ++s;

                        continue;



                      case 'T':

                        (*info->fprintf_func) (stream, "pt");

                        ++s;

                        continue;



                      default:

                        break;

                      }

                  }



                (*info->fprintf_func) (stream, " ");



                switch (*s)

                  {

                  case '+':

                    found_plus = 1;

                    



                  default:

                    (*info->fprintf_func) (stream, "%c", *s);

                    break;



                  case '#':

                    (*info->fprintf_func) (stream, "0");

                    break;



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

                  case '1':

                  case 'r':

                    reg (X_RS1 (insn));

                    break;



                  case '2':

                  case 'O':

                    reg (X_RS2 (insn));

                    break;



                  case 'd':

                    reg (X_RD (insn));

                    break;

#undef  reg



#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)])

                  case 'e':

                    freg (X_RS1 (insn));

                    break;

                  case 'v':     

                  case 'V':     

                    fregx (X_RS1 (insn));

                    break;



                  case 'f':

                    freg (X_RS2 (insn));

                    break;

                  case 'B':     

                  case 'R':     

                    fregx (X_RS2 (insn));

                    break;



                  case 'g':

                    freg (X_RD (insn));

                    break;

                  case 'H':     

                  case 'J':     

                    fregx (X_RD (insn));

                    break;

#undef  freg

#undef  fregx



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

                  case 'b':

                    creg (X_RS1 (insn));

                    break;



                  case 'c':

                    creg (X_RS2 (insn));

                    break;



                  case 'D':

                    creg (X_RD (insn));

                    break;

#undef  creg



                  case 'h':

                    (*info->fprintf_func) (stream, "%%hi(%#x)",

                                           ((unsigned) 0xFFFFFFFF

                                            & ((int) X_IMM22 (insn) << 10)));

                    break;



                  case 'i':     

                  case 'I':     

                  case 'j':     

                    {

                      int imm;



                      if (*s == 'i')

                        imm = X_SIMM (insn, 13);

                      else if (*s == 'I')

                        imm = X_SIMM (insn, 11);

                      else

                        imm = X_SIMM (insn, 10);



                      













                      if (found_plus)

                        imm_added_to_rs1 = 1;



                      if (imm <= 9)

                        (*info->fprintf_func) (stream, "%d", imm);

                      else

                        (*info->fprintf_func) (stream, "%#x", imm);

                    }

                    break;



                  case 'X':     

                  case 'Y':     

                    {

                      int imm = X_IMM (insn, *s == 'X' ? 5 : 6);



                      if (imm <= 9)

                        (info->fprintf_func) (stream, "%d", imm);

                      else

                        (info->fprintf_func) (stream, "%#x", (unsigned) imm);

                    }

                    break;



                  case '3':

                    (info->fprintf_func) (stream, "%ld", X_IMM (insn, 3));

                    break;



                  case 'K':

                    {

                      int mask = X_MEMBAR (insn);

                      int bit = 0x40, printed_one = 0;

                      const char *name;



                      if (mask == 0)

                        (info->fprintf_func) (stream, "0");

                      else

                        while (bit)

                          {

                            if (mask & bit)

                              {

                                if (printed_one)

                                  (info->fprintf_func) (stream, "|");

                                name = sparc_decode_membar (bit);

                                (info->fprintf_func) (stream, "%s", name);

                                printed_one = 1;

                              }

                            bit >>= 1;

                          }

                      break;

                    }



                  case 'k':

                    info->target = memaddr + SEX (X_DISP16 (insn), 16) * 4;

                    (*info->print_address_func) (info->target, info);

                    break;



                  case 'G':

                    info->target = memaddr + SEX (X_DISP19 (insn), 19) * 4;

                    (*info->print_address_func) (info->target, info);

                    break;



                  case '6':

                  case '7':

                  case '8':

                  case '9':

                    (*info->fprintf_func) (stream, "%%fcc%c", *s - '6' + '0');

                    break;



                  case 'z':

                    (*info->fprintf_func) (stream, "%%icc");

                    break;



                  case 'Z':

                    (*info->fprintf_func) (stream, "%%xcc");

                    break;



                  case 'E':

                    (*info->fprintf_func) (stream, "%%ccr");

                    break;



                  case 's':

                    (*info->fprintf_func) (stream, "%%fprs");

                    break;



                  case 'o':

                    (*info->fprintf_func) (stream, "%%asi");

                    break;



                  case 'W':

                    (*info->fprintf_func) (stream, "%%tick");

                    break;



                  case 'P':

                    (*info->fprintf_func) (stream, "%%pc");

                    break;



                  case '?':

                    if (X_RS1 (insn) == 31)

                      (*info->fprintf_func) (stream, "%%ver");

                    else if ((unsigned) X_RS1 (insn) < 17)

                      (*info->fprintf_func) (stream, "%%%s",

                                             v9_priv_reg_names[X_RS1 (insn)]);

                    else

                      (*info->fprintf_func) (stream, "%%reserved");

                    break;



                  case '!':

                    if ((unsigned) X_RD (insn) < 17)

                      (*info->fprintf_func) (stream, "%%%s",

                                             v9_priv_reg_names[X_RD (insn)]);

                    else

                      (*info->fprintf_func) (stream, "%%reserved");

                    break;



                  case '$':

                    if ((unsigned) X_RS1 (insn) < 32)

                      (*info->fprintf_func) (stream, "%%%s",

                                             v9_hpriv_reg_names[X_RS1 (insn)]);

                    else

                      (*info->fprintf_func) (stream, "%%reserved");

                    break;



                  case '%':

                    if ((unsigned) X_RD (insn) < 32)

                      (*info->fprintf_func) (stream, "%%%s",

                                             v9_hpriv_reg_names[X_RD (insn)]);

                    else

                      (*info->fprintf_func) (stream, "%%reserved");

                    break;



                  case '/':

                    if (X_RS1 (insn) < 16 || X_RS1 (insn) > 25)

                      (*info->fprintf_func) (stream, "%%reserved");

                    else

                      (*info->fprintf_func) (stream, "%%%s",

                                             v9a_asr_reg_names[X_RS1 (insn)-16]);

                    break;



                  case '_':

                    if (X_RD (insn) < 16 || X_RD (insn) > 25)

                      (*info->fprintf_func) (stream, "%%reserved");

                    else

                      (*info->fprintf_func) (stream, "%%%s",

                                             v9a_asr_reg_names[X_RD (insn)-16]);

                    break;



                  case '*':

                    {

                      const char *name = sparc_decode_prefetch (X_RD (insn));



                      if (name)

                        (*info->fprintf_func) (stream, "%s", name);

                      else

                        (*info->fprintf_func) (stream, "%ld", X_RD (insn));

                      break;

                    }



                  case 'M':

                    (*info->fprintf_func) (stream, "%%asr%ld", X_RS1 (insn));

                    break;



                  case 'm':

                    (*info->fprintf_func) (stream, "%%asr%ld", X_RD (insn));

                    break;



                  case 'L':

                    info->target = memaddr + SEX (X_DISP30 (insn), 30) * 4;

                    (*info->print_address_func) (info->target, info);

                    break;



                  case 'n':

                    (*info->fprintf_func)

                      (stream, "%#x", SEX (X_DISP22 (insn), 22));

                    break;



                  case 'l':

                    info->target = memaddr + SEX (X_DISP22 (insn), 22) * 4;

                    (*info->print_address_func) (info->target, info);

                    break;



                  case 'A':

                    {

                      const char *name;



                      if ((info->mach == bfd_mach_sparc_v8plusa) ||

                          ((info->mach >= bfd_mach_sparc_v9) &&

                           (info->mach <= bfd_mach_sparc_v9b)))

                        name = sparc_decode_asi_v9 (X_ASI (insn));

                      else

                        name = sparc_decode_asi_v8 (X_ASI (insn));



                      if (name)

                        (*info->fprintf_func) (stream, "%s", name);

                      else

                        (*info->fprintf_func) (stream, "(%ld)", X_ASI (insn));

                      break;

                    }



                  case 'C':

                    (*info->fprintf_func) (stream, "%%csr");

                    break;



                  case 'F':

                    (*info->fprintf_func) (stream, "%%fsr");

                    break;



                  case 'p':

                    (*info->fprintf_func) (stream, "%%psr");

                    break;



                  case 'q':

                    (*info->fprintf_func) (stream, "%%fq");

                    break;



                  case 'Q':

                    (*info->fprintf_func) (stream, "%%cq");

                    break;



                  case 't':

                    (*info->fprintf_func) (stream, "%%tbr");

                    break;



                  case 'w':

                    (*info->fprintf_func) (stream, "%%wim");

                    break;



                  case 'x':

                    (*info->fprintf_func) (stream, "%ld",

                                           ((X_LDST_I (insn) << 8)

                                            + X_ASI (insn)));

                    break;



                  case 'y':

                    (*info->fprintf_func) (stream, "%%y");

                    break;



                  case 'u':

                  case 'U':

                    {

                      int val = *s == 'U' ? X_RS1 (insn) : X_RD (insn);

                      const char *name = sparc_decode_sparclet_cpreg (val);



                      if (name)

                        (*info->fprintf_func) (stream, "%s", name);

                      else

                        (*info->fprintf_func) (stream, "%%cpreg(%d)", val);

                      break;

                    }

                  }

              }

          }



          











          if (imm_ored_to_rs1 || imm_added_to_rs1)

            {

              unsigned long prev_insn;

              int errcode;



              if (memaddr >= 4)

                errcode =

                  (*info->read_memory_func)

                  (memaddr - 4, buffer, sizeof (buffer), info);

              else

                errcode = 1;



              prev_insn = getword (buffer);



              if (errcode == 0)

                {

                  















                  if (is_delayed_branch (prev_insn))

                    {

                      if (memaddr >= 8)

                        errcode = (*info->read_memory_func)

                          (memaddr - 8, buffer, sizeof (buffer), info);

                      else

                        errcode = 1;



                      prev_insn = getword (buffer);

                    }

                }



              



              if (errcode == 0)

                {

                  

                  if ((prev_insn & 0xc1c00000) == 0x01000000

                      && X_RD (prev_insn) == X_RS1 (insn))

                    {

                      (*info->fprintf_func) (stream, "\t! ");

                      info->target =

                        ((unsigned) 0xFFFFFFFF

                         & ((int) X_IMM22 (prev_insn) << 10));

                      if (imm_added_to_rs1)

                        info->target += X_SIMM (insn, 13);

                      else

                        info->target |= X_SIMM (insn, 13);

                      (*info->print_address_func) (info->target, info);

                      info->insn_type = dis_dref;

                      info->data_size = 4;  

                    }

                }

            }



          if (opcode->flags & (F_UNBR|F_CONDBR|F_JSR))

            {

                

              if (opcode->flags & F_UNBR)

                info->insn_type = dis_branch;

              if (opcode->flags & F_CONDBR)

                info->insn_type = dis_condbranch;

              if (opcode->flags & F_JSR)

                info->insn_type = dis_jsr;

              if (opcode->flags & F_DELAYED)

                info->branch_delay_insns = 1;

            }



          return sizeof (buffer);

        }

    }



  info->insn_type = dis_noninsn;        

  (*info->fprintf_func) (stream, _("unknown"));

  return sizeof (buffer);

}

  (*info->fprintf_func) (stream, _("unknown"));
FUNC_0 (bfd_vma VAR_0, disassemble_info *VAR_1)

{

  FILE *stream = VAR_1->stream;

  bfd_byte buffer[4];

  unsigned long VAR_2;

  sparc_opcode_hash *op;

  

  static int VAR_3 = 0;

  

  static unsigned long VAR_4 = 0;

  bfd_vma (*getword) (const unsigned char *);



  if (!VAR_3

      || VAR_1->mach != VAR_4)

    {

      int VAR_5;



      current_arch_mask = compute_arch_mask (VAR_1->mach);



      if (!VAR_3)

        sorted_opcodes =

          malloc (sparc_num_opcodes * sizeof (sparc_opcode *));

      

      for (VAR_5 = 0; VAR_5 < sparc_num_opcodes; ++VAR_5)

        sorted_opcodes[VAR_5] = &sparc_opcodes[VAR_5];

      qsort ((char *) sorted_opcodes, sparc_num_opcodes,

             sizeof (sorted_opcodes[0]), compare_opcodes);



      build_hash_table (sorted_opcodes, opcode_hash_table, sparc_num_opcodes);

      VAR_4 = VAR_1->mach;

      VAR_3 = 1;

    }



  {

    int VAR_6 =

      (*VAR_1->read_memory_func) (VAR_0, buffer, sizeof (buffer), VAR_1);



    if (VAR_6 != 0)

      {

        (*VAR_1->memory_error_func) (VAR_6, VAR_0, VAR_1);

        return -1;

      }

  }



  



  if (VAR_1->endian == BFD_ENDIAN_BIG || VAR_1->mach == bfd_mach_sparc_sparclite)

    getword = bfd_getb32;

  else

    getword = bfd_getl32;



  VAR_2 = getword (buffer);



  VAR_1->insn_info_valid = 1;                    

  VAR_1->insn_type = dis_nonbranch;              

  VAR_1->branch_delay_insns = 0;                 

  VAR_1->target = 0;                             



  for (op = opcode_hash_table[HASH_INSN (VAR_2)]; op; op = op->next)

    {

      const sparc_opcode *opcode = op->opcode;



      

      if (! (opcode->architecture & current_arch_mask))

        continue;



      if ((opcode->match & VAR_2) == opcode->match

          && (opcode->lose & VAR_2) == 0)

        {

          



          int imm_added_to_rs1 = 0;

          int imm_ored_to_rs1 = 0;



          



          int found_plus = 0;



          

           



          



          if (opcode->match == 0x80102000) 

            imm_ored_to_rs1 = 1;

          if (opcode->match == 0x80002000) 

            imm_added_to_rs1 = 1;



          if (X_RS1 (VAR_2) != X_RD (VAR_2)

              && strchr (opcode->args, 'r') != NULL)

              

              continue;

          if (X_RS2 (VAR_2) != X_RD (VAR_2)

              && strchr (opcode->args, 'O') != NULL)

              

              continue;



          (*VAR_1->fprintf_func) (stream, "%s", opcode->name);



          {

            const char *s;



            if (opcode->args[0] != ',')

              (*VAR_1->fprintf_func) (stream, " ");



            for (s = opcode->args; *s != '\0'; ++s)

              {

                while (*s == ',')

                  {

                    (*VAR_1->fprintf_func) (stream, ",");

                    ++s;

                    switch (*s)

                      {

                      case 'a':

                        (*VAR_1->fprintf_func) (stream, "a");

                         

                        ++s;

                        continue;

                      case 'N':

                        (*VAR_1->fprintf_func) (stream, "pn");

                        ++s;

                        continue;



                      case 'T':

                        (*VAR_1->fprintf_func) (stream, "pt");

                        ++s;

                        continue;



                      default:

                        break;

                      }

                  }



                (*VAR_1->fprintf_func) (stream, " ");



                switch (*s)

                  {

                  case '+':

                    found_plus = 1;

                    



                  default:

                    (*VAR_1->fprintf_func) (stream, "%c", *s);

                    break;



                  case '#':

                    (*VAR_1->fprintf_func) (stream, "0");

                    break;



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

                  case '1':

                  case 'r':

                    reg (X_RS1 (VAR_2));

                    break;



                  case '2':

                  case 'O':

                    reg (X_RS2 (VAR_2));

                    break;



                  case 'd':

                    reg (X_RD (VAR_2));

                    break;

#undef  reg



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

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

                  case 'e':

                    freg (X_RS1 (VAR_2));

                    break;

                  case 'v':     

                  case 'V':     

                    fregx (X_RS1 (VAR_2));

                    break;



                  case 'f':

                    freg (X_RS2 (VAR_2));

                    break;

                  case 'B':     

                  case 'R':     

                    fregx (X_RS2 (VAR_2));

                    break;



                  case 'g':

                    freg (X_RD (VAR_2));

                    break;

                  case 'H':     

                  case 'J':     

                    fregx (X_RD (VAR_2));

                    break;

#undef  freg

#undef  fregx



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

                  case 'b':

                    creg (X_RS1 (VAR_2));

                    break;



                  case 'c':

                    creg (X_RS2 (VAR_2));

                    break;



                  case 'D':

                    creg (X_RD (VAR_2));

                    break;

#undef  creg



                  case 'h':

                    (*VAR_1->fprintf_func) (stream, "%%hi(%#x)",

                                           ((unsigned) 0xFFFFFFFF

                                            & ((int) X_IMM22 (VAR_2) << 10)));

                    break;



                  case 'VAR_5':     

                  case 'I':     

                  case 'j':     

                    {

                      int imm;



                      if (*s == 'VAR_5')

                        imm = X_SIMM (VAR_2, 13);

                      else if (*s == 'I')

                        imm = X_SIMM (VAR_2, 11);

                      else

                        imm = X_SIMM (VAR_2, 10);



                      













                      if (found_plus)

                        imm_added_to_rs1 = 1;



                      if (imm <= 9)

                        (*VAR_1->fprintf_func) (stream, "%d", imm);

                      else

                        (*VAR_1->fprintf_func) (stream, "%#x", imm);

                    }

                    break;



                  case 'X':     

                  case 'Y':     

                    {

                      int imm = X_IMM (VAR_2, *s == 'X' ? 5 : 6);



                      if (imm <= 9)

                        (VAR_1->fprintf_func) (stream, "%d", imm);

                      else

                        (VAR_1->fprintf_func) (stream, "%#x", (unsigned) imm);

                    }

                    break;



                  case '3':

                    (VAR_1->fprintf_func) (stream, "%ld", X_IMM (VAR_2, 3));

                    break;



                  case 'K':

                    {

                      int mask = X_MEMBAR (VAR_2);

                      int bit = 0x40, printed_one = 0;

                      const char *name;



                      if (mask == 0)

                        (VAR_1->fprintf_func) (stream, "0");

                      else

                        while (bit)

                          {

                            if (mask & bit)

                              {

                                if (printed_one)

                                  (VAR_1->fprintf_func) (stream, "|");

                                name = sparc_decode_membar (bit);

                                (VAR_1->fprintf_func) (stream, "%s", name);

                                printed_one = 1;

                              }

                            bit >>= 1;

                          }

                      break;

                    }



                  case 'k':

                    VAR_1->target = VAR_0 + SEX (X_DISP16 (VAR_2), 16) * 4;

                    (*VAR_1->print_address_func) (VAR_1->target, VAR_1);

                    break;



                  case 'G':

                    VAR_1->target = VAR_0 + SEX (X_DISP19 (VAR_2), 19) * 4;

                    (*VAR_1->print_address_func) (VAR_1->target, VAR_1);

                    break;



                  case '6':

                  case '7':

                  case '8':

                  case '9':

                    (*VAR_1->fprintf_func) (stream, "%%fcc%c", *s - '6' + '0');

                    break;



                  case 'z':

                    (*VAR_1->fprintf_func) (stream, "%%icc");

                    break;



                  case 'Z':

                    (*VAR_1->fprintf_func) (stream, "%%xcc");

                    break;



                  case 'E':

                    (*VAR_1->fprintf_func) (stream, "%%ccr");

                    break;



                  case 's':

                    (*VAR_1->fprintf_func) (stream, "%%fprs");

                    break;



                  case 'o':

                    (*VAR_1->fprintf_func) (stream, "%%asi");

                    break;



                  case 'W':

                    (*VAR_1->fprintf_func) (stream, "%%tick");

                    break;



                  case 'P':

                    (*VAR_1->fprintf_func) (stream, "%%pc");

                    break;



                  case '?':

                    if (X_RS1 (VAR_2) == 31)

                      (*VAR_1->fprintf_func) (stream, "%%ver");

                    else if ((unsigned) X_RS1 (VAR_2) < 17)

                      (*VAR_1->fprintf_func) (stream, "%%%s",

                                             v9_priv_reg_names[X_RS1 (VAR_2)]);

                    else

                      (*VAR_1->fprintf_func) (stream, "%%reserved");

                    break;



                  case '!':

                    if ((unsigned) X_RD (VAR_2) < 17)

                      (*VAR_1->fprintf_func) (stream, "%%%s",

                                             v9_priv_reg_names[X_RD (VAR_2)]);

                    else

                      (*VAR_1->fprintf_func) (stream, "%%reserved");

                    break;



                  case '$':

                    if ((unsigned) X_RS1 (VAR_2) < 32)

                      (*VAR_1->fprintf_func) (stream, "%%%s",

                                             v9_hpriv_reg_names[X_RS1 (VAR_2)]);

                    else

                      (*VAR_1->fprintf_func) (stream, "%%reserved");

                    break;



                  case '%':

                    if ((unsigned) X_RD (VAR_2) < 32)

                      (*VAR_1->fprintf_func) (stream, "%%%s",

                                             v9_hpriv_reg_names[X_RD (VAR_2)]);

                    else

                      (*VAR_1->fprintf_func) (stream, "%%reserved");

                    break;



                  case '/':

                    if (X_RS1 (VAR_2) < 16 || X_RS1 (VAR_2) > 25)

                      (*VAR_1->fprintf_func) (stream, "%%reserved");

                    else

                      (*VAR_1->fprintf_func) (stream, "%%%s",

                                             v9a_asr_reg_names[X_RS1 (VAR_2)-16]);

                    break;



                  case '_':

                    if (X_RD (VAR_2) < 16 || X_RD (VAR_2) > 25)

                      (*VAR_1->fprintf_func) (stream, "%%reserved");

                    else

                      (*VAR_1->fprintf_func) (stream, "%%%s",

                                             v9a_asr_reg_names[X_RD (VAR_2)-16]);

                    break;



                  case '*':

                    {

                      const char *name = sparc_decode_prefetch (X_RD (VAR_2));



                      if (name)

                        (*VAR_1->fprintf_func) (stream, "%s", name);

                      else

                        (*VAR_1->fprintf_func) (stream, "%ld", X_RD (VAR_2));

                      break;

                    }



                  case 'M':

                    (*VAR_1->fprintf_func) (stream, "%%asr%ld", X_RS1 (VAR_2));

                    break;



                  case 'm':

                    (*VAR_1->fprintf_func) (stream, "%%asr%ld", X_RD (VAR_2));

                    break;



                  case 'L':

                    VAR_1->target = VAR_0 + SEX (X_DISP30 (VAR_2), 30) * 4;

                    (*VAR_1->print_address_func) (VAR_1->target, VAR_1);

                    break;



                  case 'n':

                    (*VAR_1->fprintf_func)

                      (stream, "%#x", SEX (X_DISP22 (VAR_2), 22));

                    break;



                  case 'l':

                    VAR_1->target = VAR_0 + SEX (X_DISP22 (VAR_2), 22) * 4;

                    (*VAR_1->print_address_func) (VAR_1->target, VAR_1);

                    break;



                  case 'A':

                    {

                      const char *name;



                      if ((VAR_1->mach == bfd_mach_sparc_v8plusa) ||

                          ((VAR_1->mach >= bfd_mach_sparc_v9) &&

                           (VAR_1->mach <= bfd_mach_sparc_v9b)))

                        name = sparc_decode_asi_v9 (X_ASI (VAR_2));

                      else

                        name = sparc_decode_asi_v8 (X_ASI (VAR_2));



                      if (name)

                        (*VAR_1->fprintf_func) (stream, "%s", name);

                      else

                        (*VAR_1->fprintf_func) (stream, "(%ld)", X_ASI (VAR_2));

                      break;

                    }



                  case 'C':

                    (*VAR_1->fprintf_func) (stream, "%%csr");

                    break;



                  case 'F':

                    (*VAR_1->fprintf_func) (stream, "%%fsr");

                    break;



                  case 'p':

                    (*VAR_1->fprintf_func) (stream, "%%psr");

                    break;



                  case 'q':

                    (*VAR_1->fprintf_func) (stream, "%%fq");

                    break;



                  case 'Q':

                    (*VAR_1->fprintf_func) (stream, "%%cq");

                    break;



                  case 't':

                    (*VAR_1->fprintf_func) (stream, "%%tbr");

                    break;



                  case 'w':

                    (*VAR_1->fprintf_func) (stream, "%%wim");

                    break;



                  case 'x':

                    (*VAR_1->fprintf_func) (stream, "%ld",

                                           ((X_LDST_I (VAR_2) << 8)

                                            + X_ASI (VAR_2)));

                    break;



                  case 'y':

                    (*VAR_1->fprintf_func) (stream, "%%y");

                    break;



                  case 'u':

                  case 'U':

                    {

                      int val = *s == 'U' ? X_RS1 (VAR_2) : X_RD (VAR_2);

                      const char *name = sparc_decode_sparclet_cpreg (val);



                      if (name)

                        (*VAR_1->fprintf_func) (stream, "%s", name);

                      else

                        (*VAR_1->fprintf_func) (stream, "%%cpreg(%d)", val);

                      break;

                    }

                  }

              }

          }



          











          if (imm_ored_to_rs1 || imm_added_to_rs1)

            {

              unsigned long prev_insn;

              int errcode;



              if (VAR_0 >= 4)

                errcode =

                  (*VAR_1->read_memory_func)

                  (VAR_0 - 4, buffer, sizeof (buffer), VAR_1);

              else

                errcode = 1;



              prev_insn = getword (buffer);



              if (errcode == 0)

                {

                  















                  if (is_delayed_branch (prev_insn))

                    {

                      if (VAR_0 >= 8)

                        errcode = (*VAR_1->read_memory_func)

                          (VAR_0 - 8, buffer, sizeof (buffer), VAR_1);

                      else

                        errcode = 1;



                      prev_insn = getword (buffer);

                    }

                }



              



              if (errcode == 0)

                {

                  

                  if ((prev_insn & 0xc1c00000) == 0x01000000

                      && X_RD (prev_insn) == X_RS1 (VAR_2))

                    {

                      (*VAR_1->fprintf_func) (stream, "\t! ");

                      VAR_1->target =

                        ((unsigned) 0xFFFFFFFF

                         & ((int) X_IMM22 (prev_insn) << 10));

                      if (imm_added_to_rs1)

                        VAR_1->target += X_SIMM (VAR_2, 13);

                      else

                        VAR_1->target |= X_SIMM (VAR_2, 13);

                      (*VAR_1->print_address_func) (VAR_1->target, VAR_1);

                      VAR_1->insn_type = dis_dref;

                      VAR_1->data_size = 4;  

                    }

                }

            }



          if (opcode->flags & (F_UNBR|F_CONDBR|F_JSR))

            {

                

              if (opcode->flags & F_UNBR)

                VAR_1->insn_type = dis_branch;

              if (opcode->flags & F_CONDBR)

                VAR_1->insn_type = dis_condbranch;

              if (opcode->flags & F_JSR)

                VAR_1->insn_type = dis_jsr;

              if (opcode->flags & F_DELAYED)

                VAR_1->branch_delay_insns = 1;

            }



          return sizeof (buffer);

        }

    }



  VAR_1->insn_type = dis_noninsn;        

  (*VAR_1->fprintf_func) (stream, _("unknown"));

  return sizeof (buffer);

}

FUNC_0 (bfd_vma VAR_0, disassemble_info *VAR_1)
{ FILE *stream = VAR_1->stream; bfd_byte buffer[4]; unsigned long VAR_2; sparc_opcode_hash *op; static int VAR_3 = 0; static unsigned long VAR_4 = 0; bfd_vma (*getword) (const unsigned char *); if (!VAR_3
|| VAR_1->mach != VAR_4)
{ int VAR_5; current_arch_mask = compute_arch_mask (VAR_1->mach); if (!VAR_3)
sorted_opcodes =
malloc (sparc_num_opcodes * sizeof (sparc_opcode *)); for (VAR_5 = 0; VAR_5 < sparc_num_opcodes; ++VAR_5) sorted_opcodes[VAR_5] = &sparc_opcodes[VAR_5]; qsort ((char *) sorted_opcodes, sparc_num_opcodes,
sizeof (sorted_opcodes[0]), compare_opcodes); build_hash_table (sorted_opcodes, opcode_hash_table, sparc_num_opcodes); VAR_4 = VAR_1->mach; VAR_3 = 1; } { int VAR_6 =
(*VAR_1->read_memory_func) (VAR_0, buffer, sizeof (buffer), VAR_1); if (VAR_6 != 0)
{ (*VAR_1->memory_error_func) (VAR_6, VAR_0, VAR_1); return -1; } } if (VAR_1->endian == BFD_ENDIAN_BIG || VAR_1->mach == bfd_mach_sparc_sparclite)
getword = bfd_getb32; else
getword = bfd_getl32; VAR_2 = getword (buffer); VAR_1->insn_info_valid = 1; VAR_1->insn_type = dis_nonbranch; VAR_1->branch_delay_insns = 0; VAR_1->target = 0; for (op = opcode_hash_table[HASH_INSN (VAR_2)]; op; op = op->next) { const sparc_opcode *opcode = op->opcode; if (! (opcode->architecture & current_arch_mask))
continue; if ((opcode->match & VAR_2) == opcode->match
&& (opcode->lose & VAR_2) == 0)
{ int imm_added_to_rs1 = 0; int imm_ored_to_rs1 = 0; int found_plus = 0; if (opcode->match == 0x80102000)
imm_ored_to_rs1 = 1; if (opcode->match == 0x80002000)
imm_added_to_rs1 = 1; if (X_RS1 (VAR_2) != X_RD (VAR_2)
&& strchr (opcode->args, 'r') != NULL)
continue; if (X_RS2 (VAR_2) != X_RD (VAR_2)
&& strchr (opcode->args, 'O') != NULL)
continue; (*VAR_1->fprintf_func) (stream, "%s", opcode->name); { const char *s; if (opcode->args[0] != ',')
(*VAR_1->fprintf_func) (stream, " "); for (s = opcode->args; *s != '\0'; ++s) { while (*s == ',')
{ (*VAR_1->fprintf_func) (stream, ","); ++s; switch (*s)
{ case 'a':
(*VAR_1->fprintf_func) (stream, "a"); ++s; continue; case 'N':
(*VAR_1->fprintf_func) (stream, "pn"); ++s; continue; case 'T':
(*VAR_1->fprintf_func) (stream, "pt"); ++s; continue; default:
break; } } (*VAR_1->fprintf_func) (stream, " "); switch (*s)
{ case '+':
found_plus = 1; default:
(*VAR_1->fprintf_func) (stream, "%c", *s); break; case '#':
(*VAR_1->fprintf_func) (stream, "0"); break; #define reg(n)  (*VAR_1->fprintf_func) (stream, "%%%s", reg_names[n])
case '1':
case 'r':
reg (X_RS1 (VAR_2)); break; case '2':
case 'O':
reg (X_RS2 (VAR_2)); break; case 'd':
reg (X_RD (VAR_2)); break; #undef  reg
#define freg(n)         (*VAR_1->fprintf_func) (stream, "%%%s", freg_names[n])
#define fregx(n)        (*VAR_1->fprintf_func) (stream, "%%%s", freg_names[((n) & ~1) | (((n) & 1) << 5)])
case 'e':
freg (X_RS1 (VAR_2)); break; case 'v':
case 'V':
fregx (X_RS1 (VAR_2)); break; case 'f':
freg (X_RS2 (VAR_2)); break; case 'B':
case 'R':
fregx (X_RS2 (VAR_2)); break; case 'g':
freg (X_RD (VAR_2)); break; case 'H':
case 'J':
fregx (X_RD (VAR_2)); break; #undef  freg
#undef  fregx
#define creg(n) (*VAR_1->fprintf_func) (stream, "%%c%u", (unsigned int) (n))
case 'b':
creg (X_RS1 (VAR_2)); break; case 'c':
creg (X_RS2 (VAR_2)); break; case 'D':
creg (X_RD (VAR_2)); break; #undef  creg
case 'h':
(*VAR_1->fprintf_func) (stream, "%%hi(%#x)",
((unsigned) 0xFFFFFFFF
& ((int) X_IMM22 (VAR_2) << 10))); break; case 'VAR_5':
case 'I':
case 'j':
{ int imm; if (*s == 'VAR_5')
imm = X_SIMM (VAR_2, 13); else if (*s == 'I')
imm = X_SIMM (VAR_2, 11); else
imm = X_SIMM (VAR_2, 10); if (found_plus)
imm_added_to_rs1 = 1; if (imm <= 9)
(*VAR_1->fprintf_func) (stream, "%d", imm); else
(*VAR_1->fprintf_func) (stream, "%#x", imm); } break; case 'X':
case 'Y':
{ int imm = X_IMM (VAR_2, *s == 'X' ? 5 : 6); if (imm <= 9)
(VAR_1->fprintf_func) (stream, "%d", imm); else
(VAR_1->fprintf_func) (stream, "%#x", (unsigned) imm); } break; case '3':
(VAR_1->fprintf_func) (stream, "%ld", X_IMM (VAR_2, 3)); break; case 'K':
{ int mask = X_MEMBAR (VAR_2); int bit = 0x40, printed_one = 0; const char *name; if (mask == 0)
(VAR_1->fprintf_func) (stream, "0"); else
while (bit)
{ if (mask & bit)
{ if (printed_one)
(VAR_1->fprintf_func) (stream, "|"); name = sparc_decode_membar (bit); (VAR_1->fprintf_func) (stream, "%s", name); printed_one = 1; } bit >>= 1; } break; } case 'k':
VAR_1->target = VAR_0 + SEX (X_DISP16 (VAR_2), 16) * 4; (*VAR_1->print_address_func) (VAR_1->target, VAR_1); break; case 'G':
VAR_1->target = VAR_0 + SEX (X_DISP19 (VAR_2), 19) * 4; (*VAR_1->print_address_func) (VAR_1->target, VAR_1); break; case '6':
case '7':
case '8':
case '9':
(*VAR_1->fprintf_func) (stream, "%%fcc%c", *s - '6' + '0'); break; case 'z':
(*VAR_1->fprintf_func) (stream, "%%icc"); break; case 'Z':
(*VAR_1->fprintf_func) (stream, "%%xcc"); break; case 'E':
(*VAR_1->fprintf_func) (stream, "%%ccr"); break; case 's':
(*VAR_1->fprintf_func) (stream, "%%fprs"); break; case 'o':
(*VAR_1->fprintf_func) (stream, "%%asi"); break; case 'W':
(*VAR_1->fprintf_func) (stream, "%%tick"); break; case 'P':
(*VAR_1->fprintf_func) (stream, "%%pc"); break; case '?':
if (X_RS1 (VAR_2) == 31)
(*VAR_1->fprintf_func) (stream, "%%ver"); else if ((unsigned) X_RS1 (VAR_2) < 17)
(*VAR_1->fprintf_func) (stream, "%%%s",
v9_priv_reg_names[X_RS1 (VAR_2)]); else
(*VAR_1->fprintf_func) (stream, "%%reserved"); break; case '!':
if ((unsigned) X_RD (VAR_2) < 17)
(*VAR_1->fprintf_func) (stream, "%%%s",
v9_priv_reg_names[X_RD (VAR_2)]); else
(*VAR_1->fprintf_func) (stream, "%%reserved"); break; case '$':
if ((unsigned) X_RS1 (VAR_2) < 32)
(*VAR_1->fprintf_func) (stream, "%%%s",
v9_hpriv_reg_names[X_RS1 (VAR_2)]); else
(*VAR_1->fprintf_func) (stream, "%%reserved"); break; case '%':
if ((unsigned) X_RD (VAR_2) < 32)
(*VAR_1->fprintf_func) (stream, "%%%s",
v9_hpriv_reg_names[X_RD (VAR_2)]); else
(*VAR_1->fprintf_func) (stream, "%%reserved"); break; case '/':
if (X_RS1 (VAR_2) < 16 || X_RS1 (VAR_2) > 25)
(*VAR_1->fprintf_func) (stream, "%%reserved"); else
(*VAR_1->fprintf_func) (stream, "%%%s",
v9a_asr_reg_names[X_RS1 (VAR_2)-16]); break; case '_':
if (X_RD (VAR_2) < 16 || X_RD (VAR_2) > 25)
(*VAR_1->fprintf_func) (stream, "%%reserved"); else
(*VAR_1->fprintf_func) (stream, "%%%s",
v9a_asr_reg_names[X_RD (VAR_2)-16]); break; case '*':
{ const char *name = sparc_decode_prefetch (X_RD (VAR_2)); if (name)
(*VAR_1->fprintf_func) (stream, "%s", name); else
(*VAR_1->fprintf_func) (stream, "%ld", X_RD (VAR_2)); break; } case 'M':
(*VAR_1->fprintf_func) (stream, "%%asr%ld", X_RS1 (VAR_2)); break; case 'm':
(*VAR_1->fprintf_func) (stream, "%%asr%ld", X_RD (VAR_2)); break; case 'L':
VAR_1->target = VAR_0 + SEX (X_DISP30 (VAR_2), 30) * 4; (*VAR_1->print_address_func) (VAR_1->target, VAR_1); break; case 'n':
(*VAR_1->fprintf_func)
(stream, "%#x", SEX (X_DISP22 (VAR_2), 22)); break; case 'l':
VAR_1->target = VAR_0 + SEX (X_DISP22 (VAR_2), 22) * 4; (*VAR_1->print_address_func) (VAR_1->target, VAR_1); break; case 'A':
{ const char *name; if ((VAR_1->mach == bfd_mach_sparc_v8plusa) ||
((VAR_1->mach >= bfd_mach_sparc_v9) &&
(VAR_1->mach <= bfd_mach_sparc_v9b)))
name = sparc_decode_asi_v9 (X_ASI (VAR_2)); else
name = sparc_decode_asi_v8 (X_ASI (VAR_2)); if (name)
(*VAR_1->fprintf_func) (stream, "%s", name); else
(*VAR_1->fprintf_func) (stream, "(%ld)", X_ASI (VAR_2)); break; } case 'C':
(*VAR_1->fprintf_func) (stream, "%%csr"); break; case 'F':
(*VAR_1->fprintf_func) (stream, "%%fsr"); break; case 'p':
(*VAR_1->fprintf_func) (stream, "%%psr"); break; case 'q':
(*VAR_1->fprintf_func) (stream, "%%fq"); break; case 'Q':
(*VAR_1->fprintf_func) (stream, "%%cq"); break; case 't':
(*VAR_1->fprintf_func) (stream, "%%tbr"); break; case 'w':
(*VAR_1->fprintf_func) (stream, "%%wim"); break; case 'x':
(*VAR_1->fprintf_func) (stream, "%ld",
((X_LDST_I (VAR_2) << 8)
+ X_ASI (VAR_2))); break; case 'y':
(*VAR_1->fprintf_func) (stream, "%%y"); break; case 'u':
case 'U':
{ int val = *s == 'U' ? X_RS1 (VAR_2) : X_RD (VAR_2); const char *name = sparc_decode_sparclet_cpreg (val); if (name)
(*VAR_1->fprintf_func) (stream, "%s", name); else
(*VAR_1->fprintf_func) (stream, "%%cpreg(%d)", val); break; } } } } if (imm_ored_to_rs1 || imm_added_to_rs1)
{ unsigned long prev_insn; int errcode; if (VAR_0 >= 4)
errcode =
(*VAR_1->read_memory_func)
(VAR_0 - 4, buffer, sizeof (buffer), VAR_1); else
errcode = 1; prev_insn = getword (buffer); if (errcode == 0)
{ if (is_delayed_branch (prev_insn))
{ if (VAR_0 >= 8)
errcode = (*VAR_1->read_memory_func)
(VAR_0 - 8, buffer, sizeof (buffer), VAR_1); else
errcode = 1; prev_insn = getword (buffer); } } if (errcode == 0)
{ if ((prev_insn & 0xc1c00000) == 0x01000000
&& X_RD (prev_insn) == X_RS1 (VAR_2))
{ (*VAR_1->fprintf_func) (stream, "\t! "); VAR_1->target =
((unsigned) 0xFFFFFFFF
& ((int) X_IMM22 (prev_insn) << 10)); if (imm_added_to_rs1)
VAR_1->target += X_SIMM (VAR_2, 13); else
VAR_1->target |= X_SIMM (VAR_2, 13); (*VAR_1->print_address_func) (VAR_1->target, VAR_1); VAR_1->insn_type = dis_dref; VAR_1->data_size = 4; } } } if (opcode->flags & (F_UNBR|F_CONDBR|F_JSR))
{ if (opcode->flags & F_UNBR)
VAR_1->insn_type = dis_branch; if (opcode->flags & F_CONDBR)
VAR_1->insn_type = dis_condbranch; if (opcode->flags & F_JSR)
VAR_1->insn_type = dis_jsr; if (opcode->flags & F_DELAYED)
VAR_1->branch_delay_insns = 1; } return sizeof (buffer); } } VAR_1->insn_type = dis_noninsn; (*VAR_1->fprintf_func) (stream, _("unknown")); return sizeof (buffer); }