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