Update/correct copyright notices.
[deliverable/binutils-gdb.git] / gdb / ns32k-tdep.c
CommitLineData
c906108c 1/* Print NS 32000 instructions for GDB, the GNU debugger.
b6ba6518 2 Copyright 1986, 1988, 1991, 1992, 1994, 1995, 1998, 1999, 2000, 2001
c906108c
SS
3 Free Software Foundation, Inc.
4
c5aa993b 5 This file is part of GDB.
c906108c 6
c5aa993b
JM
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.
c906108c 11
c5aa993b
JM
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.
c906108c 16
c5aa993b
JM
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. */
c906108c
SS
21
22#include "defs.h"
f6427ade 23#include "frame.h"
c906108c
SS
24
25void
fba45db2 26_initialize_ns32k_tdep (void)
c906108c
SS
27{
28 tm_print_insn = print_insn_ns32k;
29}
b83266a0
SS
30
31/* Advance PC across any function entry prologue instructions
32 to reach some "real" code. */
33
34CORE_ADDR
fba45db2 35merlin_skip_prologue (CORE_ADDR pc)
b83266a0
SS
36{
37 register int op = read_memory_integer (pc, 1);
38 if (op == 0x82)
39 {
c5aa993b 40 op = read_memory_integer (pc + 2, 1);
b83266a0
SS
41 if ((op & 0x80) == 0)
42 pc += 3;
43 else if ((op & 0xc0) == 0x80)
44 pc += 4;
c5aa993b
JM
45 else
46 pc += 6;
b83266a0
SS
47 }
48 return pc;
49}
50
51CORE_ADDR
fba45db2 52umax_skip_prologue (CORE_ADDR pc)
b83266a0
SS
53{
54 register unsigned char op = read_memory_integer (pc, 1);
55 if (op == 0x82)
56 {
c5aa993b 57 op = read_memory_integer (pc + 2, 1);
b83266a0
SS
58 if ((op & 0x80) == 0)
59 pc += 3;
60 else if ((op & 0xc0) == 0x80)
61 pc += 4;
62 else
63 pc += 6;
c5aa993b 64 }
b83266a0
SS
65 return pc;
66}
67
392a587b
JM
68/* Return number of args passed to a frame.
69 Can return -1, meaning no way to tell. */
70
71int
fba45db2 72merlin_frame_num_args (struct frame_info *fi)
392a587b
JM
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);
c5aa993b 81 insn = read_memory_integer (pc, 2);
392a587b
JM
82 addr_mode = (insn >> 11) & 0x1f;
83 insn = insn & 0x7ff;
84 if ((insn & 0x7fc) == 0x57c
c5aa993b 85 && addr_mode == 0x14) /* immediate */
392a587b 86 {
c5aa993b 87 if (insn == 0x57c) /* adjspb */
392a587b 88 width = 1;
c5aa993b 89 else if (insn == 0x57d) /* adjspw */
392a587b 90 width = 2;
c5aa993b 91 else if (insn == 0x57f) /* adjspd */
392a587b 92 width = 4;
c5aa993b 93 numargs = read_memory_integer (pc + 2, width);
392a587b
JM
94 if (width > 1)
95 flip_bytes (&numargs, width);
c5aa993b 96 numargs = -sign_extend (numargs, width * 8) / 4;
392a587b
JM
97 }
98 else
99 numargs = -1;
100 return numargs;
101}
102
cce74817
JM
103
104/* Return number of args passed to a frame.
105 Can return -1, meaning no way to tell.
106 Encore's C compiler often reuses same area on stack for args,
107 so this will often not work properly. If the arg names
108 are known, it's likely most of them will be printed. */
392a587b 109int
fba45db2 110umax_frame_num_args (struct frame_info *fi)
392a587b
JM
111{
112 int numargs;
113 CORE_ADDR pc;
114 CORE_ADDR enter_addr;
115 unsigned int insn;
116 unsigned int addr_mode;
117 int width;
118
119 numargs = -1;
120 enter_addr = ns32k_get_enter_addr ((fi)->pc);
121 if (enter_addr > 0)
122 {
123 pc = ((enter_addr == 1)
124 ? SAVED_PC_AFTER_CALL (fi)
125 : FRAME_SAVED_PC (fi));
c5aa993b 126 insn = read_memory_integer (pc, 2);
392a587b
JM
127 addr_mode = (insn >> 11) & 0x1f;
128 insn = insn & 0x7ff;
129 if ((insn & 0x7fc) == 0x57c
c5aa993b 130 && addr_mode == 0x14) /* immediate */
392a587b 131 {
c5aa993b 132 if (insn == 0x57c) /* adjspb */
392a587b 133 width = 1;
c5aa993b 134 else if (insn == 0x57d) /* adjspw */
392a587b 135 width = 2;
c5aa993b 136 else if (insn == 0x57f) /* adjspd */
392a587b 137 width = 4;
c5aa993b 138 numargs = read_memory_integer (pc + 2, width);
392a587b
JM
139 if (width > 1)
140 flip_bytes (&numargs, width);
c5aa993b 141 numargs = -sign_extend (numargs, width * 8) / 4;
392a587b
JM
142 }
143 }
144 return numargs;
145}
b83266a0 146
c906108c 147
fba45db2 148sign_extend (int value, int bits)
c906108c
SS
149{
150 value = value & ((1 << bits) - 1);
c5aa993b 151 return (value & (1 << (bits - 1))
c906108c
SS
152 ? value | (~((1 << bits) - 1))
153 : value);
154}
155
156void
fba45db2 157flip_bytes (char *ptr, int count)
c906108c
SS
158{
159 char tmp;
160
161 while (count > 0)
162 {
163 tmp = *ptr;
c5aa993b
JM
164 ptr[0] = ptr[count - 1];
165 ptr[count - 1] = tmp;
c906108c
SS
166 ptr++;
167 count -= 2;
168 }
169}
170
171/* Return the number of locals in the current frame given a pc
172 pointing to the enter instruction. This is used in the macro
173 FRAME_FIND_SAVED_REGS. */
174
175int
fba45db2 176ns32k_localcount (CORE_ADDR enter_pc)
c906108c
SS
177{
178 unsigned char localtype;
179 int localcount;
180
c5aa993b 181 localtype = read_memory_integer (enter_pc + 2, 1);
c906108c
SS
182 if ((localtype & 0x80) == 0)
183 localcount = localtype;
184 else if ((localtype & 0xc0) == 0x80)
185 localcount = (((localtype & 0x3f) << 8)
c5aa993b 186 | (read_memory_integer (enter_pc + 3, 1) & 0xff));
c906108c
SS
187 else
188 localcount = (((localtype & 0x3f) << 24)
c5aa993b
JM
189 | ((read_memory_integer (enter_pc + 3, 1) & 0xff) << 16)
190 | ((read_memory_integer (enter_pc + 4, 1) & 0xff) << 8)
191 | (read_memory_integer (enter_pc + 5, 1) & 0xff));
c906108c
SS
192 return localcount;
193}
194
195
196/* Nonzero if instruction at PC is a return instruction. */
197
198static int
fba45db2 199ns32k_about_to_return (CORE_ADDR pc)
c906108c
SS
200{
201 return (read_memory_integer (pc, 1) == 0x12);
202}
203
204
205/*
206 * Get the address of the enter opcode for the function
207 * containing PC, if there is an enter for the function,
208 * and if the pc is between the enter and exit.
209 * Returns positive address if pc is between enter/exit,
210 * 1 if pc before enter or after exit, 0 otherwise.
211 */
212
213CORE_ADDR
fba45db2 214ns32k_get_enter_addr (CORE_ADDR pc)
c906108c
SS
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))
c5aa993b 223 return 1; /* after exit */
c906108c
SS
224
225 enter_addr = get_pc_function_start (pc);
226
c5aa993b
JM
227 if (pc == enter_addr)
228 return 1; /* before enter */
c906108c
SS
229
230 op = read_memory_integer (enter_addr, 1);
231
232 if (op != 0x82)
c5aa993b 233 return 0; /* function has no enter/exit */
c906108c 234
c5aa993b 235 return enter_addr; /* pc is between enter and exit */
c906108c 236}
This page took 0.105175 seconds and 4 git commands to generate.