home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gdb-4.16-base.tgz / gdb-4.16-base.tar / fsf / gdb / opcodes / z8k-dis.c < prev    next >
C/C++ Source or Header  |  1995-07-07  |  14KB  |  572 lines

  1. /*
  2. This file is part of GNU Binutils.
  3.  
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  17.  
  18. #include <ansidecl.h>
  19. #include "sysdep.h"
  20. #include "dis-asm.h"
  21.  
  22. #define DEFINE_TABLE
  23. #include "z8k-opc.h"
  24.  
  25.  
  26. #include <setjmp.h>
  27.  
  28.  
  29. typedef struct
  30. {
  31.   /* These are all indexed by nibble number (i.e only every other entry
  32.      of bytes is used, and every 4th entry of words).  */
  33.   unsigned char nibbles[24];
  34.   unsigned char bytes[24];
  35.   unsigned short words[24];
  36.  
  37.   /* Nibble number of first word not yet fetched.  */
  38.   int max_fetched;
  39.   bfd_vma insn_start;
  40.   jmp_buf bailout;
  41.  
  42.   long tabl_index;
  43.   char instr_asmsrc[80];
  44.   unsigned long arg_reg[0x0f];
  45.   unsigned long immediate;
  46.   unsigned long displacement;
  47.   unsigned long address;
  48.   unsigned long cond_code;
  49.   unsigned long ctrl_code;
  50.   unsigned long flags;
  51.   unsigned long interrupts;
  52. }
  53. instr_data_s;
  54.  
  55. /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
  56.    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
  57.    on error.  */
  58. #define FETCH_DATA(info, nibble) \
  59.   ((nibble) < ((instr_data_s *)(info->private_data))->max_fetched \
  60.    ? 1 : fetch_data ((info), (nibble)))
  61.  
  62. static int
  63. fetch_data (info, nibble)
  64.      struct disassemble_info *info;
  65.      int nibble;
  66. {
  67.   unsigned char mybuf[20];
  68.   int status;
  69.   instr_data_s *priv = (instr_data_s *)info->private_data;
  70.   bfd_vma start;
  71.  
  72.   if ((nibble % 4) != 0)
  73.     abort ();
  74.  
  75.   status = (*info->read_memory_func) (priv->insn_start,
  76.                       (bfd_byte *) mybuf,
  77.                       nibble / 2,
  78.                       info);
  79.   if (status != 0)
  80.     {
  81.       (*info->memory_error_func) (status, priv->insn_start, info);
  82.       longjmp (priv->bailout, 1);
  83.     }
  84.  
  85.   {
  86.     int i;
  87.     unsigned char *p = mybuf ;
  88.     
  89.     for (i = 0; i < nibble;)
  90.       {
  91.     priv->words[i] = (p[0] << 8) | p[1];
  92.     
  93.     priv->bytes[i] = *p;
  94.     priv->nibbles[i++] = *p >> 4;
  95.     priv->nibbles[i++] = *p &0xf;
  96.  
  97.     ++p;
  98.     priv->bytes[i] = *p;
  99.     priv->nibbles[i++] = *p >> 4;
  100.     priv->nibbles[i++] = *p & 0xf;
  101.  
  102.     ++p;
  103.       }
  104.   }
  105.   priv->max_fetched = nibble;
  106.   return 1;
  107. }
  108.  
  109. static char *codes[16] =
  110. {
  111.   "f",
  112.   "lt",
  113.   "le",
  114.   "ule",
  115.   "ov/pe",
  116.   "mi",
  117.   "eq",
  118.   "c/ult",
  119.   "t",
  120.   "ge",
  121.   "gt",
  122.   "ugt",
  123.   "nov/po",
  124.   "pl",
  125.   "ne",
  126.   "nc/uge"
  127. };
  128.  
  129. int z8k_lookup_instr PARAMS ((unsigned char*, disassemble_info *));
  130. static void output_instr
  131.   PARAMS ((instr_data_s *, unsigned long, disassemble_info *));
  132. static void unpack_instr PARAMS ((instr_data_s *, int, disassemble_info *));
  133. static void unparse_instr PARAMS ((instr_data_s *));
  134.  
  135. static int
  136. print_insn_z8k (addr, info, is_segmented)
  137.      bfd_vma addr;
  138.      disassemble_info *info;
  139.      int is_segmented;
  140. {
  141.   instr_data_s instr_data;
  142.  
  143.   info->private_data = (PTR) &instr_data;
  144.   instr_data.max_fetched = 0;
  145.   instr_data.insn_start = addr;
  146.   if (setjmp (instr_data.bailout) != 0)
  147.     /* Error return.  */
  148.     return -1;
  149.  
  150.   instr_data.tabl_index = z8k_lookup_instr (instr_data.nibbles, info);
  151.   if (instr_data.tabl_index > 0)
  152.     {
  153.       unpack_instr (&instr_data, is_segmented, info);
  154.       unparse_instr (&instr_data);
  155.       output_instr (&instr_data, addr, info);
  156.       return z8k_table[instr_data.tabl_index].length;
  157.     }
  158.   else
  159.     {
  160.       FETCH_DATA (info, 4);
  161.       (*info->fprintf_func) (info->stream, ".word %02x%02x",
  162.                  instr_data.bytes[0], instr_data.bytes[2]);
  163.       return 2;
  164.     }
  165. }
  166.  
  167. print_insn_z8001 (addr, info)
  168.      bfd_vma addr;
  169.      disassemble_info *info;
  170. {
  171.   return print_insn_z8k (addr, info, 1);
  172. }
  173.  
  174. print_insn_z8002 (addr, info)
  175.      bfd_vma addr;
  176.      disassemble_info *info;
  177. {
  178.   return print_insn_z8k (addr, info, 0);
  179. }
  180.  
  181. int
  182. z8k_lookup_instr (nibbles, info)
  183.      unsigned char *nibbles;
  184.      disassemble_info *info;
  185. {
  186.  
  187.   int nibl_index, tabl_index;
  188.   int nibl_matched;
  189.   unsigned short instr_nibl;
  190.   unsigned short tabl_datum, datum_class, datum_value;
  191.  
  192.   nibl_matched = 0;
  193.   tabl_index = 0;
  194.   while (!nibl_matched && z8k_table[tabl_index].name)
  195.     {
  196.       nibl_matched = 1;
  197.       for (nibl_index = 0; nibl_index < z8k_table[tabl_index].length * 2 && nibl_matched; nibl_index++)
  198.     {
  199.       if ((nibl_index % 4) == 0)
  200.         /* Fetch one word at a time.  */
  201.         FETCH_DATA (info, nibl_index + 4);
  202.       instr_nibl = nibbles[nibl_index];
  203.  
  204.       tabl_datum = z8k_table[tabl_index].byte_info[nibl_index];
  205.       datum_class = tabl_datum & CLASS_MASK;
  206.       datum_value = ~CLASS_MASK & tabl_datum;
  207.  
  208.       switch (datum_class)
  209.         {
  210.         case CLASS_BIT:
  211.           if (datum_value != instr_nibl)
  212.         nibl_matched = 0;
  213.           break;
  214.         case CLASS_00II:
  215.           if (!((~instr_nibl) & 0x4))
  216.         nibl_matched = 0;
  217.           break;
  218.         case CLASS_01II:
  219.           if (!(instr_nibl & 0x4))
  220.         nibl_matched = 0;
  221.           break;
  222.         case CLASS_0CCC:
  223.           if (!((~instr_nibl) & 0x8))
  224.         nibl_matched = 0;
  225.           break;
  226.         case CLASS_1CCC:
  227.           if (!(instr_nibl & 0x8))
  228.         nibl_matched = 0;
  229.           break;
  230.         case CLASS_0DISP7:
  231.           if (!((~instr_nibl) & 0x8))
  232.         nibl_matched = 0;
  233.           nibl_index += 1;
  234.           break;
  235.         case CLASS_1DISP7:
  236.           if (!(instr_nibl & 0x8))
  237.         nibl_matched = 0;
  238.           nibl_index += 1;
  239.           break;
  240.         case CLASS_REGN0:
  241.           if (instr_nibl == 0)
  242.         nibl_matched = 0;
  243.           break;
  244.         case CLASS_BIT_1OR2:
  245.           if ((instr_nibl | 0x2) != (datum_value | 0x2))
  246.         nibl_matched = 0;
  247.           break;
  248.         default:
  249.           break;
  250.         }
  251.     }
  252.       if (nibl_matched)
  253.     {
  254.       return tabl_index;
  255.     }
  256.  
  257.       tabl_index++;
  258.     }
  259.   return -1;
  260.  
  261. }
  262.  
  263. static void
  264. output_instr (instr_data, addr, info)
  265.      instr_data_s *instr_data;
  266.      unsigned long addr;
  267.      disassemble_info *info;
  268. {
  269.   int loop, loop_limit;
  270.   char tmp_str[20];
  271.   char out_str[100];
  272.  
  273.   strcpy (out_str, "\t");
  274.  
  275.   loop_limit = z8k_table[instr_data->tabl_index].length * 2;
  276.   FETCH_DATA (info, loop_limit);
  277.   for (loop = 0; loop < loop_limit; loop++)
  278.     {
  279.       sprintf (tmp_str, "%x", instr_data->nibbles[loop]);
  280.       strcat (out_str, tmp_str);
  281.     }
  282.  
  283.   while (loop++ < 8)
  284.     {
  285.       strcat (out_str, " ");
  286.     }
  287.  
  288.   strcat (out_str, instr_data->instr_asmsrc);
  289.  
  290.   (*info->fprintf_func) (info->stream, "%s", out_str);
  291. }
  292.  
  293. static void
  294. unpack_instr (instr_data, is_segmented, info)
  295.      instr_data_s *instr_data;
  296.      int is_segmented;
  297.      disassemble_info *info;
  298. {
  299.   int nibl_count, loop;
  300.   unsigned short instr_nibl, instr_byte, instr_word;
  301.   long instr_long;
  302.   unsigned short tabl_datum, datum_class, datum_value;
  303.  
  304.   nibl_count = 0;
  305.   loop = 0;
  306.   while (z8k_table[instr_data->tabl_index].byte_info[loop] != 0)
  307.     {
  308.       FETCH_DATA (info, nibl_count + 4 - (nibl_count % 4));
  309.       instr_nibl = instr_data->nibbles[nibl_count];
  310.       instr_byte = instr_data->bytes[nibl_count];
  311.       instr_word = instr_data->words[nibl_count];
  312.  
  313.       tabl_datum = z8k_table[instr_data->tabl_index].byte_info[loop];
  314.       datum_class = tabl_datum & CLASS_MASK;
  315.       datum_value = tabl_datum & ~CLASS_MASK;
  316.  
  317.       switch (datum_class)
  318.     {
  319.     case CLASS_X:
  320.       instr_data->address = instr_nibl;
  321.       break;
  322.     case CLASS_BA:
  323.       instr_data->displacement = instr_nibl;
  324.       break;
  325.     case CLASS_BX:
  326.       instr_data->arg_reg[datum_value] = instr_nibl;
  327.       break;
  328.     case CLASS_DISP:
  329.       switch (datum_value)
  330.         {
  331.         case ARG_DISP16:
  332.           instr_data->displacement = instr_word;
  333.           nibl_count += 3;
  334.           break;
  335.         case ARG_DISP12:
  336.           instr_data->displacement = instr_word & 0x0fff;
  337.           nibl_count += 2;
  338.           break;
  339.         default:
  340.           break;
  341.         }
  342.       break;
  343.     case CLASS_IMM:
  344.       switch (datum_value)
  345.         {
  346.         case ARG_IMM4:
  347.           instr_data->immediate = instr_nibl;
  348.           break;
  349.         case ARG_NIM8:
  350.           instr_data->immediate = (-instr_byte);
  351.           nibl_count += 1;
  352.           break;
  353.         case ARG_IMM8:
  354.           instr_data->immediate = instr_byte;
  355.           nibl_count += 1;
  356.           break;
  357.         case ARG_IMM16:
  358.           instr_data->immediate = instr_word;
  359.           nibl_count += 3;
  360.           break;
  361.         case ARG_IMM32:
  362.           FETCH_DATA (info, nibl_count + 8);
  363.           instr_long = (instr_data->words[nibl_count] << 16)
  364.         | (instr_data->words[nibl_count + 4]);
  365.           instr_data->immediate = instr_long;
  366.           nibl_count += 7;
  367.           break;
  368.         case ARG_IMMN:
  369.           instr_data->immediate = instr_nibl - 1;
  370.           break;
  371.         case ARG_IMM4M1:
  372.           instr_data->immediate = instr_nibl + 1;
  373.           break;
  374.         case ARG_IMM_1:
  375.           instr_data->immediate = 1;
  376.           break;
  377.         case ARG_IMM_2:
  378.           instr_data->immediate = 2;
  379.           break;
  380.         case ARG_IMM2:
  381.           instr_data->immediate = instr_nibl & 0x3;
  382.           break;
  383.         default:
  384.           break;
  385.         }
  386.       break;
  387.     case CLASS_CC:
  388.       instr_data->cond_code = instr_nibl;
  389.       break;
  390.     case CLASS_CTRL:
  391.       instr_data->ctrl_code = instr_nibl;
  392.       break;
  393.     case CLASS_DA:
  394.     case CLASS_ADDRESS:
  395.       if (is_segmented)
  396.         {
  397.           if (instr_nibl & 0x8)
  398.         {
  399.           FETCH_DATA (info, nibl_count + 8);
  400.           instr_long = (instr_data->words[nibl_count] << 16)
  401.             | (instr_data->words[nibl_count + 4]);
  402.           instr_data->address = ((instr_word & 0x7f00) << 8) +
  403.             (instr_long & 0xffff);
  404.           nibl_count += 7;
  405.         }
  406.           else
  407.         {
  408.           instr_data->address = ((instr_word & 0x7f00) << 8) +
  409.             (instr_word & 0x00ff);
  410.           nibl_count += 3;
  411.         }
  412.         }
  413.       else
  414.         {
  415.           instr_data->address = instr_word;
  416.           nibl_count += 3;
  417.         }
  418.       break;
  419.     case CLASS_0CCC:
  420.       instr_data->cond_code = instr_nibl & 0x7;
  421.       break;
  422.     case CLASS_1CCC:
  423.       instr_data->cond_code = instr_nibl & 0x7;
  424.       break;
  425.     case CLASS_0DISP7:
  426.       instr_data->displacement = instr_byte & 0x7f;
  427.       nibl_count += 1;
  428.       break;
  429.     case CLASS_1DISP7:
  430.       instr_data->displacement = instr_byte & 0x7f;
  431.       nibl_count += 1;
  432.       break;
  433.     case CLASS_01II:
  434.       instr_data->interrupts = instr_nibl & 0x3;
  435.       break;
  436.     case CLASS_00II:
  437.       instr_data->interrupts = instr_nibl & 0x3;
  438.       break;
  439.     case CLASS_BIT:
  440.       /* do nothing */
  441.       break;
  442.     case CLASS_IR:
  443.       instr_data->arg_reg[datum_value] = instr_nibl;
  444.       break;
  445.     case CLASS_FLAGS:
  446.       instr_data->flags = instr_nibl;
  447.       break;
  448.     case CLASS_REG:
  449.       instr_data->arg_reg[datum_value] = instr_nibl;
  450.       break;
  451.     case CLASS_REG_BYTE:
  452.       instr_data->arg_reg[datum_value] = instr_nibl;
  453.       break;
  454.     case CLASS_REG_WORD:
  455.       instr_data->arg_reg[datum_value] = instr_nibl;
  456.       break;
  457.     case CLASS_REG_QUAD:
  458.       instr_data->arg_reg[datum_value] = instr_nibl;
  459.       break;
  460.     case CLASS_REG_LONG:
  461.       instr_data->arg_reg[datum_value] = instr_nibl;
  462.       break;
  463.     case CLASS_REGN0:
  464.       instr_data->arg_reg[datum_value] = instr_nibl;
  465.       break;
  466.     default:
  467.       break;
  468.     }
  469.  
  470.       loop += 1;
  471.       nibl_count += 1;
  472.     }
  473. }
  474.  
  475. static void
  476. unparse_instr (instr_data)
  477.      instr_data_s *instr_data;
  478. {
  479.   unsigned short tabl_datum, datum_class, datum_value;
  480.   int loop, loop_limit;
  481.   char out_str[80], tmp_str[25];
  482.  
  483.   sprintf (out_str, "\t%s\t", z8k_table[instr_data->tabl_index].name);
  484.  
  485.   loop_limit = z8k_table[instr_data->tabl_index].noperands;
  486.   for (loop = 0; loop < loop_limit; loop++)
  487.     {
  488.       if (loop)
  489.     strcat (out_str, ",");
  490.  
  491.       tabl_datum = z8k_table[instr_data->tabl_index].arg_info[loop];
  492.       datum_class = tabl_datum & CLASS_MASK;
  493.       datum_value = tabl_datum & ~CLASS_MASK;
  494.  
  495.       switch (datum_class)
  496.     {
  497.     case CLASS_X:
  498.       sprintf (tmp_str, "0x%0x(R%d)", instr_data->address,
  499.            instr_data->arg_reg[datum_value]);
  500.       strcat (out_str, tmp_str);
  501.       break;
  502.     case CLASS_BA:
  503.       sprintf (tmp_str, "r%d(#%x)", instr_data->arg_reg[datum_value],
  504.            instr_data->immediate);
  505.       strcat (out_str, tmp_str);
  506.       break;
  507.     case CLASS_BX:
  508.       sprintf (tmp_str, "r%d(R%d)", instr_data->arg_reg[datum_value],
  509.            instr_data->arg_reg[ARG_RX]);
  510.       strcat (out_str, tmp_str);
  511.       break;
  512.     case CLASS_DISP:
  513.       sprintf (tmp_str, "#0x%0x", instr_data->displacement);
  514.       strcat (out_str, tmp_str);
  515.       break;
  516.     case CLASS_IMM:
  517.       sprintf (tmp_str, "#0x%0x", instr_data->immediate);
  518.       strcat (out_str, tmp_str);
  519.       break;
  520.     case CLASS_CC:
  521.       sprintf (tmp_str, "%s", codes[instr_data->cond_code]);
  522.       strcat (out_str, tmp_str);
  523.       break;
  524.     case CLASS_CTRL:
  525.       sprintf (tmp_str, "0x%0x", instr_data->ctrl_code);
  526.       strcat (out_str, tmp_str);
  527.       break;
  528.     case CLASS_DA:
  529.     case CLASS_ADDRESS:
  530.       sprintf (tmp_str, "#0x%0x", instr_data->address);
  531.       strcat (out_str, tmp_str);
  532.       break;
  533.     case CLASS_IR:
  534.       sprintf (tmp_str, "@R%d", instr_data->arg_reg[datum_value]);
  535.       strcat (out_str, tmp_str);
  536.       break;
  537.     case CLASS_FLAGS:
  538.       sprintf (tmp_str, "0x%0x", instr_data->flags);
  539.       strcat (out_str, tmp_str);
  540.       break;
  541.     case CLASS_REG_BYTE:
  542.       if (instr_data->arg_reg[datum_value] >= 0x8)
  543.         {
  544.           sprintf (tmp_str, "rl%d",
  545.                instr_data->arg_reg[datum_value] - 0x8);
  546.         }
  547.       else
  548.         {
  549.           sprintf (tmp_str, "rh%d", instr_data->arg_reg[datum_value]);
  550.         }
  551.       strcat (out_str, tmp_str);
  552.       break;
  553.     case CLASS_REG_WORD:
  554.       sprintf (tmp_str, "r%d", instr_data->arg_reg[datum_value]);
  555.       strcat (out_str, tmp_str);
  556.       break;
  557.     case CLASS_REG_QUAD:
  558.       sprintf (tmp_str, "rq%d", instr_data->arg_reg[datum_value]);
  559.       strcat (out_str, tmp_str);
  560.       break;
  561.     case CLASS_REG_LONG:
  562.       sprintf (tmp_str, "rr%d", instr_data->arg_reg[datum_value]);
  563.       strcat (out_str, tmp_str);
  564.       break;
  565.     default:
  566.       break;
  567.     }
  568.     }
  569.  
  570.   strcpy (instr_data->instr_asmsrc, out_str);
  571. }
  572.