home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / gdb-4.9 / gdb / hppa-pinsn.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-12  |  11.6 KB  |  435 lines

  1. /* Disassembler for the PA-RISC. Somewhat derived from sparc-pinsn.c.
  2.    Copyright 1989, 1990, 1992 Free Software Foundation, Inc.
  3.  
  4.    Contributed by the Center for Software Science at the
  5.    University of Utah (pa-gdb-bugs@cs.utah.edu).
  6.  
  7. This file is part of GDB.
  8.  
  9. This program is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2 of the License, or
  12. (at your option) any later version.
  13.  
  14. This program is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. GNU General Public License for more details.
  18.  
  19. You should have received a copy of the GNU General Public License
  20. along with this program; if not, write to the Free Software
  21. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  22.  
  23. #include "defs.h"
  24. #include "symtab.h"
  25. #include "opcode/hppa.h"
  26.  
  27. static char *control_reg[] =
  28. {  "rctr", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
  29.    "pidr1", "pidr2", "ccr", "sar", "pidr3", "pidr4",
  30.    "iva", "eiem", "itmr", "pcsq", "pcoq", "iir", "isr",
  31.    "ior", "ipsw", "eirr", "tr0", "tr1", "tr2", "tr3",
  32.    "tr4", "tr5", "tr6", "tr7"
  33.    };
  34.  
  35. static char *compare_cond_names[] =
  36. {  "", ",=", ",<", ",<=", ",<<", ",<<=", ",sv",
  37.    ",od", ",tr", ",<>", ",>=", ",>", ",>>=",
  38.    ",>>", ",nsv", ",ev"
  39.    };
  40.  
  41. static char *add_cond_names[] =
  42. {  "", ",=", ",<", ",<=", ",nuv", ",znv", ",sv",
  43.    ",od", ",tr", ",<>", ",>=", ",>", ",uv",
  44.    ",vnz", ",nsv", ",ev"
  45.    };
  46.  
  47. static char *logical_cond_names[] =
  48. {  "", ",=", ",<", ",<=", 0, 0, 0, ",od",
  49.    ",tr", ",<>", ",>=", ",>", 0, 0, 0, ",ev"
  50.    };
  51.  
  52. static char *unit_cond_names[] =
  53. {  "", 0, ",sbz", ",shz", ",sdc", 0, ",sbc", ",shc",
  54.    ",tr", 0, ",nbz", ",nhz", ",ndc", 0, ",nbc", ",nhc"
  55.    };
  56.  
  57. static char *shift_cond_names[] =
  58. {"", ",=", ",<", ",od", ",tr", ",<>", ",>=", ",ev"};
  59.  
  60. static char *index_compl_names[] = {"", ",m", ",s", ",sm"};
  61. static char *short_ldst_compl_names[] = {"", ",ma", "", ",mb"};
  62. static char *short_bytes_compl_names[] = {"", ",b,m", ",e", ",e,m"};
  63. static char *float_format_names[] = {",sgl", ",dbl", ",quad"};
  64. static char *float_comp_names[] =
  65. {",false?", ",false", ",?", ",!<=>", ",=", ",=t", ",?=", ",!<>",
  66.  ",!?>=", ",<", ",?<", ",!>=", ",!?>", ",<=", ",?<=", ",!>",
  67.  ",!?<=", ",>", ",?>", ",!<=", ",!?<", ",>=", ",?>=", ",!<",
  68.  ",!?=", ",<>", ",!=", ",!=t", ",!?", ",<=>", ",true?", ",true"
  69.  };
  70.  
  71. /* For a bunch of different instructions form an index into a 
  72.    completer name table. */
  73. #define GET_COMPL(insn) (GET_FIELD (insn, 26, 26) | \
  74.              GET_FIELD (insn, 18, 18) << 1)
  75.  
  76. #define GET_COND(insn) (GET_FIELD ((insn), 16, 18) + \
  77.             (GET_FIELD ((insn), 19, 19) ? 8 : 0))
  78.  
  79. static void fput_reg PARAMS ((unsigned reg, FILE *stream));
  80. static void fput_const PARAMS ((unsigned num, FILE *stream));
  81. static void fput_reg_r PARAMS ((unsigned reg, FILE *stream));
  82. static void fput_creg PARAMS ((unsigned reg, FILE *stream));
  83.  
  84. /* Print one instruction from MEMADDR on STREAM.  */
  85. int
  86. print_insn (memaddr, stream)
  87.      CORE_ADDR memaddr;
  88.      FILE *stream;
  89. {
  90.   long insn;
  91.   unsigned int i, op;
  92.  
  93.   insn = read_memory_integer (memaddr, sizeof (insn));
  94.  
  95.   for (i = 0; i < NUMOPCODES; ++i)
  96.     {
  97.       const struct pa_opcode *opcode = &pa_opcodes[i];
  98.       if ((insn & opcode->mask) == opcode->match)
  99.     {
  100.       register const char *s;
  101.       
  102.       fputs_filtered (opcode->name, stream);
  103.     
  104.       if (!index ("cCY<?!@-+&U>~nZFM", opcode->args[0]))
  105.         fputs_filtered (" ", stream);
  106.       for (s = opcode->args; *s != '\0'; ++s)
  107.         {
  108.           switch (*s)
  109.         {
  110.         case 'x':
  111.           fput_reg (GET_FIELD (insn, 11, 15), stream);
  112.           break;
  113.         case 'X':
  114.                   if (GET_FIELD (insn, 25, 25))
  115.               fput_reg_r (GET_FIELD (insn, 11, 15), stream);
  116.           else
  117.               fput_reg (GET_FIELD (insn, 11, 15), stream);
  118.           break;
  119.         case 'b':
  120.           fput_reg (GET_FIELD (insn, 6, 10), stream);
  121.           break;
  122.         case '^':
  123.           fput_creg (GET_FIELD (insn, 6, 10), stream);
  124.           break;
  125.         case 'E':
  126.                   if (GET_FIELD (insn, 25, 25))
  127.               fput_reg_r (GET_FIELD (insn, 6, 10), stream);
  128.           else
  129.               fput_reg (GET_FIELD (insn, 6, 10), stream);
  130.           break;
  131.         case 't':
  132.           fput_reg (GET_FIELD (insn, 27, 31), stream);
  133.           break;
  134.         case 'v':
  135.                   if (GET_FIELD (insn, 25, 25))
  136.               fput_reg_r (GET_FIELD (insn, 27, 31), stream);
  137.           else
  138.               fput_reg (GET_FIELD (insn, 27, 31), stream);
  139.           break;
  140.         case '4':
  141.           fput_creg (GET_FIELD (insn, 6, 10), stream);
  142.           break;
  143.         case '6':
  144.           fput_reg (GET_FIELD (insn, 11, 15), stream);
  145.           break;
  146.         case '7':
  147.           fput_reg (GET_FIELD (insn, 27, 31), stream);
  148.           break;
  149.         case '8':
  150.           fput_reg (GET_FIELD (insn, 16, 20), stream);
  151.           break;
  152.         case '9':
  153.           fput_reg (GET_FIELD (insn, 21, 25), stream);
  154.           break;
  155.         case '5':
  156.           fput_const (extract_5_load (insn), stream);
  157.           break;
  158.           /* case 's': */
  159.         case 'S':
  160.           fprintf_filtered (stream, "sr%d", extract_3 (insn));
  161.           break;
  162.         case 'c':
  163.           fprintf_filtered (stream, "%s ",
  164.                     index_compl_names[GET_COMPL (insn)]);
  165.           break;
  166.         case 'C':
  167.           fprintf_filtered (stream, "%s ",
  168.                     short_ldst_compl_names[GET_COMPL (insn)]);
  169.           break;
  170.         case 'Y':
  171.           fprintf_filtered (stream, "%s ",
  172.                     short_bytes_compl_names[GET_COMPL (insn)]);
  173.           break;
  174.         /* these four conditions are for the set of instructions
  175.            which distinguish true/false conditions by opcode rather
  176.            than by the 'f' bit (sigh): comb, comib, addb, addib */
  177.         case '<':
  178.           fputs_filtered (compare_cond_names[GET_FIELD (insn, 16, 18)],
  179.                   stream);
  180.           break;
  181.         case '?':
  182.           fputs_filtered (compare_cond_names[GET_FIELD (insn, 16, 18) + 8],
  183.                   stream);
  184.           break;
  185.         case '!':
  186.           fputs_filtered (add_cond_names[GET_FIELD (insn, 16, 18)],
  187.                   stream);
  188.           break;
  189.         case '@':
  190.           fputs_filtered (add_cond_names[GET_FIELD (insn, 16, 18) + 8],
  191.                   stream);
  192.           break;
  193.         case '-':
  194.           fprintf_filtered (stream, "%s ",
  195.                     compare_cond_names[GET_COND (insn)]);
  196.           break;
  197.         case '+':
  198.           fprintf_filtered (stream, "%s ",
  199.                     add_cond_names[GET_FIELD (insn, 16, 18)]);
  200.           break;
  201.  
  202.         case '&':
  203.           fprintf_filtered (stream, "%s ",
  204.                     logical_cond_names[GET_COND (insn)]);
  205.           break;
  206.         case 'U':
  207.           fprintf_filtered (stream, "%s ",
  208.                     unit_cond_names[GET_COND (insn)]);
  209.           break;
  210.         case '>':
  211.         case '~':
  212.           fprintf_filtered (stream, "%s ",
  213.                     shift_cond_names[GET_FIELD (insn, 16, 18)]);
  214.           break;
  215.         case 'V':
  216.           fput_const (extract_5_store (insn), stream);
  217.           break;
  218.         case 'r':
  219.           fput_const (extract_5r_store (insn), stream);
  220.           break;
  221.         case 'R':
  222.           fput_const (extract_5R_store (insn), stream);
  223.           break;
  224.         case 'i':
  225.           fput_const (extract_11 (insn), stream);
  226.           break;
  227.         case 'j':
  228.           fput_const (extract_14 (insn), stream);
  229.           break;
  230.         case 'k':
  231.           fput_const (extract_21 (insn), stream);
  232.           break;
  233.         case 'n':
  234.           if (insn & 0x2)
  235.             fprintf_filtered (stream, ",n ");
  236.           else
  237.             fprintf_filtered (stream, " ");
  238.           break;
  239.         case 'w':
  240.           print_address (memaddr + 8 + extract_12 (insn), stream);
  241.           break;
  242.         case 'W':
  243.           op = GET_FIELD (insn, 0, 5);
  244.  
  245.           if (op == 0x38 /* be */ || op == 0x39 /* ble */)
  246.             fput_const (extract_17 (insn), stream);
  247.           else
  248.             print_address (memaddr + 8 + extract_17 (insn), stream);
  249.  
  250.           break;
  251.         case 'B':
  252.           {
  253.             int space;
  254.             if (space = GET_FIELD (insn, 16, 17))
  255.               fprintf_filtered (stream, "sr%d,", space);
  256.             fput_reg (GET_FIELD (insn, 6, 10), stream);
  257.             break;
  258.           }
  259.         case 'p':
  260.           fprintf_filtered (stream, "%d",
  261.                     31 - GET_FIELD (insn, 22, 26));
  262.           break;
  263.         case 'P':
  264.           fprintf_filtered (stream, "%d",
  265.                     GET_FIELD (insn, 22, 26));
  266.           break;
  267.         case 'Q':
  268.           fprintf_filtered (stream, "%d",
  269.                     GET_FIELD (insn, 11, 15));
  270.           break;
  271.         case 'T':
  272.           fprintf_filtered (stream, "%d",
  273.                     32 - GET_FIELD (insn, 27, 31));
  274.           break;
  275.         case 'A':
  276.           fput_const (GET_FIELD (insn, 6, 18), stream);
  277.           break;
  278.         case 'Z':
  279.           if (GET_FIELD (insn, 26, 26))
  280.             fprintf_filtered (stream, ",m ");
  281.           else
  282.             fprintf_filtered (stream, " ");
  283.           break;
  284.         case 'D':
  285.           fput_const (GET_FIELD (insn, 6, 31), stream);
  286.           break;
  287.         case 'f':
  288.           fprintf_filtered (stream, ",%d", GET_FIELD (insn, 23, 25));
  289.           break;
  290.         case 'O':
  291.           fput_const ((GET_FIELD (insn, 6,20) << 5 |
  292.                    GET_FIELD (insn, 27, 31)), stream);
  293.           break;
  294.         case 'o':
  295.           fput_const (GET_FIELD (insn, 6, 20), stream);
  296.           break;
  297.         case '2':
  298.           fput_const ((GET_FIELD (insn, 6, 22) << 5 |
  299.                    GET_FIELD (insn, 27, 31)), stream);
  300.           break;
  301.         case '1':
  302.           fput_const ((GET_FIELD (insn, 11, 20) << 5 |
  303.                    GET_FIELD (insn, 27, 31)), stream);
  304.           break;
  305.         case '0':
  306.           fput_const ((GET_FIELD (insn, 16, 20) << 5 |
  307.                    GET_FIELD (insn, 27, 31)), stream);
  308.           break;
  309.         case 'u':
  310.           fprintf_filtered (stream, "%d", GET_FIELD (insn, 23, 25));
  311.           break;
  312.         case 'F':
  313.           /* if no destination completer, need a space here */
  314.           if (GET_FIELD (insn, 21, 22) == 1)
  315.             fputs_filtered (float_format_names[GET_FIELD (insn, 19, 20)],
  316.                     stream);
  317.           else
  318.             fprintf_filtered (stream, "%s ",
  319.                       float_format_names[GET_FIELD
  320.                              (insn, 19, 20)]);
  321.           break;
  322.         case 'G':
  323.           fprintf_filtered (stream, "%s ",
  324.                     float_format_names[GET_FIELD (insn,
  325.                                   17, 18)]);
  326.           break;
  327.         case 'H':
  328.             fputs_filtered (float_format_names[GET_FIELD 
  329.                                                       (insn, 26, 26)], stream);
  330.           break;
  331.         case 'M':
  332.           fputs_filtered (float_comp_names[GET_FIELD (insn, 27, 31)],
  333.                   stream);
  334.           break;
  335.         case '}':
  336.           fprintf_filtered (stream, "fp%d", GET_FIELD (insn, 6, 10));
  337.           break;
  338.         case '|':
  339.           fprintf_filtered (stream, "fp%d", GET_FIELD (insn, 11, 15));
  340.           break;
  341.         case '{':
  342.           if (GET_FIELD (insn, 23, 25) == 0)
  343.             fprintf_filtered (stream, "fp%d",
  344.                       GET_FIELD (insn, 27, 31));
  345.           else
  346.             fprintf_filtered (stream, "cp%d",
  347.                       GET_FIELD (insn, 27, 31));
  348.           break;
  349.         default:
  350.           fprintf_filtered (stream, "%c", *s);
  351.           break;
  352.         }
  353.         }
  354.  
  355. /* If this is an external branch, examine the previous instruction and see if
  356.    it was an ldil that loaded something into the same base reg.  If so, then
  357.    calculate the branch target from the constants in both instructions, and
  358.    print it out. */
  359.  
  360.       op = GET_FIELD (insn, 0, 5);
  361.       if (op == 0x38 /* be */ || op == 0x39 /* ble */)
  362.         {
  363.           CORE_ADDR target_address;
  364.           long prev_insn;
  365.           int basereg, basereg_prev;
  366.  
  367.           target_address = extract_17 (insn);
  368.           basereg = GET_FIELD (insn, 6, 10);
  369.           if (basereg != 0)
  370.         {
  371.           prev_insn = read_memory_integer (memaddr - 4,
  372.                            sizeof(prev_insn));
  373.           basereg_prev = GET_FIELD (prev_insn, 6, 10);
  374.  
  375.           if ((prev_insn & 0xfc000000) == 0x20000000 /* ldil */
  376.               && basereg == basereg_prev)
  377.             target_address += extract_21 (prev_insn);
  378.         }
  379.           fprintf_filtered (stream, "\t! ");
  380.           print_address (target_address, stream);
  381.         }
  382.  
  383.       return sizeof(insn);
  384.     }
  385.     }
  386.   fprintf_filtered (stream, "%#8x", insn);
  387.   return sizeof(insn);
  388. }
  389.   
  390. /* Utility function to print registers */
  391.  
  392. static void
  393. fput_reg (reg, stream)
  394.      unsigned reg;
  395.      FILE *stream;
  396. {
  397.   if (reg)
  398.     fputs_filtered (reg_names[reg], stream);
  399.   else
  400.     fputs_filtered ("r0", stream);
  401. }
  402.  
  403. void
  404. fput_reg_r (reg, stream)
  405.      unsigned reg;
  406.      FILE *stream;
  407. {
  408.   if (reg)
  409.     fputs_filtered (reg_names[reg], stream);
  410.   else
  411.     fputs_filtered ("r0", stream);
  412.   fputs_filtered ("R", stream);
  413. }
  414.  
  415. void
  416. fput_creg (reg, stream)
  417.      unsigned reg;
  418.      FILE *stream;
  419. {
  420.   fputs_filtered (control_reg[reg], stream);
  421. }
  422.  
  423. /* print constants with sign */
  424.  
  425. void
  426. fput_const (num, stream)
  427.      unsigned num;
  428.      FILE *stream;
  429. {
  430.   if ((int)num < 0)
  431.     fprintf_filtered (stream, "-%x", -(int)num);
  432.   else
  433.     fprintf_filtered (stream, "%x", num);
  434. }
  435.