xref: /openbsd/gnu/usr.bin/binutils/gdb/ns32k-tdep.c (revision 63addd46)
1b725ae77Skettenis /* Target dependent code for the NS32000, for GDB.
2b725ae77Skettenis 
3b725ae77Skettenis    Copyright 1986, 1988, 1991, 1992, 1994, 1995, 1998, 1999, 2000,
4b725ae77Skettenis    2001, 2002, 2003, 2004 Free Software Foundation, Inc.
5e93f7393Sniklas 
6e93f7393Sniklas    This file is part of GDB.
7e93f7393Sniklas 
8e93f7393Sniklas    This program is free software; you can redistribute it and/or modify
9e93f7393Sniklas    it under the terms of the GNU General Public License as published by
10e93f7393Sniklas    the Free Software Foundation; either version 2 of the License, or
11e93f7393Sniklas    (at your option) any later version.
12e93f7393Sniklas 
13e93f7393Sniklas    This program is distributed in the hope that it will be useful,
14e93f7393Sniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
15e93f7393Sniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16e93f7393Sniklas    GNU General Public License for more details.
17e93f7393Sniklas 
18e93f7393Sniklas    You should have received a copy of the GNU General Public License
19e93f7393Sniklas    along with this program; if not, write to the Free Software
20b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
21b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
22e93f7393Sniklas 
23e93f7393Sniklas #include "defs.h"
24b725ae77Skettenis #include "frame.h"
25b725ae77Skettenis #include "gdbtypes.h"
26b725ae77Skettenis #include "gdbcore.h"
27b725ae77Skettenis #include "inferior.h"
28b725ae77Skettenis #include "regcache.h"
29b725ae77Skettenis #include "target.h"
30b725ae77Skettenis #include "arch-utils.h"
31b725ae77Skettenis #include "osabi.h"
32b725ae77Skettenis #include "dis-asm.h"
33b725ae77Skettenis 
34b725ae77Skettenis #include "ns32k-tdep.h"
35b725ae77Skettenis #include "gdb_string.h"
36b725ae77Skettenis 
37b725ae77Skettenis static int sign_extend (int value, int bits);
38b725ae77Skettenis static CORE_ADDR ns32k_get_enter_addr (CORE_ADDR);
39b725ae77Skettenis static int ns32k_localcount (CORE_ADDR enter_pc);
40b725ae77Skettenis static void flip_bytes (void *, int);
41b725ae77Skettenis 
42b725ae77Skettenis static const char *
ns32k_register_name_32082(int regno)43b725ae77Skettenis ns32k_register_name_32082 (int regno)
44b725ae77Skettenis {
45b725ae77Skettenis   static char *register_names[] =
46b725ae77Skettenis   {
47b725ae77Skettenis     "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
48b725ae77Skettenis     "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
49b725ae77Skettenis     "sp", "fp", "pc", "ps",
50b725ae77Skettenis     "l0", "l1", "l2", "l3", "xx",
51b725ae77Skettenis   };
52b725ae77Skettenis 
53b725ae77Skettenis   if (regno < 0)
54b725ae77Skettenis     return NULL;
55b725ae77Skettenis   if (regno >= sizeof (register_names) / sizeof (*register_names))
56b725ae77Skettenis     return NULL;
57b725ae77Skettenis 
58b725ae77Skettenis   return (register_names[regno]);
59b725ae77Skettenis }
60b725ae77Skettenis 
61b725ae77Skettenis static const char *
ns32k_register_name_32382(int regno)62b725ae77Skettenis ns32k_register_name_32382 (int regno)
63b725ae77Skettenis {
64b725ae77Skettenis   static char *register_names[] =
65b725ae77Skettenis   {
66b725ae77Skettenis     "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
67b725ae77Skettenis     "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
68b725ae77Skettenis     "sp", "fp", "pc", "ps",
69b725ae77Skettenis     "fsr",
70b725ae77Skettenis     "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", "xx",
71b725ae77Skettenis   };
72b725ae77Skettenis 
73b725ae77Skettenis   if (regno < 0)
74b725ae77Skettenis     return NULL;
75b725ae77Skettenis   if (regno >= sizeof (register_names) / sizeof (*register_names))
76b725ae77Skettenis     return NULL;
77b725ae77Skettenis 
78b725ae77Skettenis   return (register_names[regno]);
79b725ae77Skettenis }
80b725ae77Skettenis 
81b725ae77Skettenis static int
ns32k_register_byte_32082(int regno)82b725ae77Skettenis ns32k_register_byte_32082 (int regno)
83b725ae77Skettenis {
84b725ae77Skettenis   if (regno >= NS32K_LP0_REGNUM)
85b725ae77Skettenis     return (NS32K_LP0_REGNUM * 4) + ((regno - NS32K_LP0_REGNUM) * 8);
86b725ae77Skettenis 
87b725ae77Skettenis   return (regno * 4);
88b725ae77Skettenis }
89b725ae77Skettenis 
90b725ae77Skettenis static int
ns32k_register_byte_32382(int regno)91b725ae77Skettenis ns32k_register_byte_32382 (int regno)
92b725ae77Skettenis {
93b725ae77Skettenis   /* This is a bit yuk.  The even numbered double precision floating
94b725ae77Skettenis      point long registers occupy the same space as the even:odd numbered
95b725ae77Skettenis      single precision floating point registers, but the extra 32381 FPU
96b725ae77Skettenis      registers are at the end.  Doing it this way is compatible for both
97b725ae77Skettenis      32081 and 32381 equipped machines.  */
98b725ae77Skettenis 
99b725ae77Skettenis   return ((regno < NS32K_LP0_REGNUM ? regno
100b725ae77Skettenis            : (regno - NS32K_LP0_REGNUM) & 1 ? regno - 1
101b725ae77Skettenis            : (regno - NS32K_LP0_REGNUM + FP0_REGNUM)) * 4);
102b725ae77Skettenis }
103b725ae77Skettenis 
104b725ae77Skettenis static int
ns32k_register_raw_size(int regno)105b725ae77Skettenis ns32k_register_raw_size (int regno)
106b725ae77Skettenis {
107b725ae77Skettenis   /* All registers are 4 bytes, except for the doubled floating
108b725ae77Skettenis      registers.  */
109b725ae77Skettenis 
110b725ae77Skettenis   return ((regno >= NS32K_LP0_REGNUM) ? 8 : 4);
111b725ae77Skettenis }
112b725ae77Skettenis 
113b725ae77Skettenis static int
ns32k_register_virtual_size(int regno)114b725ae77Skettenis ns32k_register_virtual_size (int regno)
115b725ae77Skettenis {
116b725ae77Skettenis   return ((regno >= NS32K_LP0_REGNUM) ? 8 : 4);
117b725ae77Skettenis }
118b725ae77Skettenis 
119b725ae77Skettenis static struct type *
ns32k_register_virtual_type(int regno)120b725ae77Skettenis ns32k_register_virtual_type (int regno)
121b725ae77Skettenis {
122b725ae77Skettenis   if (regno < FP0_REGNUM)
123b725ae77Skettenis     return (builtin_type_int);
124b725ae77Skettenis 
125b725ae77Skettenis   if (regno < FP0_REGNUM + 8)
126b725ae77Skettenis     return (builtin_type_float);
127b725ae77Skettenis 
128b725ae77Skettenis   if (regno < NS32K_LP0_REGNUM)
129b725ae77Skettenis     return (builtin_type_int);
130b725ae77Skettenis 
131b725ae77Skettenis   return (builtin_type_double);
132b725ae77Skettenis }
133b725ae77Skettenis 
134b725ae77Skettenis /* Immediately after a function call, return the saved PC.  Can't
135b725ae77Skettenis    always go through the frames for this because on some systems,
136b725ae77Skettenis    the new frame is not set up until the new function executes some
137b725ae77Skettenis    instructions.  */
138b725ae77Skettenis 
139b725ae77Skettenis static CORE_ADDR
ns32k_saved_pc_after_call(struct frame_info * frame)140b725ae77Skettenis ns32k_saved_pc_after_call (struct frame_info *frame)
141b725ae77Skettenis {
142b725ae77Skettenis   return (read_memory_integer (read_register (SP_REGNUM), 4));
143b725ae77Skettenis }
144b725ae77Skettenis 
145b725ae77Skettenis /* Advance PC across any function entry prologue instructions
146b725ae77Skettenis    to reach some "real" code.  */
147b725ae77Skettenis 
148b725ae77Skettenis static CORE_ADDR
umax_skip_prologue(CORE_ADDR pc)149b725ae77Skettenis umax_skip_prologue (CORE_ADDR pc)
150b725ae77Skettenis {
151b725ae77Skettenis   unsigned char op = read_memory_integer (pc, 1);
152b725ae77Skettenis   if (op == 0x82)
153b725ae77Skettenis     {
154b725ae77Skettenis       op = read_memory_integer (pc + 2, 1);
155b725ae77Skettenis       if ((op & 0x80) == 0)
156b725ae77Skettenis 	pc += 3;
157b725ae77Skettenis       else if ((op & 0xc0) == 0x80)
158b725ae77Skettenis 	pc += 4;
159b725ae77Skettenis       else
160b725ae77Skettenis 	pc += 6;
161b725ae77Skettenis     }
162b725ae77Skettenis   return pc;
163b725ae77Skettenis }
164b725ae77Skettenis 
165b725ae77Skettenis static const unsigned char *
ns32k_breakpoint_from_pc(CORE_ADDR * pcp,int * lenp)166b725ae77Skettenis ns32k_breakpoint_from_pc (CORE_ADDR *pcp, int *lenp)
167b725ae77Skettenis {
168b725ae77Skettenis   static const unsigned char breakpoint_insn[] = { 0xf2 };
169b725ae77Skettenis 
170b725ae77Skettenis   *lenp = sizeof (breakpoint_insn);
171b725ae77Skettenis   return breakpoint_insn;
172b725ae77Skettenis }
173b725ae77Skettenis 
174b725ae77Skettenis /* Return number of args passed to a frame.
175b725ae77Skettenis    Can return -1, meaning no way to tell.
176b725ae77Skettenis    Encore's C compiler often reuses same area on stack for args,
177b725ae77Skettenis    so this will often not work properly.  If the arg names
178b725ae77Skettenis    are known, it's likely most of them will be printed. */
179b725ae77Skettenis 
180b725ae77Skettenis static int
umax_frame_num_args(struct frame_info * fi)181b725ae77Skettenis umax_frame_num_args (struct frame_info *fi)
182b725ae77Skettenis {
183b725ae77Skettenis   int numargs;
184b725ae77Skettenis   CORE_ADDR pc;
185b725ae77Skettenis   CORE_ADDR enter_addr;
186b725ae77Skettenis   unsigned int insn;
187b725ae77Skettenis   unsigned int addr_mode;
188b725ae77Skettenis   int width;
189b725ae77Skettenis 
190b725ae77Skettenis   numargs = -1;
191b725ae77Skettenis   enter_addr = ns32k_get_enter_addr (get_frame_pc (fi));
192b725ae77Skettenis   if (enter_addr > 0)
193b725ae77Skettenis     {
194b725ae77Skettenis       pc = ((enter_addr == 1)
195b725ae77Skettenis 	    ? DEPRECATED_SAVED_PC_AFTER_CALL (fi)
196b725ae77Skettenis 	    : DEPRECATED_FRAME_SAVED_PC (fi));
197b725ae77Skettenis       insn = read_memory_integer (pc, 2);
198b725ae77Skettenis       addr_mode = (insn >> 11) & 0x1f;
199b725ae77Skettenis       insn = insn & 0x7ff;
200b725ae77Skettenis       if ((insn & 0x7fc) == 0x57c
201b725ae77Skettenis 	  && addr_mode == 0x14)	/* immediate */
202b725ae77Skettenis 	{
203b725ae77Skettenis 	  if (insn == 0x57c)	/* adjspb */
204b725ae77Skettenis 	    width = 1;
205b725ae77Skettenis 	  else if (insn == 0x57d)	/* adjspw */
206b725ae77Skettenis 	    width = 2;
207b725ae77Skettenis 	  else if (insn == 0x57f)	/* adjspd */
208b725ae77Skettenis 	    width = 4;
209b725ae77Skettenis 	  else
210b725ae77Skettenis 	    internal_error (__FILE__, __LINE__, "bad else");
211b725ae77Skettenis 	  numargs = read_memory_integer (pc + 2, width);
212b725ae77Skettenis 	  if (width > 1)
213b725ae77Skettenis 	    flip_bytes (&numargs, width);
214b725ae77Skettenis 	  numargs = -sign_extend (numargs, width * 8) / 4;
215b725ae77Skettenis 	}
216b725ae77Skettenis     }
217b725ae77Skettenis   return numargs;
218b725ae77Skettenis }
219b725ae77Skettenis 
220b725ae77Skettenis static int
sign_extend(int value,int bits)221b725ae77Skettenis sign_extend (int value, int bits)
222b725ae77Skettenis {
223b725ae77Skettenis   value = value & ((1 << bits) - 1);
224b725ae77Skettenis   return (value & (1 << (bits - 1))
225b725ae77Skettenis 	  ? value | (~((1 << bits) - 1))
226b725ae77Skettenis 	  : value);
227b725ae77Skettenis }
228b725ae77Skettenis 
229b725ae77Skettenis static void
flip_bytes(void * p,int count)230b725ae77Skettenis flip_bytes (void *p, int count)
231b725ae77Skettenis {
232b725ae77Skettenis   char tmp;
233b725ae77Skettenis   char *ptr = 0;
234b725ae77Skettenis 
235b725ae77Skettenis   while (count > 0)
236b725ae77Skettenis     {
237b725ae77Skettenis       tmp = *ptr;
238b725ae77Skettenis       ptr[0] = ptr[count - 1];
239b725ae77Skettenis       ptr[count - 1] = tmp;
240b725ae77Skettenis       ptr++;
241b725ae77Skettenis       count -= 2;
242b725ae77Skettenis     }
243b725ae77Skettenis }
244b725ae77Skettenis 
245b725ae77Skettenis /* Return the number of locals in the current frame given a
246b725ae77Skettenis    pc pointing to the enter instruction.  This is used by
247b725ae77Skettenis    ns32k_frame_init_saved_regs.  */
248b725ae77Skettenis 
249b725ae77Skettenis static int
ns32k_localcount(CORE_ADDR enter_pc)250b725ae77Skettenis ns32k_localcount (CORE_ADDR enter_pc)
251b725ae77Skettenis {
252b725ae77Skettenis   unsigned char localtype;
253b725ae77Skettenis   int localcount;
254b725ae77Skettenis 
255b725ae77Skettenis   localtype = read_memory_integer (enter_pc + 2, 1);
256b725ae77Skettenis   if ((localtype & 0x80) == 0)
257b725ae77Skettenis     localcount = localtype;
258b725ae77Skettenis   else if ((localtype & 0xc0) == 0x80)
259b725ae77Skettenis     localcount = (((localtype & 0x3f) << 8)
260b725ae77Skettenis 		  | (read_memory_integer (enter_pc + 3, 1) & 0xff));
261b725ae77Skettenis   else
262b725ae77Skettenis     localcount = (((localtype & 0x3f) << 24)
263b725ae77Skettenis 		  | ((read_memory_integer (enter_pc + 3, 1) & 0xff) << 16)
264b725ae77Skettenis 		  | ((read_memory_integer (enter_pc + 4, 1) & 0xff) << 8)
265b725ae77Skettenis 		  | (read_memory_integer (enter_pc + 5, 1) & 0xff));
266b725ae77Skettenis   return localcount;
267b725ae77Skettenis }
268b725ae77Skettenis 
269b725ae77Skettenis 
270b725ae77Skettenis /* Nonzero if instruction at PC is a return instruction.  */
271b725ae77Skettenis 
272b725ae77Skettenis static int
ns32k_about_to_return(CORE_ADDR pc)273b725ae77Skettenis ns32k_about_to_return (CORE_ADDR pc)
274b725ae77Skettenis {
275b725ae77Skettenis   return (read_memory_integer (pc, 1) == 0x12);
276b725ae77Skettenis }
277b725ae77Skettenis 
278b725ae77Skettenis /* Get the address of the enter opcode for this function, if it is active.
279b725ae77Skettenis    Returns positive address > 1 if pc is between enter/exit,
280b725ae77Skettenis    1 if pc before enter or after exit, 0 otherwise. */
281b725ae77Skettenis static CORE_ADDR
ns32k_get_enter_addr(CORE_ADDR pc)282b725ae77Skettenis ns32k_get_enter_addr (CORE_ADDR pc)
283b725ae77Skettenis {
284b725ae77Skettenis   CORE_ADDR enter_addr;
285b725ae77Skettenis   unsigned char op;
286b725ae77Skettenis 
287b725ae77Skettenis   if (pc == 0)
288b725ae77Skettenis     return 0;
289b725ae77Skettenis 
290b725ae77Skettenis   if (ns32k_about_to_return (pc))
291b725ae77Skettenis     return 1;			/* after exit */
292b725ae77Skettenis 
293b725ae77Skettenis   enter_addr = get_pc_function_start (pc);
294b725ae77Skettenis 
295b725ae77Skettenis   if (pc == enter_addr)
296b725ae77Skettenis     return 1;			/* before enter */
297b725ae77Skettenis 
298b725ae77Skettenis   op = read_memory_integer (enter_addr, 1);
299b725ae77Skettenis 
300b725ae77Skettenis   if (op != 0x82)
301b725ae77Skettenis     return 0;			/* function has no enter/exit */
302b725ae77Skettenis 
303b725ae77Skettenis   return enter_addr;		/* pc is between enter and exit */
304b725ae77Skettenis }
305b725ae77Skettenis 
306b725ae77Skettenis static CORE_ADDR
ns32k_frame_chain(struct frame_info * frame)307b725ae77Skettenis ns32k_frame_chain (struct frame_info *frame)
308b725ae77Skettenis {
309b725ae77Skettenis   /* In the case of the NS32000 series, the frame's nominal address is the
310b725ae77Skettenis      FP value, and that address is saved at the previous FP value as a
311b725ae77Skettenis      4-byte word.  */
312b725ae77Skettenis   return (read_memory_integer (get_frame_base (frame), 4));
313b725ae77Skettenis }
314b725ae77Skettenis 
315b725ae77Skettenis 
316b725ae77Skettenis static CORE_ADDR
ns32k_sigtramp_saved_pc(struct frame_info * frame)317b725ae77Skettenis ns32k_sigtramp_saved_pc (struct frame_info *frame)
318b725ae77Skettenis {
319b725ae77Skettenis   CORE_ADDR sigcontext_addr;
320b725ae77Skettenis   char *buf;
321b725ae77Skettenis   int ptrbytes = TYPE_LENGTH (builtin_type_void_func_ptr);
322b725ae77Skettenis   int sigcontext_offs = (2 * TARGET_INT_BIT) / TARGET_CHAR_BIT;
323b725ae77Skettenis 
324b725ae77Skettenis   buf = alloca (ptrbytes);
325b725ae77Skettenis   /* Get sigcontext address, it is the third parameter on the stack.  */
326b725ae77Skettenis   if (get_next_frame (frame))
327b725ae77Skettenis     sigcontext_addr = read_memory_typed_address
328b725ae77Skettenis       (DEPRECATED_FRAME_ARGS_ADDRESS (get_next_frame (frame)) + FRAME_ARGS_SKIP + sigcontext_offs,
329b725ae77Skettenis        builtin_type_void_data_ptr);
330b725ae77Skettenis   else
331b725ae77Skettenis     sigcontext_addr = read_memory_typed_address
332b725ae77Skettenis       (read_register (SP_REGNUM) + sigcontext_offs, builtin_type_void_data_ptr);
333b725ae77Skettenis 
334b725ae77Skettenis   /* Offset to saved PC in sigcontext, from <machine/signal.h>.  Don't
335b725ae77Skettenis      cause a memory_error when accessing sigcontext in case the stack
336b725ae77Skettenis      layout has changed or the stack is corrupt.  */
337b725ae77Skettenis   target_read_memory (sigcontext_addr + 20, buf, ptrbytes);
338b725ae77Skettenis   return extract_typed_address (buf, builtin_type_void_func_ptr);
339b725ae77Skettenis }
340b725ae77Skettenis 
341b725ae77Skettenis static CORE_ADDR
ns32k_frame_saved_pc(struct frame_info * frame)342b725ae77Skettenis ns32k_frame_saved_pc (struct frame_info *frame)
343b725ae77Skettenis {
344b725ae77Skettenis   if ((get_frame_type (frame) == SIGTRAMP_FRAME))
345b725ae77Skettenis     return (ns32k_sigtramp_saved_pc (frame)); /* XXXJRT */
346b725ae77Skettenis 
347b725ae77Skettenis   return (read_memory_integer (get_frame_base (frame) + 4, 4));
348b725ae77Skettenis }
349b725ae77Skettenis 
350b725ae77Skettenis static CORE_ADDR
ns32k_frame_args_address(struct frame_info * frame)351b725ae77Skettenis ns32k_frame_args_address (struct frame_info *frame)
352b725ae77Skettenis {
353b725ae77Skettenis   if (ns32k_get_enter_addr (get_frame_pc (frame)) > 1)
354b725ae77Skettenis     return (get_frame_base (frame));
355b725ae77Skettenis 
356b725ae77Skettenis   return (read_register (SP_REGNUM) - 4);
357b725ae77Skettenis }
358b725ae77Skettenis 
359b725ae77Skettenis /* Code to initialize the addresses of the saved registers of frame described
360b725ae77Skettenis    by FRAME_INFO.  This includes special registers such as pc and fp saved in
361b725ae77Skettenis    special ways in the stack frame.  sp is even more special: the address we
362b725ae77Skettenis    return for it IS the sp for the next frame.  */
363b725ae77Skettenis 
364b725ae77Skettenis static void
ns32k_frame_init_saved_regs(struct frame_info * frame)365b725ae77Skettenis ns32k_frame_init_saved_regs (struct frame_info *frame)
366b725ae77Skettenis {
367b725ae77Skettenis   int regmask, regnum;
368b725ae77Skettenis   int localcount;
369b725ae77Skettenis   CORE_ADDR enter_addr, next_addr;
370b725ae77Skettenis 
371b725ae77Skettenis   if (deprecated_get_frame_saved_regs (frame))
372b725ae77Skettenis     return;
373b725ae77Skettenis 
374b725ae77Skettenis   frame_saved_regs_zalloc (frame);
375b725ae77Skettenis 
376b725ae77Skettenis   enter_addr = ns32k_get_enter_addr (get_frame_pc (frame));
377b725ae77Skettenis   if (enter_addr > 1)
378b725ae77Skettenis     {
379b725ae77Skettenis       regmask = read_memory_integer (enter_addr + 1, 1) & 0xff;
380b725ae77Skettenis       localcount = ns32k_localcount (enter_addr);
381b725ae77Skettenis       next_addr = get_frame_base (frame) + localcount;
382b725ae77Skettenis 
383b725ae77Skettenis       for (regnum = 0; regnum < 8; regnum++)
384b725ae77Skettenis 	{
385b725ae77Skettenis           if (regmask & (1 << regnum))
386b725ae77Skettenis 	    deprecated_get_frame_saved_regs (frame)[regnum] = next_addr -= 4;
387b725ae77Skettenis 	}
388b725ae77Skettenis 
389b725ae77Skettenis       deprecated_get_frame_saved_regs (frame)[SP_REGNUM] = get_frame_base (frame) + 4;
390b725ae77Skettenis       deprecated_get_frame_saved_regs (frame)[PC_REGNUM] = get_frame_base (frame) + 4;
391b725ae77Skettenis       deprecated_get_frame_saved_regs (frame)[DEPRECATED_FP_REGNUM] = read_memory_integer (get_frame_base (frame), 4);
392b725ae77Skettenis     }
393b725ae77Skettenis   else if (enter_addr == 1)
394b725ae77Skettenis     {
395b725ae77Skettenis       CORE_ADDR sp = read_register (SP_REGNUM);
396b725ae77Skettenis       deprecated_get_frame_saved_regs (frame)[PC_REGNUM] = sp;
397b725ae77Skettenis       deprecated_get_frame_saved_regs (frame)[SP_REGNUM] = sp + 4;
398b725ae77Skettenis     }
399b725ae77Skettenis }
400b725ae77Skettenis 
401b725ae77Skettenis static void
ns32k_pop_frame(void)402b725ae77Skettenis ns32k_pop_frame (void)
403b725ae77Skettenis {
404b725ae77Skettenis   struct frame_info *frame = get_current_frame ();
405b725ae77Skettenis   CORE_ADDR fp;
406b725ae77Skettenis   int regnum;
407b725ae77Skettenis 
408b725ae77Skettenis   fp = get_frame_base (frame);
409b725ae77Skettenis   DEPRECATED_FRAME_INIT_SAVED_REGS (frame);
410b725ae77Skettenis 
411b725ae77Skettenis   for (regnum = 0; regnum < 8; regnum++)
412b725ae77Skettenis     if (deprecated_get_frame_saved_regs (frame)[regnum])
413b725ae77Skettenis       write_register (regnum,
414b725ae77Skettenis 		      read_memory_integer (deprecated_get_frame_saved_regs (frame)[regnum], 4));
415b725ae77Skettenis 
416b725ae77Skettenis   write_register (DEPRECATED_FP_REGNUM, read_memory_integer (fp, 4));
417b725ae77Skettenis   write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
418b725ae77Skettenis   write_register (SP_REGNUM, fp + 8);
419b725ae77Skettenis   flush_cached_frames ();
420b725ae77Skettenis }
421b725ae77Skettenis 
422*63addd46Skettenis static CORE_ADDR
ns32k_push_arguments(int nargs,struct value ** args,CORE_ADDR sp,int struct_return,CORE_ADDR struct_addr)423*63addd46Skettenis ns32k_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
424*63addd46Skettenis 		      int struct_return, CORE_ADDR struct_addr)
425b725ae77Skettenis {
426*63addd46Skettenis   /* ASSERT ( !struct_return); */
427*63addd46Skettenis   int i;
428*63addd46Skettenis   for (i = nargs - 1; i >= 0; i--)
429b725ae77Skettenis     {
430*63addd46Skettenis       struct value *arg = args[i];
431*63addd46Skettenis       int len = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg));
432*63addd46Skettenis       int container_len = len;
433*63addd46Skettenis       int offset;
434b725ae77Skettenis 
435*63addd46Skettenis       /* Are we going to put it at the high or low end of the
436*63addd46Skettenis 	 container?  */
437*63addd46Skettenis       if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
438*63addd46Skettenis 	offset = container_len - len;
439*63addd46Skettenis       else
440*63addd46Skettenis 	offset = 0;
441b725ae77Skettenis 
442*63addd46Skettenis       /* Stack grows downward.  */
443*63addd46Skettenis       sp -= container_len;
444*63addd46Skettenis       write_memory (sp + offset, VALUE_CONTENTS_ALL (arg), len);
445b725ae77Skettenis     }
446*63addd46Skettenis   return sp;
447*63addd46Skettenis }
448*63addd46Skettenis 
449b725ae77Skettenis 
450b725ae77Skettenis static void
ns32k_store_struct_return(CORE_ADDR addr,CORE_ADDR sp)451b725ae77Skettenis ns32k_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
452b725ae77Skettenis {
453b725ae77Skettenis   /* On this machine, this is a no-op (Encore Umax didn't use GCC).  */
454b725ae77Skettenis }
455b725ae77Skettenis 
456b725ae77Skettenis static void
ns32k_extract_return_value(struct type * valtype,char * regbuf,char * valbuf)457b725ae77Skettenis ns32k_extract_return_value (struct type *valtype, char *regbuf, char *valbuf)
458b725ae77Skettenis {
459b725ae77Skettenis   memcpy (valbuf,
460b725ae77Skettenis           regbuf + DEPRECATED_REGISTER_BYTE (TYPE_CODE (valtype) == TYPE_CODE_FLT ?
461b725ae77Skettenis 				  FP0_REGNUM : 0), TYPE_LENGTH (valtype));
462b725ae77Skettenis }
463b725ae77Skettenis 
464b725ae77Skettenis static void
ns32k_store_return_value(struct type * valtype,char * valbuf)465b725ae77Skettenis ns32k_store_return_value (struct type *valtype, char *valbuf)
466b725ae77Skettenis {
467b725ae77Skettenis   deprecated_write_register_bytes (TYPE_CODE (valtype) == TYPE_CODE_FLT
468b725ae77Skettenis 				   ? FP0_REGNUM : 0, valbuf,
469b725ae77Skettenis 				   TYPE_LENGTH (valtype));
470b725ae77Skettenis }
471e93f7393Sniklas 
472e93f7393Sniklas void
ns32k_gdbarch_init_32082(struct gdbarch * gdbarch)473b725ae77Skettenis ns32k_gdbarch_init_32082 (struct gdbarch *gdbarch)
474e93f7393Sniklas {
475b725ae77Skettenis   set_gdbarch_num_regs (gdbarch, NS32K_NUM_REGS_32082);
476b725ae77Skettenis 
477b725ae77Skettenis   set_gdbarch_register_name (gdbarch, ns32k_register_name_32082);
478b725ae77Skettenis   set_gdbarch_deprecated_register_byte (gdbarch, ns32k_register_byte_32082);
479b725ae77Skettenis }
480b725ae77Skettenis 
481b725ae77Skettenis void
ns32k_gdbarch_init_32382(struct gdbarch * gdbarch)482b725ae77Skettenis ns32k_gdbarch_init_32382 (struct gdbarch *gdbarch)
483b725ae77Skettenis {
484b725ae77Skettenis   set_gdbarch_num_regs (gdbarch, NS32K_NUM_REGS_32382);
485b725ae77Skettenis 
486b725ae77Skettenis   set_gdbarch_register_name (gdbarch, ns32k_register_name_32382);
487b725ae77Skettenis   set_gdbarch_deprecated_register_byte (gdbarch, ns32k_register_byte_32382);
488b725ae77Skettenis }
489b725ae77Skettenis 
490b725ae77Skettenis /* Initialize the current architecture based on INFO.  If possible, re-use an
491b725ae77Skettenis    architecture from ARCHES, which is a list of architectures already created
492b725ae77Skettenis    during this debugging session.
493b725ae77Skettenis 
494b725ae77Skettenis    Called e.g. at program startup, when reading a core file, and when reading
495b725ae77Skettenis    a binary file.  */
496b725ae77Skettenis 
497b725ae77Skettenis static struct gdbarch *
ns32k_gdbarch_init(struct gdbarch_info info,struct gdbarch_list * arches)498b725ae77Skettenis ns32k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
499b725ae77Skettenis {
500b725ae77Skettenis   struct gdbarch *gdbarch;
501b725ae77Skettenis 
502b725ae77Skettenis   /* If there is already a candidate, use it.  */
503b725ae77Skettenis   arches = gdbarch_list_lookup_by_info (arches, &info);
504b725ae77Skettenis   if (arches != NULL)
505b725ae77Skettenis     return arches->gdbarch;
506b725ae77Skettenis 
507b725ae77Skettenis   gdbarch = gdbarch_alloc (&info, NULL);
508b725ae77Skettenis 
509b725ae77Skettenis   /* NOTE: cagney/2002-12-06: This can be deleted when this arch is
510b725ae77Skettenis      ready to unwind the PC first (see frame.c:get_prev_frame()).  */
511b725ae77Skettenis   set_gdbarch_deprecated_init_frame_pc (gdbarch, deprecated_init_frame_pc_default);
512b725ae77Skettenis 
513b725ae77Skettenis   /* Register info */
514b725ae77Skettenis   ns32k_gdbarch_init_32082 (gdbarch);
515b725ae77Skettenis   set_gdbarch_num_regs (gdbarch, NS32K_SP_REGNUM);
516b725ae77Skettenis   set_gdbarch_num_regs (gdbarch, NS32K_FP_REGNUM);
517b725ae77Skettenis   set_gdbarch_num_regs (gdbarch, NS32K_PC_REGNUM);
518b725ae77Skettenis   set_gdbarch_num_regs (gdbarch, NS32K_PS_REGNUM);
519b725ae77Skettenis 
520b725ae77Skettenis   set_gdbarch_deprecated_register_size (gdbarch, NS32K_REGISTER_SIZE);
521b725ae77Skettenis   set_gdbarch_deprecated_register_raw_size (gdbarch, ns32k_register_raw_size);
522b725ae77Skettenis   set_gdbarch_deprecated_register_virtual_size (gdbarch, ns32k_register_virtual_size);
523b725ae77Skettenis   set_gdbarch_deprecated_register_virtual_type (gdbarch, ns32k_register_virtual_type);
524b725ae77Skettenis 
525b725ae77Skettenis   /* Frame and stack info */
526b725ae77Skettenis   set_gdbarch_skip_prologue (gdbarch, umax_skip_prologue);
527b725ae77Skettenis   set_gdbarch_deprecated_saved_pc_after_call (gdbarch, ns32k_saved_pc_after_call);
528b725ae77Skettenis 
529b725ae77Skettenis   set_gdbarch_frame_num_args (gdbarch, umax_frame_num_args);
530b725ae77Skettenis 
531b725ae77Skettenis   set_gdbarch_deprecated_frame_chain (gdbarch, ns32k_frame_chain);
532b725ae77Skettenis   set_gdbarch_deprecated_frame_saved_pc (gdbarch, ns32k_frame_saved_pc);
533b725ae77Skettenis 
534b725ae77Skettenis   set_gdbarch_deprecated_frame_args_address (gdbarch, ns32k_frame_args_address);
535b725ae77Skettenis 
536b725ae77Skettenis   set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, ns32k_frame_init_saved_regs);
537b725ae77Skettenis 
538b725ae77Skettenis   set_gdbarch_frame_args_skip (gdbarch, 8);
539b725ae77Skettenis 
540b725ae77Skettenis   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
541b725ae77Skettenis 
542b725ae77Skettenis   /* Return value info */
543b725ae77Skettenis   set_gdbarch_deprecated_store_struct_return (gdbarch, ns32k_store_struct_return);
544b725ae77Skettenis   set_gdbarch_deprecated_extract_return_value (gdbarch, ns32k_extract_return_value);
545b725ae77Skettenis   set_gdbarch_deprecated_store_return_value (gdbarch, ns32k_store_return_value);
546b725ae77Skettenis 
547b725ae77Skettenis   /* Call dummy info */
548b725ae77Skettenis   set_gdbarch_deprecated_pop_frame (gdbarch, ns32k_pop_frame);
549b725ae77Skettenis   set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
550*63addd46Skettenis   set_gdbarch_deprecated_push_arguments (gdbarch, ns32k_push_arguments);
551b725ae77Skettenis 
552b725ae77Skettenis   /* Breakpoint info */
553b725ae77Skettenis   set_gdbarch_breakpoint_from_pc (gdbarch, ns32k_breakpoint_from_pc);
554b725ae77Skettenis 
555b725ae77Skettenis   /* Should be using push_dummy_call.  */
556b725ae77Skettenis   set_gdbarch_deprecated_dummy_write_sp (gdbarch, deprecated_write_sp);
557b725ae77Skettenis 
558b725ae77Skettenis   set_gdbarch_print_insn (gdbarch, print_insn_ns32k);
559b725ae77Skettenis 
560b725ae77Skettenis   /* Hook in OS ABI-specific overrides, if they have been registered.  */
561b725ae77Skettenis   gdbarch_init_osabi (info, gdbarch);
562b725ae77Skettenis 
563b725ae77Skettenis   return (gdbarch);
564b725ae77Skettenis }
565b725ae77Skettenis 
566b725ae77Skettenis extern initialize_file_ftype _initialize_ns32k_tdep; /* -Wmissing-prototypes */
567b725ae77Skettenis 
568b725ae77Skettenis void
_initialize_ns32k_tdep(void)569b725ae77Skettenis _initialize_ns32k_tdep (void)
570b725ae77Skettenis {
571b725ae77Skettenis   gdbarch_register (bfd_arch_ns32k, ns32k_gdbarch_init, NULL);
572b725ae77Skettenis 
573e93f7393Sniklas }
574