]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/gdb/gdb/ns32k-tdep.c
This file was not part of the GDB 5.2.1 import and should have been
[FreeBSD/FreeBSD.git] / contrib / gdb / 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 }