*** empty log message ***
[deliverable/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 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 void
29 _initialize_ns32k_tdep (void)
30 {
31 tm_print_insn = print_insn_ns32k;
32 }
33
34 /* Advance PC across any function entry prologue instructions
35 to reach some "real" code. */
36
37 CORE_ADDR
38 umax_skip_prologue (CORE_ADDR pc)
39 {
40 register unsigned char op = read_memory_integer (pc, 1);
41 if (op == 0x82)
42 {
43 op = read_memory_integer (pc + 2, 1);
44 if ((op & 0x80) == 0)
45 pc += 3;
46 else if ((op & 0xc0) == 0x80)
47 pc += 4;
48 else
49 pc += 6;
50 }
51 return pc;
52 }
53
54 /* Return number of args passed to a frame.
55 Can return -1, meaning no way to tell.
56 Encore's C compiler often reuses same area on stack for args,
57 so this will often not work properly. If the arg names
58 are known, it's likely most of them will be printed. */
59
60 int
61 umax_frame_num_args (struct frame_info *fi)
62 {
63 int numargs;
64 CORE_ADDR pc;
65 CORE_ADDR enter_addr;
66 unsigned int insn;
67 unsigned int addr_mode;
68 int width;
69
70 numargs = -1;
71 enter_addr = ns32k_get_enter_addr ((fi)->pc);
72 if (enter_addr > 0)
73 {
74 pc = ((enter_addr == 1)
75 ? SAVED_PC_AFTER_CALL (fi)
76 : FRAME_SAVED_PC (fi));
77 insn = read_memory_integer (pc, 2);
78 addr_mode = (insn >> 11) & 0x1f;
79 insn = insn & 0x7ff;
80 if ((insn & 0x7fc) == 0x57c
81 && addr_mode == 0x14) /* immediate */
82 {
83 if (insn == 0x57c) /* adjspb */
84 width = 1;
85 else if (insn == 0x57d) /* adjspw */
86 width = 2;
87 else if (insn == 0x57f) /* adjspd */
88 width = 4;
89 else
90 internal_error (__FILE__, __LINE__, "bad else");
91 numargs = read_memory_integer (pc + 2, width);
92 if (width > 1)
93 flip_bytes (&numargs, width);
94 numargs = -sign_extend (numargs, width * 8) / 4;
95 }
96 }
97 return numargs;
98 }
99
100 static int
101 sign_extend (int value, int bits)
102 {
103 value = value & ((1 << bits) - 1);
104 return (value & (1 << (bits - 1))
105 ? value | (~((1 << bits) - 1))
106 : value);
107 }
108
109 void
110 flip_bytes (void *p, int count)
111 {
112 char tmp;
113 char *ptr = 0;
114
115 while (count > 0)
116 {
117 tmp = *ptr;
118 ptr[0] = ptr[count - 1];
119 ptr[count - 1] = tmp;
120 ptr++;
121 count -= 2;
122 }
123 }
124
125 /* Return the number of locals in the current frame given a pc
126 pointing to the enter instruction. This is used in the macro
127 FRAME_FIND_SAVED_REGS. */
128
129 int
130 ns32k_localcount (CORE_ADDR enter_pc)
131 {
132 unsigned char localtype;
133 int localcount;
134
135 localtype = read_memory_integer (enter_pc + 2, 1);
136 if ((localtype & 0x80) == 0)
137 localcount = localtype;
138 else if ((localtype & 0xc0) == 0x80)
139 localcount = (((localtype & 0x3f) << 8)
140 | (read_memory_integer (enter_pc + 3, 1) & 0xff));
141 else
142 localcount = (((localtype & 0x3f) << 24)
143 | ((read_memory_integer (enter_pc + 3, 1) & 0xff) << 16)
144 | ((read_memory_integer (enter_pc + 4, 1) & 0xff) << 8)
145 | (read_memory_integer (enter_pc + 5, 1) & 0xff));
146 return localcount;
147 }
148
149
150 /* Nonzero if instruction at PC is a return instruction. */
151
152 static int
153 ns32k_about_to_return (CORE_ADDR pc)
154 {
155 return (read_memory_integer (pc, 1) == 0x12);
156 }
157
158
159 /*
160 * Get the address of the enter opcode for the function
161 * containing PC, if there is an enter for the function,
162 * and if the pc is between the enter and exit.
163 * Returns positive address if pc is between enter/exit,
164 * 1 if pc before enter or after exit, 0 otherwise.
165 */
166
167 CORE_ADDR
168 ns32k_get_enter_addr (CORE_ADDR pc)
169 {
170 CORE_ADDR enter_addr;
171 unsigned char op;
172
173 if (pc == 0)
174 return 0;
175
176 if (ns32k_about_to_return (pc))
177 return 1; /* after exit */
178
179 enter_addr = get_pc_function_start (pc);
180
181 if (pc == enter_addr)
182 return 1; /* before enter */
183
184 op = read_memory_integer (enter_addr, 1);
185
186 if (op != 0x82)
187 return 0; /* function has no enter/exit */
188
189 return enter_addr; /* pc is between enter and exit */
190 }
This page took 0.034032 seconds and 4 git commands to generate.