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