Intel 386 Mach host port
[deliverable/binutils-gdb.git] / gdb / gould-pinsn.c
CommitLineData
dd3b648e
RP
1/* Print GOULD RISC instructions for GDB, the GNU debugger.
2 Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
3
4This file is part of GDB.
5
99a7de40 6This program is free software; you can redistribute it and/or modify
dd3b648e 7it under the terms of the GNU General Public License as published by
99a7de40
JG
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
dd3b648e 10
99a7de40 11This program is distributed in the hope that it will be useful,
dd3b648e
RP
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
99a7de40
JG
17along with this program; if not, write to the Free Software
18Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
dd3b648e
RP
19
20#include <stdio.h>
21#include "gdbcore.h"
22
23#include "defs.h"
24#include "param.h"
25#include "symtab.h"
26#include "frame.h"
27#if defined GOULD_PN
28#include "pn-opcode.h"
29#else
30#include "np1-opcode.h"
31#endif
32
33/* GOULD RISC instructions are never longer than this many bytes. */
34#define MAXLEN 4
35
36/* Number of elements in the opcode table. */
37#define NOPCODES (sizeof gld_opcodes / sizeof gld_opcodes[0])
38
39\f
40/* Print the GOULD instruction at address MEMADDR in debugged memory,
41 on STREAM. Returns length of the instruction, in bytes. */
42
43int
44print_insn (memaddr, stream)
45 CORE_ADDR memaddr;
46 FILE *stream;
47{
48 unsigned char buffer[MAXLEN];
49 register int i;
50 register char *d;
51 register int bestmask;
52 unsigned best;
53 int temp, index, bestlen;
54
55 read_memory (memaddr, buffer, MAXLEN);
56
57 bestmask = 0;
58 index = -1;
59 best = 0xffffffff;
60 for (i = 0; i < NOPCODES; i++)
61 {
62 register unsigned int opcode = gld_opcodes[i].opcode;
63 register unsigned int mask = gld_opcodes[i].mask;
64 register unsigned int len = gld_opcodes[i].length;
65 register unsigned int test;
66
67 /* Get possible opcode bytes into integer */
68 test = buffer[0] << 24;
69 test |= buffer[1] << 16;
70 test |= buffer[2] << 8;
71 test |= buffer[3];
72
73 /* Mask with opcode and see if match */
74 if ((opcode & mask) == (test & mask))
75 {
76 /* See if second or third match */
77 if (index >= 0)
78 {
79 /* Take new one if it looks good */
80 if (bestlen == MAXLEN && len == MAXLEN)
81 {
82 /* See if lower bits matched */
83 if (((bestmask & 3) == 0) &&
84 ((mask & 3) != 0))
85 {
86 bestmask = mask;
87 bestlen = len;
88 best = test;
89 index = i;
90 }
91 }
92 }
93 else
94 {
95 /* First match, save it */
96 bestmask = mask;
97 bestlen = len;
98 best = test;
99 index = i;
100 }
101 }
102 }
103
104 /* Handle undefined instructions. */
105 if (index < 0)
106 {
107 fprintf (stream, "undefined 0%o",(buffer[0]<<8)+buffer[1]);
108 return 2;
109 }
110
111 /* Print instruction name */
112 fprintf (stream, "%-12s", gld_opcodes[index].name);
113
114 /* Adjust if short instruction */
115 if (gld_opcodes[index].length < 4)
116 {
117 best >>= 16;
118 i = 0;
119 }
120 else
121 {
122 i = 16;
123 }
124
125 /* Dump out instruction arguments */
126 for (d = gld_opcodes[index].args; *d; ++d)
127 {
128 switch (*d)
129 {
130 case 'f':
131 fprintf (stream, "%d", (best >> (7 + i)) & 7);
132 break;
133 case 'r':
134 fprintf (stream, "r%d", (best >> (7 + i)) & 7);
135 break;
136 case 'R':
137 fprintf (stream, "r%d", (best >> (4 + i)) & 7);
138 break;
139 case 'b':
140 fprintf (stream, "b%d", (best >> (7 + i)) & 7);
141 break;
142 case 'B':
143 fprintf (stream, "b%d", (best >> (4 + i)) & 7);
144 break;
145 case 'v':
146 fprintf (stream, "b%d", (best >> (7 + i)) & 7);
147 break;
148 case 'V':
149 fprintf (stream, "b%d", (best >> (4 + i)) & 7);
150 break;
151 case 'X':
152 temp = (best >> 20) & 7;
153 if (temp)
154 fprintf (stream, "r%d", temp);
155 else
156 putc ('0', stream);
157 break;
158 case 'A':
159 temp = (best >> 16) & 7;
160 if (temp)
161 fprintf (stream, "(b%d)", temp);
162 break;
163 case 'S':
164 fprintf (stream, "#%d", best & 0x1f);
165 break;
166 case 'I':
167 fprintf (stream, "#%x", best & 0xffff);
168 break;
169 case 'O':
170 fprintf (stream, "%x", best & 0xffff);
171 break;
172 case 'h':
173 fprintf (stream, "%d", best & 0xfffe);
174 break;
175 case 'd':
176 fprintf (stream, "%d", best & 0xfffc);
177 break;
178 case 'T':
179 fprintf (stream, "%d", (best >> 8) & 0xff);
180 break;
181 case 'N':
182 fprintf (stream, "%d", best & 0xff);
183 break;
184 default:
185 putc (*d, stream);
186 break;
187 }
188 }
189
190 /* Return length of instruction */
191 return (gld_opcodes[index].length);
192}
193
194/*
195 * Find the number of arguments to a function.
196 */
197findarg(frame)
198 struct frame_info *frame;
199{
200 register struct symbol *func;
201 register unsigned pc;
202
203#ifdef notdef
204 /* find starting address of frame function */
205 pc = get_pc_function_start (frame->pc);
206
207 /* find function symbol info */
208 func = find_pc_function (pc);
209
210 /* call blockframe code to look for match */
211 if (func != NULL)
212 return (func->value.block->nsyms / sizeof(int));
213#endif
214
215 return (-1);
216}
217
218/*
219 * In the case of the NPL, the frame's norminal address is Br2 and the
220 * previous routines frame is up the stack X bytes. Finding out what
221 * 'X' is can be tricky.
222 *
223 * 1.) stored in the code function header xA(Br1).
224 * 2.) must be careful of recurssion.
225 */
226FRAME_ADDR
227findframe(thisframe)
228 FRAME thisframe;
229{
230 register FRAME_ADDR pointer;
231 FRAME_ADDR framechain();
232#if 0
233 struct frame_info *frame;
234
235 /* Setup toplevel frame structure */
236 frame->pc = read_pc();
237 frame->next_frame = 0;
238 frame->frame = read_register (SP_REGNUM); /* Br2 */
239
240 /* Search for this frame (start at current Br2) */
241 do
242 {
243 pointer = framechain(frame);
244 frame->next_frame = frame->frame;
245 frame->frame = pointer;
246 frame->pc = FRAME_SAVED_PC(frame);
247 }
248 while (frame->next_frame != thisframe);
249#endif
250
251 pointer = framechain (thisframe);
252
253 /* stop gap for now, end at __base3 */
254 if (thisframe->pc == 0)
255 return 0;
256
257 return pointer;
258}
259
260/*
261 * Gdb front-end and internal framechain routine.
262 * Go back up stack one level. Tricky...
263 */
264FRAME_ADDR
265framechain(frame)
266 register struct frame_info *frame;
267{
268 register CORE_ADDR func, prevsp;
269 register unsigned value;
270
271 /* Get real function start address from internal frame address */
272 func = get_pc_function_start(frame->pc);
273
274 /* If no stack given, read register Br1 "(sp)" */
275 if (!frame->frame)
276 prevsp = read_register (SP_REGNUM);
277 else
278 prevsp = frame->frame;
279
280 /* Check function header, case #2 */
281 value = read_memory_integer (func, 4);
282 if (value)
283 {
284 /* 32bit call push value stored in function header */
285 prevsp += value;
286 }
287 else
288 {
289 /* read half-word from suabr at start of function */
290 prevsp += read_memory_integer (func + 10, 2);
291 }
292
293 return (prevsp);
294}
This page took 0.044526 seconds and 4 git commands to generate.