import gdb-1999-05-25 snapshot
[deliverable/binutils-gdb.git] / gdb / ns32k-tdep.c
CommitLineData
c906108c
SS
1/* Print NS 32000 instructions for GDB, the GNU debugger.
2 Copyright 1986, 1988, 1991, 1992, 1994, 1995
3 Free Software Foundation, Inc.
4
5This file is part of GDB.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21#include "defs.h"
22
23void
24_initialize_ns32k_tdep ()
25{
26 tm_print_insn = print_insn_ns32k;
27}
b83266a0
SS
28
29/* Advance PC across any function entry prologue instructions
30 to reach some "real" code. */
31
32CORE_ADDR
33merlin_skip_prologue (pc)
34 CORE_ADDR pc;
35{
36 register int op = read_memory_integer (pc, 1);
37 if (op == 0x82)
38 {
39 op = read_memory_integer (pc+2,1);
40 if ((op & 0x80) == 0)
41 pc += 3;
42 else if ((op & 0xc0) == 0x80)
43 pc += 4;
44 else pc += 6;
45 }
46 return pc;
47}
48
49CORE_ADDR
50umax_skip_prologue (pc)
51 CORE_ADDR pc;
52{
53 register unsigned char op = read_memory_integer (pc, 1);
54 if (op == 0x82)
55 {
56 op = read_memory_integer (pc+2,1);
57 if ((op & 0x80) == 0)
58 pc += 3;
59 else if ((op & 0xc0) == 0x80)
60 pc += 4;
61 else
62 pc += 6;
63 }
64 return pc;
65}
66
392a587b
JM
67/* Return number of args passed to a frame.
68 Can return -1, meaning no way to tell. */
69
70int
71merlin_frame_num_args (fi)
72 struct frame_info *fi;
73{
74 int numargs;
75 CORE_ADDR pc;
76 int insn;
77 int addr_mode;
78 int width;
79
80 pc = FRAME_SAVED_PC (fi);
81 insn = read_memory_integer (pc,2);
82 addr_mode = (insn >> 11) & 0x1f;
83 insn = insn & 0x7ff;
84 if ((insn & 0x7fc) == 0x57c
85 && addr_mode == 0x14) /* immediate */
86 {
87 if (insn == 0x57c) /* adjspb */
88 width = 1;
89 else if (insn == 0x57d) /* adjspw */
90 width = 2;
91 else if (insn == 0x57f) /* adjspd */
92 width = 4;
93 numargs = read_memory_integer (pc+2,width);
94 if (width > 1)
95 flip_bytes (&numargs, width);
96 numargs = - sign_extend (numargs, width*8) / 4;
97 }
98 else
99 numargs = -1;
100 return numargs;
101}
102
103int
104umax_frame_num_args (fi)
105 struct frame_info *fi;
106{
107 int numargs;
108 CORE_ADDR pc;
109 CORE_ADDR enter_addr;
110 unsigned int insn;
111 unsigned int addr_mode;
112 int width;
113
114 numargs = -1;
115 enter_addr = ns32k_get_enter_addr ((fi)->pc);
116 if (enter_addr > 0)
117 {
118 pc = ((enter_addr == 1)
119 ? SAVED_PC_AFTER_CALL (fi)
120 : FRAME_SAVED_PC (fi));
121 insn = read_memory_integer (pc,2);
122 addr_mode = (insn >> 11) & 0x1f;
123 insn = insn & 0x7ff;
124 if ((insn & 0x7fc) == 0x57c
125 && addr_mode == 0x14) /* immediate */
126 {
127 if (insn == 0x57c) /* adjspb */
128 width = 1;
129 else if (insn == 0x57d) /* adjspw */
130 width = 2;
131 else if (insn == 0x57f) /* adjspd */
132 width = 4;
133 numargs = read_memory_integer (pc+2,width);
134 if (width > 1)
135 flip_bytes (&numargs, width);
136 numargs = - sign_extend (numargs, width*8) / 4;
137 }
138 }
139 return numargs;
140}
b83266a0 141
c906108c
SS
142
143sign_extend (value, bits)
144{
145 value = value & ((1 << bits) - 1);
146 return (value & (1 << (bits-1))
147 ? value | (~((1 << bits) - 1))
148 : value);
149}
150
151void
152flip_bytes (ptr, count)
153 char *ptr;
154 int count;
155{
156 char tmp;
157
158 while (count > 0)
159 {
160 tmp = *ptr;
161 ptr[0] = ptr[count-1];
162 ptr[count-1] = tmp;
163 ptr++;
164 count -= 2;
165 }
166}
167
168/* Return the number of locals in the current frame given a pc
169 pointing to the enter instruction. This is used in the macro
170 FRAME_FIND_SAVED_REGS. */
171
172int
173ns32k_localcount (enter_pc)
174 CORE_ADDR enter_pc;
175{
176 unsigned char localtype;
177 int localcount;
178
179 localtype = read_memory_integer (enter_pc+2, 1);
180 if ((localtype & 0x80) == 0)
181 localcount = localtype;
182 else if ((localtype & 0xc0) == 0x80)
183 localcount = (((localtype & 0x3f) << 8)
184 | (read_memory_integer (enter_pc+3, 1) & 0xff));
185 else
186 localcount = (((localtype & 0x3f) << 24)
187 | ((read_memory_integer (enter_pc+3, 1) & 0xff) << 16)
188 | ((read_memory_integer (enter_pc+4, 1) & 0xff) << 8 )
189 | (read_memory_integer (enter_pc+5, 1) & 0xff));
190 return localcount;
191}
192
193
194/* Nonzero if instruction at PC is a return instruction. */
195
196static int
197ns32k_about_to_return (pc)
198 CORE_ADDR pc;
199{
200 return (read_memory_integer (pc, 1) == 0x12);
201}
202
203
204/*
205 * Get the address of the enter opcode for the function
206 * containing PC, if there is an enter for the function,
207 * and if the pc is between the enter and exit.
208 * Returns positive address if pc is between enter/exit,
209 * 1 if pc before enter or after exit, 0 otherwise.
210 */
211
212CORE_ADDR
213ns32k_get_enter_addr (pc)
214 CORE_ADDR pc;
215{
216 CORE_ADDR enter_addr;
217 unsigned char op;
218
219 if (pc == 0)
220 return 0;
221
222 if (ns32k_about_to_return (pc))
223 return 1; /* after exit */
224
225 enter_addr = get_pc_function_start (pc);
226
227 if (pc == enter_addr)
228 return 1; /* before enter */
229
230 op = read_memory_integer (enter_addr, 1);
231
232 if (op != 0x82)
233 return 0; /* function has no enter/exit */
234
235 return enter_addr; /* pc is between enter and exit */
236}
This page took 0.051746 seconds and 4 git commands to generate.