281b1cfb440c477b8cb2c0d3fd78527b07909cf9
[external/binutils.git] / gdb / tahoe-tdep.c
1 /* Print instructions for Tahoe target machines, for GDB.
2    Copyright 1986, 1989, 1991, 1992 Free Software Foundation, Inc.
3    Contributed by the State University of New York at Buffalo, by the
4    Distributed Computer Systems Lab, Department of Computer Science, 1991.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22 #include "defs.h"
23 #include "symtab.h"
24 #include "opcode/tahoe.h"
25
26 /* Tahoe instructions are never longer than this.  */
27 #define MAXLEN 62
28
29 /* Number of elements in the opcode table.  */
30 #define NOPCODES (sizeof votstrs / sizeof votstrs[0])
31
32 static unsigned char *print_insn_arg ();
33
34 /* Print the Tahoe instruction at address MEMADDR in debugged memory,
35    on STREAM.  Returns length of the instruction, in bytes.  */
36
37 int
38 tahoe_print_insn (memaddr, stream)
39      CORE_ADDR memaddr;
40      GDB_FILE *stream;
41 {
42   unsigned char buffer[MAXLEN];
43   register int i;
44   register unsigned char *p;
45   register char *d;
46
47   read_memory (memaddr, buffer, MAXLEN);
48
49   for (i = 0; i < NOPCODES; i++)
50     if (votstrs[i].detail.code == buffer[0]
51         || votstrs[i].detail.code == *(unsigned short *)buffer)
52       break;
53
54   /* Handle undefined instructions.  */
55   if (i == NOPCODES)
56     {
57       fprintf_unfiltered (stream, "0%o", buffer[0]);
58       return 1;
59     }
60
61   fprintf_unfiltered (stream, "%s", votstrs[i].name);
62
63   /* Point at first byte of argument data,
64      and at descriptor for first argument.  */
65   p = buffer + 1 + (votstrs[i].detail.code >= 0x100);
66   d = votstrs[i].detail.args;
67
68   if (*d)
69     fputc_unfiltered ('\t', stream);
70
71   while (*d)
72     {
73       p = print_insn_arg (d, p, memaddr + (p - buffer), stream);
74       d += 2;
75       if (*d)
76         fprintf_unfiltered (stream, ",");
77     }
78   return p - buffer;
79 }
80 /*******************************************************************/
81 static unsigned char *
82 print_insn_arg (d, p, addr, stream)
83      char *d;
84      register char *p;
85      CORE_ADDR addr;
86      GDB_FILE *stream;
87 {
88   int temp1 = 0;
89   register int regnum = *p & 0xf;
90   float floatlitbuf;
91
92   if (*d == 'b')
93     {
94       if (d[1] == 'b')
95         fprintf_unfiltered (stream, "0x%x", addr + *p++ + 1);
96       else
97         {
98
99           temp1 = *p;
100           temp1 <<= 8;
101           temp1 |= *(p + 1);
102           fprintf_unfiltered (stream, "0x%x", addr + temp1 + 2);
103           p += 2;
104         }
105     }
106   else
107     switch ((*p++ >> 4) & 0xf)
108       {
109       case 0:
110       case 1:
111       case 2:
112       case 3:                   /* Literal (short immediate byte) mode */
113         if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
114           {
115             *(int *)&floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4);
116             fprintf_unfiltered (stream, "$%f", floatlitbuf);
117           }
118         else
119           fprintf_unfiltered (stream, "$%d", p[-1] & 0x3f);
120         break;
121
122       case 4:                   /* Indexed */
123         p = (char *) print_insn_arg (d, p, addr + 1, stream);
124         fprintf_unfiltered (stream, "[%s]", reg_names[regnum]);
125         break;
126
127       case 5:                   /* Register */
128         fprintf_unfiltered (stream, reg_names[regnum]);
129         break;
130
131       case 7:                   /* Autodecrement */
132         fputc_unfiltered ('-', stream);
133       case 6:                   /* Register deferred */
134         fprintf_unfiltered (stream, "(%s)", reg_names[regnum]);
135         break;
136
137       case 9:                   /* Absolute Address & Autoincrement deferred */
138         fputc_unfiltered ('*', stream);
139         if (regnum == PC_REGNUM)
140           {
141             temp1 = *p;
142             temp1 <<= 8;
143             temp1 |= *(p +1);
144
145             fputc_unfiltered ('$', stream);
146             print_address (temp1, stream);
147             p += 4;
148             break;
149           }
150       case 8:                   /*Immediate & Autoincrement SP */
151         if (regnum == 8)         /*88 is Immediate Byte Mode*/
152           fprintf_unfiltered (stream, "$%d", *p++);
153
154         else if (regnum == 9)        /*89 is Immediate Word Mode*/
155           {
156             temp1 = *p;
157             temp1 <<= 8; 
158             temp1 |= *(p +1);
159             fprintf_unfiltered (stream, "$%d", temp1);
160             p += 2;
161           }  
162
163         else if (regnum == PC_REGNUM)    /*8F is Immediate Long Mode*/
164           {
165             temp1 = *p;
166             temp1 <<=8;
167             temp1 |= *(p +1);
168             temp1 <<=8;
169             temp1 |= *(p +2);
170             temp1 <<= 8;
171             temp1 |= *(p +3);
172             fprintf_unfiltered (stream, "$%d", temp1);
173             p += 4;
174           }
175
176         else                            /*8E is Autoincrement SP Mode*/
177               fprintf_unfiltered (stream, "(%s)+", reg_names[regnum]);
178         break;
179
180       case 11:                  /* Register + Byte Displacement Deferred Mode*/
181         fputc_unfiltered ('*', stream);
182       case 10:                  /* Register + Byte Displacement Mode*/
183         if (regnum == PC_REGNUM)
184           print_address (addr + *p + 2, stream);
185         else
186           fprintf_unfiltered (stream, "%d(%s)", *p, reg_names[regnum]);
187         p += 1;
188         break;
189
190       case 13:                  /* Register + Word Displacement Deferred Mode*/
191         fputc_unfiltered ('*', stream);
192       case 12:                  /* Register + Word Displacement Mode*/
193         temp1 = *p;
194         temp1 <<= 8;
195         temp1 |= *(p +1);
196         if (regnum == PC_REGNUM)
197           print_address (addr + temp1 + 3, stream);
198         else
199           fprintf_unfiltered (stream, "%d(%s)", temp1, reg_names[regnum]);
200         p += 2;
201         break;
202
203       case 15:                  /* Register + Long Displacement Deferred Mode*/
204         fputc_unfiltered ('*', stream);
205       case 14:                  /* Register + Long Displacement Mode*/
206         temp1 = *p;
207         temp1 <<= 8;
208         temp1 |= *(p +1);
209         temp1 <<= 8;
210         temp1 |= *(p +2);
211         temp1 <<= 8;
212         temp1 |= *(p +3);
213         if (regnum == PC_REGNUM)
214           print_address (addr + temp1 + 5, stream);
215         else
216           fprintf_unfiltered (stream, "%d(%s)", temp1, reg_names[regnum]);
217         p += 4;
218       }
219
220   return (unsigned char *) p;
221 }
222
223
224
225
226
227
228
229
230
231
232
233
234