OSDN Git Service

* ns32k-tdep.c: Update copyright years.
[pf3gnuchains/pf3gnuchains3x.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 }