xref: /openbsd-src/gnu/usr.bin/binutils/gdb/v850-tdep.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
1b725ae77Skettenis /* Target-dependent code for the NEC V850 for GDB, the GNU debugger.
2b725ae77Skettenis 
3b725ae77Skettenis    Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free
4b725ae77Skettenis    Software Foundation, Inc.
5b725ae77Skettenis 
6b725ae77Skettenis    This file is part of GDB.
7b725ae77Skettenis 
8b725ae77Skettenis    This program is free software; you can redistribute it and/or modify
9b725ae77Skettenis    it under the terms of the GNU General Public License as published by
10b725ae77Skettenis    the Free Software Foundation; either version 2 of the License, or
11b725ae77Skettenis    (at your option) any later version.
12b725ae77Skettenis 
13b725ae77Skettenis    This program is distributed in the hope that it will be useful,
14b725ae77Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
15b725ae77Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16b725ae77Skettenis    GNU General Public License for more details.
17b725ae77Skettenis 
18b725ae77Skettenis    You should have received a copy of the GNU General Public License
19b725ae77Skettenis    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.  */
22b725ae77Skettenis 
23b725ae77Skettenis #include "defs.h"
24b725ae77Skettenis #include "frame.h"
25b725ae77Skettenis #include "inferior.h"
26b725ae77Skettenis #include "target.h"
27b725ae77Skettenis #include "value.h"
28b725ae77Skettenis #include "bfd.h"
29b725ae77Skettenis #include "gdb_string.h"
30b725ae77Skettenis #include "gdbcore.h"
31b725ae77Skettenis #include "objfiles.h"
32b725ae77Skettenis #include "arch-utils.h"
33b725ae77Skettenis #include "regcache.h"
34b725ae77Skettenis #include "symtab.h"
35b725ae77Skettenis #include "dis-asm.h"
36b725ae77Skettenis 
37b725ae77Skettenis struct gdbarch_tdep
38b725ae77Skettenis {
39b725ae77Skettenis   /* gdbarch target dependent data here. Currently unused for v850. */
40b725ae77Skettenis };
41b725ae77Skettenis 
42b725ae77Skettenis /* Extra info which is saved in each frame_info. */
43b725ae77Skettenis struct frame_extra_info
44b725ae77Skettenis {
45b725ae77Skettenis };
46b725ae77Skettenis 
47b725ae77Skettenis enum {
48b725ae77Skettenis  E_R0_REGNUM,
49b725ae77Skettenis  E_R1_REGNUM,
50b725ae77Skettenis  E_R2_REGNUM, E_SAVE1_START_REGNUM = E_R2_REGNUM, E_SAVE1_END_REGNUM = E_R2_REGNUM,
51b725ae77Skettenis  E_R3_REGNUM, E_SP_REGNUM = E_R3_REGNUM,
52b725ae77Skettenis  E_R4_REGNUM,
53b725ae77Skettenis  E_R5_REGNUM,
54b725ae77Skettenis  E_R6_REGNUM, E_ARG0_REGNUM = E_R6_REGNUM,
55b725ae77Skettenis  E_R7_REGNUM,
56b725ae77Skettenis  E_R8_REGNUM,
57b725ae77Skettenis  E_R9_REGNUM, E_ARGLAST_REGNUM = E_R9_REGNUM,
58b725ae77Skettenis  E_R10_REGNUM, E_V0_REGNUM = E_R10_REGNUM,
59b725ae77Skettenis  E_R11_REGNUM, E_V1_REGNUM = E_R11_REGNUM,
60b725ae77Skettenis  E_R12_REGNUM,
61b725ae77Skettenis  E_R13_REGNUM,
62b725ae77Skettenis  E_R14_REGNUM,
63b725ae77Skettenis  E_R15_REGNUM,
64b725ae77Skettenis  E_R16_REGNUM,
65b725ae77Skettenis  E_R17_REGNUM,
66b725ae77Skettenis  E_R18_REGNUM,
67b725ae77Skettenis  E_R19_REGNUM,
68b725ae77Skettenis  E_R20_REGNUM, E_SAVE2_START_REGNUM = E_R20_REGNUM,
69b725ae77Skettenis  E_R21_REGNUM,
70b725ae77Skettenis  E_R22_REGNUM,
71b725ae77Skettenis  E_R23_REGNUM,
72b725ae77Skettenis  E_R24_REGNUM,
73b725ae77Skettenis  E_R25_REGNUM,
74b725ae77Skettenis  E_R26_REGNUM,
75b725ae77Skettenis  E_R27_REGNUM,
76b725ae77Skettenis  E_R28_REGNUM,
77b725ae77Skettenis  E_R29_REGNUM, E_SAVE2_END_REGNUM = E_R29_REGNUM, E_FP_RAW_REGNUM = E_R29_REGNUM,
78b725ae77Skettenis  E_R30_REGNUM, E_EP_REGNUM = E_R30_REGNUM,
79b725ae77Skettenis  E_R31_REGNUM, E_SAVE3_START_REGNUM = E_R31_REGNUM, E_SAVE3_END_REGNUM = E_R31_REGNUM, E_RP_REGNUM = E_R31_REGNUM,
80b725ae77Skettenis  E_R32_REGNUM, E_SR0_REGNUM = E_R32_REGNUM,
81b725ae77Skettenis  E_R33_REGNUM,
82b725ae77Skettenis  E_R34_REGNUM,
83b725ae77Skettenis  E_R35_REGNUM,
84b725ae77Skettenis  E_R36_REGNUM,
85b725ae77Skettenis  E_R37_REGNUM, E_PS_REGNUM = E_R37_REGNUM,
86b725ae77Skettenis  E_R38_REGNUM,
87b725ae77Skettenis  E_R39_REGNUM,
88b725ae77Skettenis  E_R40_REGNUM,
89b725ae77Skettenis  E_R41_REGNUM,
90b725ae77Skettenis  E_R42_REGNUM,
91b725ae77Skettenis  E_R43_REGNUM,
92b725ae77Skettenis  E_R44_REGNUM,
93b725ae77Skettenis  E_R45_REGNUM,
94b725ae77Skettenis  E_R46_REGNUM,
95b725ae77Skettenis  E_R47_REGNUM,
96b725ae77Skettenis  E_R48_REGNUM,
97b725ae77Skettenis  E_R49_REGNUM,
98b725ae77Skettenis  E_R50_REGNUM,
99b725ae77Skettenis  E_R51_REGNUM,
100b725ae77Skettenis  E_R52_REGNUM, E_CTBP_REGNUM = E_R52_REGNUM,
101b725ae77Skettenis  E_R53_REGNUM,
102b725ae77Skettenis  E_R54_REGNUM,
103b725ae77Skettenis  E_R55_REGNUM,
104b725ae77Skettenis  E_R56_REGNUM,
105b725ae77Skettenis  E_R57_REGNUM,
106b725ae77Skettenis  E_R58_REGNUM,
107b725ae77Skettenis  E_R59_REGNUM,
108b725ae77Skettenis  E_R60_REGNUM,
109b725ae77Skettenis  E_R61_REGNUM,
110b725ae77Skettenis  E_R62_REGNUM,
111b725ae77Skettenis  E_R63_REGNUM,
112b725ae77Skettenis  E_R64_REGNUM, E_PC_REGNUM = E_R64_REGNUM,
113b725ae77Skettenis  E_R65_REGNUM, E_FP_REGNUM = E_R65_REGNUM,
114b725ae77Skettenis  E_NUM_REGS
115b725ae77Skettenis };
116b725ae77Skettenis 
117b725ae77Skettenis enum
118b725ae77Skettenis {
119b725ae77Skettenis   v850_reg_size = 4
120b725ae77Skettenis };
121b725ae77Skettenis 
122b725ae77Skettenis /* Size of all registers as a whole. */
123b725ae77Skettenis enum
124b725ae77Skettenis {
125b725ae77Skettenis   E_ALL_REGS_SIZE = (E_NUM_REGS) * v850_reg_size
126b725ae77Skettenis };
127b725ae77Skettenis 
128b725ae77Skettenis /* Size of return datatype which fits into all return registers. */
129b725ae77Skettenis enum
130b725ae77Skettenis {
131b725ae77Skettenis   E_MAX_RETTYPE_SIZE_IN_REGS = 2 * v850_reg_size
132b725ae77Skettenis };
133b725ae77Skettenis 
134b725ae77Skettenis static LONGEST call_dummy_nil[] = {0};
135b725ae77Skettenis 
136b725ae77Skettenis static char *v850_generic_reg_names[] =
137b725ae77Skettenis { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
138b725ae77Skettenis   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
139b725ae77Skettenis   "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
140b725ae77Skettenis   "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
141b725ae77Skettenis   "eipc", "eipsw", "fepc", "fepsw", "ecr", "psw", "sr6", "sr7",
142b725ae77Skettenis   "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15",
143b725ae77Skettenis   "sr16", "sr17", "sr18", "sr19", "sr20", "sr21", "sr22", "sr23",
144b725ae77Skettenis   "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31",
145b725ae77Skettenis   "pc", "fp"
146b725ae77Skettenis };
147b725ae77Skettenis 
148b725ae77Skettenis static char *v850e_reg_names[] =
149b725ae77Skettenis {
150b725ae77Skettenis   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
151b725ae77Skettenis   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
152b725ae77Skettenis   "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
153b725ae77Skettenis   "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
154b725ae77Skettenis   "eipc", "eipsw", "fepc", "fepsw", "ecr", "psw", "sr6", "sr7",
155b725ae77Skettenis   "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15",
156b725ae77Skettenis   "ctpc", "ctpsw", "dbpc", "dbpsw", "ctbp", "sr21", "sr22", "sr23",
157b725ae77Skettenis   "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31",
158b725ae77Skettenis   "pc", "fp"
159b725ae77Skettenis };
160b725ae77Skettenis 
161b725ae77Skettenis char **v850_register_names = v850_generic_reg_names;
162b725ae77Skettenis 
163b725ae77Skettenis struct
164b725ae77Skettenis   {
165b725ae77Skettenis     char **regnames;
166b725ae77Skettenis     int mach;
167b725ae77Skettenis   }
168b725ae77Skettenis v850_processor_type_table[] =
169b725ae77Skettenis {
170b725ae77Skettenis   {
171b725ae77Skettenis     v850_generic_reg_names, bfd_mach_v850
172b725ae77Skettenis   }
173b725ae77Skettenis   ,
174b725ae77Skettenis   {
175b725ae77Skettenis     v850e_reg_names, bfd_mach_v850e
176b725ae77Skettenis   }
177b725ae77Skettenis   ,
178b725ae77Skettenis   {
179b725ae77Skettenis     v850e_reg_names, bfd_mach_v850e1
180b725ae77Skettenis   }
181b725ae77Skettenis   ,
182b725ae77Skettenis   {
183b725ae77Skettenis     NULL, 0
184b725ae77Skettenis   }
185b725ae77Skettenis };
186b725ae77Skettenis 
187b725ae77Skettenis /* Info gleaned from scanning a function's prologue.  */
188b725ae77Skettenis 
189b725ae77Skettenis struct pifsr			/* Info about one saved reg */
190b725ae77Skettenis   {
191b725ae77Skettenis     int framereg;		/* Frame reg (SP or FP) */
192b725ae77Skettenis     int offset;			/* Offset from framereg */
193b725ae77Skettenis     int cur_frameoffset;	/* Current frameoffset */
194b725ae77Skettenis     int reg;			/* Saved register number */
195b725ae77Skettenis   };
196b725ae77Skettenis 
197b725ae77Skettenis struct prologue_info
198b725ae77Skettenis   {
199b725ae77Skettenis     int framereg;
200b725ae77Skettenis     int frameoffset;
201b725ae77Skettenis     int start_function;
202b725ae77Skettenis     struct pifsr *pifsrs;
203b725ae77Skettenis   };
204b725ae77Skettenis 
205b725ae77Skettenis static CORE_ADDR v850_scan_prologue (CORE_ADDR pc, struct prologue_info *fs);
206b725ae77Skettenis 
207b725ae77Skettenis /* Function: v850_register_name
208b725ae77Skettenis    Returns the name of the v850/v850e register N. */
209b725ae77Skettenis 
210b725ae77Skettenis static const char *
v850_register_name(int regnum)211b725ae77Skettenis v850_register_name (int regnum)
212b725ae77Skettenis {
213b725ae77Skettenis   if (regnum < 0 || regnum >= E_NUM_REGS)
214b725ae77Skettenis     internal_error (__FILE__, __LINE__,
215b725ae77Skettenis                     "v850_register_name: illegal register number %d",
216b725ae77Skettenis                     regnum);
217b725ae77Skettenis   else
218b725ae77Skettenis     return v850_register_names[regnum];
219b725ae77Skettenis 
220b725ae77Skettenis }
221b725ae77Skettenis 
222b725ae77Skettenis /* Function: v850_register_byte
223b725ae77Skettenis    Returns the byte position in the register cache for register N. */
224b725ae77Skettenis 
225b725ae77Skettenis static int
v850_register_byte(int regnum)226b725ae77Skettenis v850_register_byte (int regnum)
227b725ae77Skettenis {
228b725ae77Skettenis   if (regnum < 0 || regnum >= E_NUM_REGS)
229b725ae77Skettenis     internal_error (__FILE__, __LINE__,
230b725ae77Skettenis                     "v850_register_byte: illegal register number %d",
231b725ae77Skettenis                     regnum);
232b725ae77Skettenis   else
233b725ae77Skettenis     return regnum * v850_reg_size;
234b725ae77Skettenis }
235b725ae77Skettenis 
236b725ae77Skettenis /* Function: v850_register_raw_size
237b725ae77Skettenis    Returns the number of bytes occupied by the register on the target. */
238b725ae77Skettenis 
239b725ae77Skettenis static int
v850_register_raw_size(int regnum)240b725ae77Skettenis v850_register_raw_size (int regnum)
241b725ae77Skettenis {
242b725ae77Skettenis   if (regnum < 0 || regnum >= E_NUM_REGS)
243b725ae77Skettenis     internal_error (__FILE__, __LINE__,
244b725ae77Skettenis                     "v850_register_raw_size: illegal register number %d",
245b725ae77Skettenis                     regnum);
246b725ae77Skettenis   /* Only the PC has 4 Byte, all other registers 2 Byte. */
247b725ae77Skettenis   else
248b725ae77Skettenis     return v850_reg_size;
249b725ae77Skettenis }
250b725ae77Skettenis 
251b725ae77Skettenis /* Function: v850_reg_virtual_type
252b725ae77Skettenis    Returns the default type for register N. */
253b725ae77Skettenis 
254b725ae77Skettenis static struct type *
v850_reg_virtual_type(int regnum)255b725ae77Skettenis v850_reg_virtual_type (int regnum)
256b725ae77Skettenis {
257b725ae77Skettenis   if (regnum < 0 || regnum >= E_NUM_REGS)
258b725ae77Skettenis     internal_error (__FILE__, __LINE__,
259b725ae77Skettenis                     "v850_register_virtual_type: illegal register number %d",
260b725ae77Skettenis                     regnum);
261b725ae77Skettenis   else if (regnum == E_PC_REGNUM)
262b725ae77Skettenis     return builtin_type_uint32;
263b725ae77Skettenis   else
264b725ae77Skettenis     return builtin_type_int32;
265b725ae77Skettenis }
266b725ae77Skettenis 
267b725ae77Skettenis static int
v850_type_is_scalar(struct type * t)268b725ae77Skettenis v850_type_is_scalar (struct type *t)
269b725ae77Skettenis {
270b725ae77Skettenis   return (TYPE_CODE (t) != TYPE_CODE_STRUCT
271b725ae77Skettenis 	  && TYPE_CODE (t) != TYPE_CODE_UNION
272b725ae77Skettenis 	  && TYPE_CODE (t) != TYPE_CODE_ARRAY);
273b725ae77Skettenis }
274b725ae77Skettenis 
275b725ae77Skettenis /* Should call_function allocate stack space for a struct return?  */
276b725ae77Skettenis static int
v850_use_struct_convention(int gcc_p,struct type * type)277b725ae77Skettenis v850_use_struct_convention (int gcc_p, struct type *type)
278b725ae77Skettenis {
279b725ae77Skettenis   /* According to ABI:
280b725ae77Skettenis    * return TYPE_LENGTH (type) > 8);
281b725ae77Skettenis    */
282b725ae77Skettenis 
283b725ae77Skettenis   /* Current implementation in gcc: */
284b725ae77Skettenis 
285b725ae77Skettenis   int i;
286b725ae77Skettenis   struct type *fld_type, *tgt_type;
287b725ae77Skettenis 
288b725ae77Skettenis   /* 1. The value is greater than 8 bytes -> returned by copying */
289b725ae77Skettenis   if (TYPE_LENGTH (type) > 8)
290b725ae77Skettenis     return 1;
291b725ae77Skettenis 
292b725ae77Skettenis   /* 2. The value is a single basic type -> returned in register */
293b725ae77Skettenis   if (v850_type_is_scalar (type))
294b725ae77Skettenis     return 0;
295b725ae77Skettenis 
296b725ae77Skettenis   /* The value is a structure or union with a single element
297b725ae77Skettenis    * and that element is either a single basic type or an array of
298b725ae77Skettenis    * a single basic type whoes size is greater than or equal to 4
299b725ae77Skettenis    * -> returned in register */
300b725ae77Skettenis   if ((TYPE_CODE (type) == TYPE_CODE_STRUCT
301b725ae77Skettenis        || TYPE_CODE (type) == TYPE_CODE_UNION)
302b725ae77Skettenis        && TYPE_NFIELDS (type) == 1)
303b725ae77Skettenis     {
304b725ae77Skettenis       fld_type = TYPE_FIELD_TYPE (type, 0);
305b725ae77Skettenis       if (v850_type_is_scalar (fld_type) && TYPE_LENGTH (fld_type) >= 4)
306b725ae77Skettenis 	return 0;
307b725ae77Skettenis 
308b725ae77Skettenis       if (TYPE_CODE (fld_type) == TYPE_CODE_ARRAY)
309b725ae77Skettenis         {
310b725ae77Skettenis 	  tgt_type = TYPE_TARGET_TYPE (fld_type);
311b725ae77Skettenis 	  if (v850_type_is_scalar (tgt_type) && TYPE_LENGTH (tgt_type) >= 4)
312b725ae77Skettenis 	    return 0;
313b725ae77Skettenis 	}
314b725ae77Skettenis     }
315b725ae77Skettenis 
316b725ae77Skettenis   /* The value is a structure whose first element is an integer or
317b725ae77Skettenis    * a float, and which contains no arrays of more than two elements
318b725ae77Skettenis    * -> returned in register */
319b725ae77Skettenis   if (TYPE_CODE (type) == TYPE_CODE_STRUCT
320b725ae77Skettenis       && v850_type_is_scalar (TYPE_FIELD_TYPE (type, 0))
321b725ae77Skettenis       && TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)) == 4)
322b725ae77Skettenis     {
323b725ae77Skettenis       for (i = 1; i < TYPE_NFIELDS (type); ++i)
324b725ae77Skettenis         {
325b725ae77Skettenis 	  fld_type = TYPE_FIELD_TYPE (type, 0);
326b725ae77Skettenis 	  if (TYPE_CODE (fld_type) == TYPE_CODE_ARRAY)
327b725ae77Skettenis 	    {
328b725ae77Skettenis 	      tgt_type = TYPE_TARGET_TYPE (fld_type);
329b725ae77Skettenis 	      if (TYPE_LENGTH (fld_type) >= 0 && TYPE_LENGTH (tgt_type) >= 0
330b725ae77Skettenis 		  && TYPE_LENGTH (fld_type) / TYPE_LENGTH (tgt_type) > 2)
331b725ae77Skettenis 		return 1;
332b725ae77Skettenis 	    }
333b725ae77Skettenis 	}
334b725ae77Skettenis       return 0;
335b725ae77Skettenis     }
336b725ae77Skettenis 
337b725ae77Skettenis   /* The value is a union which contains at least one field which
338b725ae77Skettenis    * would be returned in registers according to these rules
339b725ae77Skettenis    * -> returned in register */
340b725ae77Skettenis   if (TYPE_CODE (type) == TYPE_CODE_UNION)
341b725ae77Skettenis     {
342b725ae77Skettenis       for (i = 0; i < TYPE_NFIELDS (type); ++i)
343b725ae77Skettenis         {
344b725ae77Skettenis 	  fld_type = TYPE_FIELD_TYPE (type, 0);
345b725ae77Skettenis 	  if (!v850_use_struct_convention (0, fld_type))
346b725ae77Skettenis 	    return 0;
347b725ae77Skettenis 	}
348b725ae77Skettenis     }
349b725ae77Skettenis 
350b725ae77Skettenis   return 1;
351b725ae77Skettenis }
352b725ae77Skettenis 
353b725ae77Skettenis 
354b725ae77Skettenis 
355b725ae77Skettenis /* Structure for mapping bits in register lists to register numbers. */
356b725ae77Skettenis struct reg_list
357b725ae77Skettenis {
358b725ae77Skettenis   long mask;
359b725ae77Skettenis   int regno;
360b725ae77Skettenis };
361b725ae77Skettenis 
362b725ae77Skettenis /* Helper function for v850_scan_prologue to handle prepare instruction. */
363b725ae77Skettenis 
364b725ae77Skettenis static void
handle_prepare(int insn,int insn2,CORE_ADDR * current_pc_ptr,struct prologue_info * pi,struct pifsr ** pifsr_ptr)365b725ae77Skettenis handle_prepare (int insn, int insn2, CORE_ADDR * current_pc_ptr,
366b725ae77Skettenis 		struct prologue_info *pi, struct pifsr **pifsr_ptr)
367b725ae77Skettenis {
368b725ae77Skettenis   CORE_ADDR current_pc = *current_pc_ptr;
369b725ae77Skettenis   struct pifsr *pifsr = *pifsr_ptr;
370b725ae77Skettenis   long next = insn2 & 0xffff;
371b725ae77Skettenis   long list12 = ((insn & 1) << 16) + (next & 0xffe0);
372b725ae77Skettenis   long offset = (insn & 0x3e) << 1;
373b725ae77Skettenis   static struct reg_list reg_table[] =
374b725ae77Skettenis   {
375b725ae77Skettenis     {0x00800, 20},		/* r20 */
376b725ae77Skettenis     {0x00400, 21},		/* r21 */
377b725ae77Skettenis     {0x00200, 22},		/* r22 */
378b725ae77Skettenis     {0x00100, 23},		/* r23 */
379b725ae77Skettenis     {0x08000, 24},		/* r24 */
380b725ae77Skettenis     {0x04000, 25},		/* r25 */
381b725ae77Skettenis     {0x02000, 26},		/* r26 */
382b725ae77Skettenis     {0x01000, 27},		/* r27 */
383b725ae77Skettenis     {0x00080, 28},		/* r28 */
384b725ae77Skettenis     {0x00040, 29},		/* r29 */
385b725ae77Skettenis     {0x10000, 30},		/* ep */
386b725ae77Skettenis     {0x00020, 31},		/* lp */
387b725ae77Skettenis     {0, 0}			/* end of table */
388b725ae77Skettenis   };
389b725ae77Skettenis   int i;
390b725ae77Skettenis 
391b725ae77Skettenis   if ((next & 0x1f) == 0x0b)	/* skip imm16 argument */
392b725ae77Skettenis     current_pc += 2;
393b725ae77Skettenis   else if ((next & 0x1f) == 0x13)	/* skip imm16 argument */
394b725ae77Skettenis     current_pc += 2;
395b725ae77Skettenis   else if ((next & 0x1f) == 0x1b)	/* skip imm32 argument */
396b725ae77Skettenis     current_pc += 4;
397b725ae77Skettenis 
398b725ae77Skettenis   /* Calculate the total size of the saved registers, and add it
399b725ae77Skettenis      it to the immediate value used to adjust SP. */
400b725ae77Skettenis   for (i = 0; reg_table[i].mask != 0; i++)
401b725ae77Skettenis     if (list12 & reg_table[i].mask)
402b725ae77Skettenis       offset += v850_register_raw_size (reg_table[i].regno);
403b725ae77Skettenis   pi->frameoffset -= offset;
404b725ae77Skettenis 
405b725ae77Skettenis   /* Calculate the offsets of the registers relative to the value
406b725ae77Skettenis      the SP will have after the registers have been pushed and the
407b725ae77Skettenis      imm5 value has been subtracted from it. */
408b725ae77Skettenis   if (pifsr)
409b725ae77Skettenis     {
410b725ae77Skettenis       for (i = 0; reg_table[i].mask != 0; i++)
411b725ae77Skettenis 	{
412b725ae77Skettenis 	  if (list12 & reg_table[i].mask)
413b725ae77Skettenis 	    {
414b725ae77Skettenis 	      int reg = reg_table[i].regno;
415b725ae77Skettenis 	      offset -= v850_register_raw_size (reg);
416b725ae77Skettenis 	      pifsr->reg = reg;
417b725ae77Skettenis 	      pifsr->offset = offset;
418b725ae77Skettenis 	      pifsr->cur_frameoffset = pi->frameoffset;
419b725ae77Skettenis #ifdef DEBUG
420b725ae77Skettenis 	      printf_filtered ("\tSaved register r%d, offset %d", reg, pifsr->offset);
421b725ae77Skettenis #endif
422b725ae77Skettenis 	      pifsr++;
423b725ae77Skettenis 	    }
424b725ae77Skettenis 	}
425b725ae77Skettenis     }
426b725ae77Skettenis #ifdef DEBUG
427b725ae77Skettenis   printf_filtered ("\tfound ctret after regsave func");
428b725ae77Skettenis #endif
429b725ae77Skettenis 
430b725ae77Skettenis   /* Set result parameters. */
431b725ae77Skettenis   *current_pc_ptr = current_pc;
432b725ae77Skettenis   *pifsr_ptr = pifsr;
433b725ae77Skettenis }
434b725ae77Skettenis 
435b725ae77Skettenis 
436b725ae77Skettenis /* Helper function for v850_scan_prologue to handle pushm/pushl instructions.
437b725ae77Skettenis    FIXME: the SR bit of the register list is not supported; must check
438b725ae77Skettenis    that the compiler does not ever generate this bit. */
439b725ae77Skettenis 
440b725ae77Skettenis static void
handle_pushm(int insn,int insn2,struct prologue_info * pi,struct pifsr ** pifsr_ptr)441b725ae77Skettenis handle_pushm (int insn, int insn2, struct prologue_info *pi,
442b725ae77Skettenis 	      struct pifsr **pifsr_ptr)
443b725ae77Skettenis {
444b725ae77Skettenis   struct pifsr *pifsr = *pifsr_ptr;
445b725ae77Skettenis   long list12 = ((insn & 0x0f) << 16) + (insn2 & 0xfff0);
446b725ae77Skettenis   long offset = 0;
447b725ae77Skettenis   static struct reg_list pushml_reg_table[] =
448b725ae77Skettenis   {
449b725ae77Skettenis     {0x80000, E_PS_REGNUM},	/* PSW */
450b725ae77Skettenis     {0x40000, 1},		/* r1 */
451b725ae77Skettenis     {0x20000, 2},		/* r2 */
452b725ae77Skettenis     {0x10000, 3},		/* r3 */
453b725ae77Skettenis     {0x00800, 4},		/* r4 */
454b725ae77Skettenis     {0x00400, 5},		/* r5 */
455b725ae77Skettenis     {0x00200, 6},		/* r6 */
456b725ae77Skettenis     {0x00100, 7},		/* r7 */
457b725ae77Skettenis     {0x08000, 8},		/* r8 */
458b725ae77Skettenis     {0x04000, 9},		/* r9 */
459b725ae77Skettenis     {0x02000, 10},		/* r10 */
460b725ae77Skettenis     {0x01000, 11},		/* r11 */
461b725ae77Skettenis     {0x00080, 12},		/* r12 */
462b725ae77Skettenis     {0x00040, 13},		/* r13 */
463b725ae77Skettenis     {0x00020, 14},		/* r14 */
464b725ae77Skettenis     {0x00010, 15},		/* r15 */
465b725ae77Skettenis     {0, 0}			/* end of table */
466b725ae77Skettenis   };
467b725ae77Skettenis   static struct reg_list pushmh_reg_table[] =
468b725ae77Skettenis   {
469b725ae77Skettenis     {0x80000, 16},		/* r16 */
470b725ae77Skettenis     {0x40000, 17},		/* r17 */
471b725ae77Skettenis     {0x20000, 18},		/* r18 */
472b725ae77Skettenis     {0x10000, 19},		/* r19 */
473b725ae77Skettenis     {0x00800, 20},		/* r20 */
474b725ae77Skettenis     {0x00400, 21},		/* r21 */
475b725ae77Skettenis     {0x00200, 22},		/* r22 */
476b725ae77Skettenis     {0x00100, 23},		/* r23 */
477b725ae77Skettenis     {0x08000, 24},		/* r24 */
478b725ae77Skettenis     {0x04000, 25},		/* r25 */
479b725ae77Skettenis     {0x02000, 26},		/* r26 */
480b725ae77Skettenis     {0x01000, 27},		/* r27 */
481b725ae77Skettenis     {0x00080, 28},		/* r28 */
482b725ae77Skettenis     {0x00040, 29},		/* r29 */
483b725ae77Skettenis     {0x00010, 30},		/* r30 */
484b725ae77Skettenis     {0x00020, 31},		/* r31 */
485b725ae77Skettenis     {0, 0}			/* end of table */
486b725ae77Skettenis   };
487b725ae77Skettenis   struct reg_list *reg_table;
488b725ae77Skettenis   int i;
489b725ae77Skettenis 
490b725ae77Skettenis   /* Is this a pushml or a pushmh? */
491b725ae77Skettenis   if ((insn2 & 7) == 1)
492b725ae77Skettenis     reg_table = pushml_reg_table;
493b725ae77Skettenis   else
494b725ae77Skettenis     reg_table = pushmh_reg_table;
495b725ae77Skettenis 
496b725ae77Skettenis   /* Calculate the total size of the saved registers, and add it
497b725ae77Skettenis      it to the immediate value used to adjust SP. */
498b725ae77Skettenis   for (i = 0; reg_table[i].mask != 0; i++)
499b725ae77Skettenis     if (list12 & reg_table[i].mask)
500b725ae77Skettenis       offset += v850_register_raw_size (reg_table[i].regno);
501b725ae77Skettenis   pi->frameoffset -= offset;
502b725ae77Skettenis 
503b725ae77Skettenis   /* Calculate the offsets of the registers relative to the value
504b725ae77Skettenis      the SP will have after the registers have been pushed and the
505b725ae77Skettenis      imm5 value is subtracted from it. */
506b725ae77Skettenis   if (pifsr)
507b725ae77Skettenis     {
508b725ae77Skettenis       for (i = 0; reg_table[i].mask != 0; i++)
509b725ae77Skettenis 	{
510b725ae77Skettenis 	  if (list12 & reg_table[i].mask)
511b725ae77Skettenis 	    {
512b725ae77Skettenis 	      int reg = reg_table[i].regno;
513b725ae77Skettenis 	      offset -= v850_register_raw_size (reg);
514b725ae77Skettenis 	      pifsr->reg = reg;
515b725ae77Skettenis 	      pifsr->offset = offset;
516b725ae77Skettenis 	      pifsr->cur_frameoffset = pi->frameoffset;
517b725ae77Skettenis #ifdef DEBUG
518b725ae77Skettenis 	      printf_filtered ("\tSaved register r%d, offset %d", reg, pifsr->offset);
519b725ae77Skettenis #endif
520b725ae77Skettenis 	      pifsr++;
521b725ae77Skettenis 	    }
522b725ae77Skettenis 	}
523b725ae77Skettenis     }
524b725ae77Skettenis #ifdef DEBUG
525b725ae77Skettenis   printf_filtered ("\tfound ctret after regsave func");
526b725ae77Skettenis #endif
527b725ae77Skettenis 
528b725ae77Skettenis   /* Set result parameters. */
529b725ae77Skettenis   *pifsr_ptr = pifsr;
530b725ae77Skettenis }
531b725ae77Skettenis 
532b725ae77Skettenis 
533b725ae77Skettenis 
534b725ae77Skettenis 
535b725ae77Skettenis /* Function: scan_prologue
536b725ae77Skettenis    Scan the prologue of the function that contains PC, and record what
537b725ae77Skettenis    we find in PI.  Returns the pc after the prologue.  Note that the
538b725ae77Skettenis    addresses saved in frame->saved_regs are just frame relative (negative
539b725ae77Skettenis    offsets from the frame pointer).  This is because we don't know the
540b725ae77Skettenis    actual value of the frame pointer yet.  In some circumstances, the
541b725ae77Skettenis    frame pointer can't be determined till after we have scanned the
542b725ae77Skettenis    prologue.  */
543b725ae77Skettenis 
544b725ae77Skettenis static CORE_ADDR
v850_scan_prologue(CORE_ADDR pc,struct prologue_info * pi)545b725ae77Skettenis v850_scan_prologue (CORE_ADDR pc, struct prologue_info *pi)
546b725ae77Skettenis {
547b725ae77Skettenis   CORE_ADDR func_addr, prologue_end, current_pc;
548b725ae77Skettenis   struct pifsr *pifsr, *pifsr_tmp;
549b725ae77Skettenis   int fp_used;
550b725ae77Skettenis   int ep_used;
551b725ae77Skettenis   int reg;
552b725ae77Skettenis   CORE_ADDR save_pc, save_end;
553b725ae77Skettenis   int regsave_func_p;
554b725ae77Skettenis   int r12_tmp;
555b725ae77Skettenis 
556b725ae77Skettenis   /* First, figure out the bounds of the prologue so that we can limit the
557b725ae77Skettenis      search to something reasonable.  */
558b725ae77Skettenis 
559b725ae77Skettenis   if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
560b725ae77Skettenis     {
561b725ae77Skettenis       struct symtab_and_line sal;
562b725ae77Skettenis 
563b725ae77Skettenis       sal = find_pc_line (func_addr, 0);
564b725ae77Skettenis 
565b725ae77Skettenis       if (func_addr == entry_point_address ())
566b725ae77Skettenis 	pi->start_function = 1;
567b725ae77Skettenis       else
568b725ae77Skettenis 	pi->start_function = 0;
569b725ae77Skettenis 
570b725ae77Skettenis #if 0
571b725ae77Skettenis       if (sal.line == 0)
572b725ae77Skettenis 	prologue_end = pc;
573b725ae77Skettenis       else
574b725ae77Skettenis 	prologue_end = sal.end;
575b725ae77Skettenis #else
576b725ae77Skettenis       prologue_end = pc;
577b725ae77Skettenis #endif
578b725ae77Skettenis     }
579b725ae77Skettenis   else
580b725ae77Skettenis     {				/* We're in the boondocks */
581b725ae77Skettenis       func_addr = pc - 100;
582b725ae77Skettenis       prologue_end = pc;
583b725ae77Skettenis     }
584b725ae77Skettenis 
585b725ae77Skettenis   prologue_end = min (prologue_end, pc);
586b725ae77Skettenis 
587b725ae77Skettenis   /* Now, search the prologue looking for instructions that setup fp, save
588b725ae77Skettenis      rp, adjust sp and such.  We also record the frame offset of any saved
589b725ae77Skettenis      registers. */
590b725ae77Skettenis 
591b725ae77Skettenis   pi->frameoffset = 0;
592b725ae77Skettenis   pi->framereg = E_SP_REGNUM;
593b725ae77Skettenis   fp_used = 0;
594b725ae77Skettenis   ep_used = 0;
595b725ae77Skettenis   pifsr = pi->pifsrs;
596b725ae77Skettenis   regsave_func_p = 0;
597b725ae77Skettenis   save_pc = 0;
598b725ae77Skettenis   save_end = 0;
599b725ae77Skettenis   r12_tmp = 0;
600b725ae77Skettenis 
601b725ae77Skettenis #ifdef DEBUG
602b725ae77Skettenis   printf_filtered ("Current_pc = 0x%.8lx, prologue_end = 0x%.8lx\n",
603b725ae77Skettenis 		   (long) func_addr, (long) prologue_end);
604b725ae77Skettenis #endif
605b725ae77Skettenis 
606b725ae77Skettenis   for (current_pc = func_addr; current_pc < prologue_end;)
607b725ae77Skettenis     {
608b725ae77Skettenis       int insn;
609b725ae77Skettenis       int insn2 = -1; /* dummy value */
610b725ae77Skettenis 
611b725ae77Skettenis #ifdef DEBUG
612b725ae77Skettenis       fprintf_filtered (gdb_stdlog, "0x%.8lx ", (long) current_pc);
613b725ae77Skettenis       gdb_print_insn (current_pc, gdb_stdlog);
614b725ae77Skettenis #endif
615b725ae77Skettenis 
616b725ae77Skettenis       insn = read_memory_unsigned_integer (current_pc, 2);
617b725ae77Skettenis       current_pc += 2;
618b725ae77Skettenis       if ((insn & 0x0780) >= 0x0600)	/* Four byte instruction? */
619b725ae77Skettenis 	{
620b725ae77Skettenis 	  insn2 = read_memory_unsigned_integer (current_pc, 2);
621b725ae77Skettenis 	  current_pc += 2;
622b725ae77Skettenis 	}
623b725ae77Skettenis 
624b725ae77Skettenis       if ((insn & 0xffc0) == ((10 << 11) | 0x0780) && !regsave_func_p)
625b725ae77Skettenis 	{			/* jarl <func>,10 */
626b725ae77Skettenis 	  long low_disp = insn2 & ~(long) 1;
627b725ae77Skettenis 	  long disp = (((((insn & 0x3f) << 16) + low_disp)
628b725ae77Skettenis 			& ~(long) 1) ^ 0x00200000) - 0x00200000;
629b725ae77Skettenis 
630b725ae77Skettenis 	  save_pc = current_pc;
631b725ae77Skettenis 	  save_end = prologue_end;
632b725ae77Skettenis 	  regsave_func_p = 1;
633b725ae77Skettenis 	  current_pc += disp - 4;
634b725ae77Skettenis 	  prologue_end = (current_pc
635b725ae77Skettenis 			  + (2 * 3)	/* moves to/from ep */
636b725ae77Skettenis 			  + 4	/* addi <const>,sp,sp */
637b725ae77Skettenis 			  + 2	/* jmp [r10] */
638b725ae77Skettenis 			  + (2 * 12)	/* sst.w to save r2, r20-r29, r31 */
639b725ae77Skettenis 			  + 20);	/* slop area */
640b725ae77Skettenis 
641b725ae77Skettenis #ifdef DEBUG
642b725ae77Skettenis 	  printf_filtered ("\tfound jarl <func>,r10, disp = %ld, low_disp = %ld, new pc = 0x%.8lx\n",
643b725ae77Skettenis 			   disp, low_disp, (long) current_pc + 2);
644b725ae77Skettenis #endif
645b725ae77Skettenis 	  continue;
646b725ae77Skettenis 	}
647b725ae77Skettenis       else if ((insn & 0xffc0) == 0x0200 && !regsave_func_p)
648b725ae77Skettenis 	{			/* callt <imm6> */
649b725ae77Skettenis 	  long ctbp = read_register (E_CTBP_REGNUM);
650b725ae77Skettenis 	  long adr = ctbp + ((insn & 0x3f) << 1);
651b725ae77Skettenis 
652b725ae77Skettenis 	  save_pc = current_pc;
653b725ae77Skettenis 	  save_end = prologue_end;
654b725ae77Skettenis 	  regsave_func_p = 1;
655b725ae77Skettenis 	  current_pc = ctbp + (read_memory_unsigned_integer (adr, 2) & 0xffff);
656b725ae77Skettenis 	  prologue_end = (current_pc
657b725ae77Skettenis 			  + (2 * 3)	/* prepare list2,imm5,sp/imm */
658b725ae77Skettenis 			  + 4	/* ctret */
659b725ae77Skettenis 			  + 20);	/* slop area */
660b725ae77Skettenis 
661b725ae77Skettenis #ifdef DEBUG
662b725ae77Skettenis 	  printf_filtered ("\tfound callt,  ctbp = 0x%.8lx, adr = %.8lx, new pc = 0x%.8lx\n",
663b725ae77Skettenis 			   ctbp, adr, (long) current_pc);
664b725ae77Skettenis #endif
665b725ae77Skettenis 	  continue;
666b725ae77Skettenis 	}
667b725ae77Skettenis       else if ((insn & 0xffc0) == 0x0780)	/* prepare list2,imm5 */
668b725ae77Skettenis 	{
669b725ae77Skettenis 	  handle_prepare (insn, insn2, &current_pc, pi, &pifsr);
670b725ae77Skettenis 	  continue;
671b725ae77Skettenis 	}
672b725ae77Skettenis       else if (insn == 0x07e0 && regsave_func_p && insn2 == 0x0144)
673b725ae77Skettenis 	{			/* ctret after processing register save function */
674b725ae77Skettenis 	  current_pc = save_pc;
675b725ae77Skettenis 	  prologue_end = save_end;
676b725ae77Skettenis 	  regsave_func_p = 0;
677b725ae77Skettenis #ifdef DEBUG
678b725ae77Skettenis 	  printf_filtered ("\tfound ctret after regsave func");
679b725ae77Skettenis #endif
680b725ae77Skettenis 	  continue;
681b725ae77Skettenis 	}
682b725ae77Skettenis       else if ((insn & 0xfff0) == 0x07e0 && (insn2 & 5) == 1)
683b725ae77Skettenis 	{			/* pushml, pushmh */
684b725ae77Skettenis 	  handle_pushm (insn, insn2, pi, &pifsr);
685b725ae77Skettenis 	  continue;
686b725ae77Skettenis 	}
687b725ae77Skettenis       else if ((insn & 0xffe0) == 0x0060 && regsave_func_p)
688b725ae77Skettenis 	{			/* jmp after processing register save function */
689b725ae77Skettenis 	  current_pc = save_pc;
690b725ae77Skettenis 	  prologue_end = save_end;
691b725ae77Skettenis 	  regsave_func_p = 0;
692b725ae77Skettenis #ifdef DEBUG
693b725ae77Skettenis 	  printf_filtered ("\tfound jmp after regsave func");
694b725ae77Skettenis #endif
695b725ae77Skettenis 	  continue;
696b725ae77Skettenis 	}
697b725ae77Skettenis       else if ((insn & 0x07c0) == 0x0780	/* jarl or jr */
698b725ae77Skettenis 	       || (insn & 0xffe0) == 0x0060	/* jmp */
699b725ae77Skettenis 	       || (insn & 0x0780) == 0x0580)	/* branch */
700b725ae77Skettenis 	{
701b725ae77Skettenis #ifdef DEBUG
702b725ae77Skettenis 	  printf_filtered ("\n");
703b725ae77Skettenis #endif
704b725ae77Skettenis 	  break;		/* Ran into end of prologue */
705b725ae77Skettenis 	}
706b725ae77Skettenis 
707b725ae77Skettenis       else if ((insn & 0xffe0) == ((E_SP_REGNUM << 11) | 0x0240))		/* add <imm>,sp */
708b725ae77Skettenis 	pi->frameoffset += ((insn & 0x1f) ^ 0x10) - 0x10;
709b725ae77Skettenis       else if (insn == ((E_SP_REGNUM << 11) | 0x0600 | E_SP_REGNUM))	/* addi <imm>,sp,sp */
710b725ae77Skettenis 	pi->frameoffset += insn2;
711b725ae77Skettenis       else if (insn == ((E_FP_RAW_REGNUM << 11) | 0x0000 | E_SP_REGNUM))	/* mov sp,fp */
712b725ae77Skettenis 	{
713b725ae77Skettenis 	  fp_used = 1;
714b725ae77Skettenis 	  pi->framereg = E_FP_RAW_REGNUM;
715b725ae77Skettenis 	}
716b725ae77Skettenis 
717b725ae77Skettenis       else if (insn == ((E_R12_REGNUM << 11) | 0x0640 | E_R0_REGNUM))	/* movhi hi(const),r0,r12 */
718b725ae77Skettenis 	r12_tmp = insn2 << 16;
719b725ae77Skettenis       else if (insn == ((E_R12_REGNUM << 11) | 0x0620 | E_R12_REGNUM))	/* movea lo(const),r12,r12 */
720b725ae77Skettenis 	r12_tmp += insn2;
721b725ae77Skettenis       else if (insn == ((E_SP_REGNUM << 11) | 0x01c0 | E_R12_REGNUM) && r12_tmp)	/* add r12,sp */
722b725ae77Skettenis 	pi->frameoffset = r12_tmp;
723b725ae77Skettenis       else if (insn == ((E_EP_REGNUM << 11) | 0x0000 | E_SP_REGNUM))	/* mov sp,ep */
724b725ae77Skettenis 	ep_used = 1;
725b725ae77Skettenis       else if (insn == ((E_EP_REGNUM << 11) | 0x0000 | E_R1_REGNUM))	/* mov r1,ep */
726b725ae77Skettenis 	ep_used = 0;
727b725ae77Skettenis       else if (((insn & 0x07ff) == (0x0760 | E_SP_REGNUM)		/* st.w <reg>,<offset>[sp] */
728b725ae77Skettenis 		|| (fp_used
729b725ae77Skettenis 		    && (insn & 0x07ff) == (0x0760 | E_FP_RAW_REGNUM)))	/* st.w <reg>,<offset>[fp] */
730b725ae77Skettenis 	       && pifsr
731b725ae77Skettenis 	       && (((reg = (insn >> 11) & 0x1f) >= E_SAVE1_START_REGNUM && reg <= E_SAVE1_END_REGNUM)
732b725ae77Skettenis 		   || (reg >= E_SAVE2_START_REGNUM && reg <= E_SAVE2_END_REGNUM)
733b725ae77Skettenis 		 || (reg >= E_SAVE3_START_REGNUM && reg <= E_SAVE3_END_REGNUM)))
734b725ae77Skettenis 	{
735b725ae77Skettenis 	  pifsr->reg = reg;
736b725ae77Skettenis 	  pifsr->offset = insn2 & ~1;
737b725ae77Skettenis 	  pifsr->cur_frameoffset = pi->frameoffset;
738b725ae77Skettenis #ifdef DEBUG
739b725ae77Skettenis 	  printf_filtered ("\tSaved register r%d, offset %d", reg, pifsr->offset);
740b725ae77Skettenis #endif
741b725ae77Skettenis 	  pifsr++;
742b725ae77Skettenis 	}
743b725ae77Skettenis 
744b725ae77Skettenis       else if (ep_used		/* sst.w <reg>,<offset>[ep] */
745b725ae77Skettenis 	       && ((insn & 0x0781) == 0x0501)
746b725ae77Skettenis 	       && pifsr
747b725ae77Skettenis 	       && (((reg = (insn >> 11) & 0x1f) >= E_SAVE1_START_REGNUM && reg <= E_SAVE1_END_REGNUM)
748b725ae77Skettenis 		   || (reg >= E_SAVE2_START_REGNUM && reg <= E_SAVE2_END_REGNUM)
749b725ae77Skettenis 		 || (reg >= E_SAVE3_START_REGNUM && reg <= E_SAVE3_END_REGNUM)))
750b725ae77Skettenis 	{
751b725ae77Skettenis 	  pifsr->reg = reg;
752b725ae77Skettenis 	  pifsr->offset = (insn & 0x007e) << 1;
753b725ae77Skettenis 	  pifsr->cur_frameoffset = pi->frameoffset;
754b725ae77Skettenis #ifdef DEBUG
755b725ae77Skettenis 	  printf_filtered ("\tSaved register r%d, offset %d", reg, pifsr->offset);
756b725ae77Skettenis #endif
757b725ae77Skettenis 	  pifsr++;
758b725ae77Skettenis 	}
759b725ae77Skettenis 
760b725ae77Skettenis #ifdef DEBUG
761b725ae77Skettenis       printf_filtered ("\n");
762b725ae77Skettenis #endif
763b725ae77Skettenis     }
764b725ae77Skettenis 
765b725ae77Skettenis   if (pifsr)
766b725ae77Skettenis     pifsr->framereg = 0;	/* Tie off last entry */
767b725ae77Skettenis 
768b725ae77Skettenis   /* Fix up any offsets to the final offset.  If a frame pointer was created, use it
769b725ae77Skettenis      instead of the stack pointer.  */
770b725ae77Skettenis   for (pifsr_tmp = pi->pifsrs; pifsr_tmp && pifsr_tmp != pifsr; pifsr_tmp++)
771b725ae77Skettenis     {
772b725ae77Skettenis       pifsr_tmp->offset -= pi->frameoffset - pifsr_tmp->cur_frameoffset;
773b725ae77Skettenis       pifsr_tmp->framereg = pi->framereg;
774b725ae77Skettenis 
775b725ae77Skettenis #ifdef DEBUG
776b725ae77Skettenis       printf_filtered ("Saved register r%d, offset = %d, framereg = r%d\n",
777b725ae77Skettenis 		    pifsr_tmp->reg, pifsr_tmp->offset, pifsr_tmp->framereg);
778b725ae77Skettenis #endif
779b725ae77Skettenis     }
780b725ae77Skettenis 
781b725ae77Skettenis #ifdef DEBUG
782b725ae77Skettenis   printf_filtered ("Framereg = r%d, frameoffset = %d\n", pi->framereg, pi->frameoffset);
783b725ae77Skettenis #endif
784b725ae77Skettenis 
785b725ae77Skettenis   return current_pc;
786b725ae77Skettenis }
787b725ae77Skettenis 
788b725ae77Skettenis /* Function: find_callers_reg
789b725ae77Skettenis    Find REGNUM on the stack.  Otherwise, it's in an active register.
790b725ae77Skettenis    One thing we might want to do here is to check REGNUM against the
791b725ae77Skettenis    clobber mask, and somehow flag it as invalid if it isn't saved on
792b725ae77Skettenis    the stack somewhere.  This would provide a graceful failure mode
793b725ae77Skettenis    when trying to get the value of caller-saves registers for an inner
794b725ae77Skettenis    frame.  */
795b725ae77Skettenis 
796b725ae77Skettenis static CORE_ADDR
v850_find_callers_reg(struct frame_info * fi,int regnum)797b725ae77Skettenis v850_find_callers_reg (struct frame_info *fi, int regnum)
798b725ae77Skettenis {
799b725ae77Skettenis   for (; fi; fi = get_next_frame (fi))
800*11efff7fSkettenis     if (deprecated_pc_in_call_dummy (get_frame_pc (fi)))
801b725ae77Skettenis       return deprecated_read_register_dummy (get_frame_pc (fi),
802b725ae77Skettenis 					     get_frame_base (fi), regnum);
803b725ae77Skettenis     else if (deprecated_get_frame_saved_regs (fi)[regnum] != 0)
804b725ae77Skettenis       return read_memory_unsigned_integer (deprecated_get_frame_saved_regs (fi)[regnum],
805b725ae77Skettenis 					   v850_register_raw_size (regnum));
806b725ae77Skettenis 
807b725ae77Skettenis   return read_register (regnum);
808b725ae77Skettenis }
809b725ae77Skettenis 
810b725ae77Skettenis /* Function: frame_chain
811b725ae77Skettenis    Figure out the frame prior to FI.  Unfortunately, this involves
812b725ae77Skettenis    scanning the prologue of the caller, which will also be done
813b725ae77Skettenis    shortly by v850_init_extra_frame_info.  For the dummy frame, we
814b725ae77Skettenis    just return the stack pointer that was in use at the time the
815b725ae77Skettenis    function call was made.  */
816b725ae77Skettenis 
817b725ae77Skettenis static CORE_ADDR
v850_frame_chain(struct frame_info * fi)818b725ae77Skettenis v850_frame_chain (struct frame_info *fi)
819b725ae77Skettenis {
820b725ae77Skettenis   struct prologue_info pi;
821b725ae77Skettenis   CORE_ADDR callers_pc, fp;
822b725ae77Skettenis 
823b725ae77Skettenis   /* First, find out who called us */
824b725ae77Skettenis   callers_pc = DEPRECATED_FRAME_SAVED_PC (fi);
825b725ae77Skettenis   /* If caller is a call-dummy, then our FP bears no relation to his FP! */
826b725ae77Skettenis   fp = v850_find_callers_reg (fi, E_FP_RAW_REGNUM);
827*11efff7fSkettenis   if (deprecated_pc_in_call_dummy (callers_pc))
828b725ae77Skettenis     return fp;			/* caller is call-dummy: return oldest value of FP */
829b725ae77Skettenis 
830b725ae77Skettenis   /* Caller is NOT a call-dummy, so everything else should just work.
831b725ae77Skettenis      Even if THIS frame is a call-dummy! */
832b725ae77Skettenis   pi.pifsrs = NULL;
833b725ae77Skettenis 
834b725ae77Skettenis   v850_scan_prologue (callers_pc, &pi);
835b725ae77Skettenis 
836b725ae77Skettenis   if (pi.start_function)
837b725ae77Skettenis     return 0;			/* Don't chain beyond the start function */
838b725ae77Skettenis 
839b725ae77Skettenis   if (pi.framereg == E_FP_RAW_REGNUM)
840b725ae77Skettenis     return v850_find_callers_reg (fi, pi.framereg);
841b725ae77Skettenis 
842b725ae77Skettenis   return get_frame_base (fi) - pi.frameoffset;
843b725ae77Skettenis }
844b725ae77Skettenis 
845b725ae77Skettenis /* Function: skip_prologue
846b725ae77Skettenis    Return the address of the first code past the prologue of the function.  */
847b725ae77Skettenis 
848b725ae77Skettenis static CORE_ADDR
v850_skip_prologue(CORE_ADDR pc)849b725ae77Skettenis v850_skip_prologue (CORE_ADDR pc)
850b725ae77Skettenis {
851b725ae77Skettenis   CORE_ADDR func_addr, func_end;
852b725ae77Skettenis 
853b725ae77Skettenis   /* See what the symbol table says */
854b725ae77Skettenis 
855b725ae77Skettenis   if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
856b725ae77Skettenis     {
857b725ae77Skettenis       struct symtab_and_line sal;
858b725ae77Skettenis 
859b725ae77Skettenis       sal = find_pc_line (func_addr, 0);
860b725ae77Skettenis 
861b725ae77Skettenis       if (sal.line != 0 && sal.end < func_end)
862b725ae77Skettenis 	return sal.end;
863b725ae77Skettenis       else
864b725ae77Skettenis 	/* Either there's no line info, or the line after the prologue is after
865b725ae77Skettenis 	   the end of the function.  In this case, there probably isn't a
866b725ae77Skettenis 	   prologue.  */
867b725ae77Skettenis 	return pc;
868b725ae77Skettenis     }
869b725ae77Skettenis 
870b725ae77Skettenis /* We can't find the start of this function, so there's nothing we can do. */
871b725ae77Skettenis   return pc;
872b725ae77Skettenis }
873b725ae77Skettenis 
874b725ae77Skettenis /* Function: pop_frame
875b725ae77Skettenis    This routine gets called when either the user uses the `return'
876b725ae77Skettenis    command, or the call dummy breakpoint gets hit.  */
877b725ae77Skettenis 
878b725ae77Skettenis static void
v850_pop_frame(void)879b725ae77Skettenis v850_pop_frame (void)
880b725ae77Skettenis {
881b725ae77Skettenis   struct frame_info *frame = get_current_frame ();
882b725ae77Skettenis   int regnum;
883b725ae77Skettenis 
884*11efff7fSkettenis   if (deprecated_pc_in_call_dummy (get_frame_pc (frame)))
885*11efff7fSkettenis     deprecated_pop_dummy_frame ();
886b725ae77Skettenis   else
887b725ae77Skettenis     {
888b725ae77Skettenis       write_register (E_PC_REGNUM, DEPRECATED_FRAME_SAVED_PC (frame));
889b725ae77Skettenis 
890b725ae77Skettenis       for (regnum = 0; regnum < E_NUM_REGS; regnum++)
891b725ae77Skettenis 	if (deprecated_get_frame_saved_regs (frame)[regnum] != 0)
892b725ae77Skettenis 	  write_register (regnum,
893b725ae77Skettenis 		      read_memory_unsigned_integer (deprecated_get_frame_saved_regs (frame)[regnum],
894b725ae77Skettenis 					     v850_register_raw_size (regnum)));
895b725ae77Skettenis 
896b725ae77Skettenis       write_register (E_SP_REGNUM, get_frame_base (frame));
897b725ae77Skettenis     }
898b725ae77Skettenis 
899b725ae77Skettenis   flush_cached_frames ();
900b725ae77Skettenis }
901b725ae77Skettenis 
902b725ae77Skettenis /* Function: push_arguments
903b725ae77Skettenis    Setup arguments and RP for a call to the target.  First four args
904b725ae77Skettenis    go in R6->R9, subsequent args go into sp + 16 -> sp + ...  Structs
905b725ae77Skettenis    are passed by reference.  64 bit quantities (doubles and long
906b725ae77Skettenis    longs) may be split between the regs and the stack.  When calling a
907b725ae77Skettenis    function that returns a struct, a pointer to the struct is passed
908b725ae77Skettenis    in as a secret first argument (always in R6).
909b725ae77Skettenis 
910b725ae77Skettenis    Stack space for the args has NOT been allocated: that job is up to us.
911b725ae77Skettenis  */
912b725ae77Skettenis 
913b725ae77Skettenis static CORE_ADDR
v850_push_arguments(int nargs,struct value ** args,CORE_ADDR sp,int struct_return,CORE_ADDR struct_addr)914b725ae77Skettenis v850_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
915b725ae77Skettenis 		     int struct_return, CORE_ADDR struct_addr)
916b725ae77Skettenis {
917b725ae77Skettenis   int argreg;
918b725ae77Skettenis   int argnum;
919b725ae77Skettenis   int len = 0;
920b725ae77Skettenis   int stack_offset;
921b725ae77Skettenis 
922b725ae77Skettenis   /* First, just for safety, make sure stack is aligned */
923b725ae77Skettenis   sp &= ~3;
924b725ae77Skettenis 
925b725ae77Skettenis   /* The offset onto the stack at which we will start copying parameters
926b725ae77Skettenis      (after the registers are used up) begins at 16 rather than at zero.
927b725ae77Skettenis      I don't really know why, that's just the way it seems to work.  */
928b725ae77Skettenis   stack_offset = 16;
929b725ae77Skettenis 
930b725ae77Skettenis   /* Now make space on the stack for the args. */
931b725ae77Skettenis   for (argnum = 0; argnum < nargs; argnum++)
932b725ae77Skettenis     len += ((TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 3) & ~3);
933b725ae77Skettenis   sp -= len + stack_offset;	/* possibly over-allocating, but it works... */
934b725ae77Skettenis   /* (you might think we could allocate 16 bytes */
935b725ae77Skettenis   /* less, but the ABI seems to use it all! )  */
936b725ae77Skettenis 
937b725ae77Skettenis   argreg = E_ARG0_REGNUM;
938b725ae77Skettenis   /* the struct_return pointer occupies the first parameter-passing reg */
939b725ae77Skettenis   if (struct_return)
940b725ae77Skettenis     argreg++;
941b725ae77Skettenis 
942b725ae77Skettenis   /* Now load as many as possible of the first arguments into
943b725ae77Skettenis      registers, and push the rest onto the stack.  There are 16 bytes
944b725ae77Skettenis      in four registers available.  Loop thru args from first to last.  */
945b725ae77Skettenis   for (argnum = 0; argnum < nargs; argnum++)
946b725ae77Skettenis     {
947b725ae77Skettenis       int len;
948b725ae77Skettenis       char *val;
949b725ae77Skettenis       char valbuf[v850_register_raw_size (E_ARG0_REGNUM)];
950b725ae77Skettenis 
951b725ae77Skettenis       if (!v850_type_is_scalar (VALUE_TYPE (*args))
952b725ae77Skettenis 	  && TYPE_LENGTH (VALUE_TYPE (*args)) > E_MAX_RETTYPE_SIZE_IN_REGS)
953b725ae77Skettenis 	{
954b725ae77Skettenis 	  store_unsigned_integer (valbuf, 4, VALUE_ADDRESS (*args));
955b725ae77Skettenis 	  len = 4;
956b725ae77Skettenis 	  val = valbuf;
957b725ae77Skettenis 	}
958b725ae77Skettenis       else
959b725ae77Skettenis 	{
960b725ae77Skettenis 	  len = TYPE_LENGTH (VALUE_TYPE (*args));
961b725ae77Skettenis 	  val = (char *) VALUE_CONTENTS (*args);
962b725ae77Skettenis 	}
963b725ae77Skettenis 
964b725ae77Skettenis       while (len > 0)
965b725ae77Skettenis 	if (argreg <= E_ARGLAST_REGNUM)
966b725ae77Skettenis 	  {
967b725ae77Skettenis 	    CORE_ADDR regval;
968b725ae77Skettenis 
969b725ae77Skettenis 	    regval = extract_unsigned_integer (val, v850_register_raw_size (argreg));
970b725ae77Skettenis 	    write_register (argreg, regval);
971b725ae77Skettenis 
972b725ae77Skettenis 	    len -= v850_register_raw_size (argreg);
973b725ae77Skettenis 	    val += v850_register_raw_size (argreg);
974b725ae77Skettenis 	    argreg++;
975b725ae77Skettenis 	  }
976b725ae77Skettenis 	else
977b725ae77Skettenis 	  {
978b725ae77Skettenis 	    write_memory (sp + stack_offset, val, 4);
979b725ae77Skettenis 
980b725ae77Skettenis 	    len -= 4;
981b725ae77Skettenis 	    val += 4;
982b725ae77Skettenis 	    stack_offset += 4;
983b725ae77Skettenis 	  }
984b725ae77Skettenis       args++;
985b725ae77Skettenis     }
986b725ae77Skettenis   return sp;
987b725ae77Skettenis }
988b725ae77Skettenis 
989b725ae77Skettenis /* Function: push_return_address (pc)
990b725ae77Skettenis    Set up the return address for the inferior function call.
991b725ae77Skettenis    Needed for targets where we don't actually execute a JSR/BSR instruction */
992b725ae77Skettenis 
993b725ae77Skettenis static CORE_ADDR
v850_push_return_address(CORE_ADDR pc,CORE_ADDR sp)994b725ae77Skettenis v850_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
995b725ae77Skettenis {
996b725ae77Skettenis   write_register (E_RP_REGNUM, entry_point_address ());
997b725ae77Skettenis   return sp;
998b725ae77Skettenis }
999b725ae77Skettenis 
1000b725ae77Skettenis /* Function: frame_saved_pc
1001b725ae77Skettenis    Find the caller of this frame.  We do this by seeing if E_RP_REGNUM
1002b725ae77Skettenis    is saved in the stack anywhere, otherwise we get it from the
1003b725ae77Skettenis    registers.  If the inner frame is a dummy frame, return its PC
1004b725ae77Skettenis    instead of RP, because that's where "caller" of the dummy-frame
1005b725ae77Skettenis    will be found.  */
1006b725ae77Skettenis 
1007b725ae77Skettenis static CORE_ADDR
v850_frame_saved_pc(struct frame_info * fi)1008b725ae77Skettenis v850_frame_saved_pc (struct frame_info *fi)
1009b725ae77Skettenis {
1010*11efff7fSkettenis   if (deprecated_pc_in_call_dummy (get_frame_pc (fi)))
1011b725ae77Skettenis     return deprecated_read_register_dummy (get_frame_pc (fi),
1012b725ae77Skettenis 					   get_frame_base (fi), E_PC_REGNUM);
1013b725ae77Skettenis   else
1014b725ae77Skettenis     return v850_find_callers_reg (fi, E_RP_REGNUM);
1015b725ae77Skettenis }
1016b725ae77Skettenis 
1017b725ae77Skettenis 
1018b725ae77Skettenis static CORE_ADDR
v850_saved_pc_after_call(struct frame_info * ignore)1019b725ae77Skettenis v850_saved_pc_after_call (struct frame_info *ignore)
1020b725ae77Skettenis {
1021b725ae77Skettenis   return read_register (E_RP_REGNUM);
1022b725ae77Skettenis }
1023b725ae77Skettenis 
1024b725ae77Skettenis static void
v850_extract_return_value(struct type * type,char * regbuf,char * valbuf)1025b725ae77Skettenis v850_extract_return_value (struct type *type, char *regbuf, char *valbuf)
1026b725ae77Skettenis {
1027b725ae77Skettenis   CORE_ADDR return_buffer;
1028b725ae77Skettenis 
1029b725ae77Skettenis   if (!v850_use_struct_convention (0, type))
1030b725ae77Skettenis     {
1031b725ae77Skettenis       /* Scalar return values of <= 8 bytes are returned in
1032b725ae77Skettenis          E_V0_REGNUM to E_V1_REGNUM. */
1033b725ae77Skettenis       memcpy (valbuf,
1034b725ae77Skettenis 	      &regbuf[DEPRECATED_REGISTER_BYTE (E_V0_REGNUM)],
1035b725ae77Skettenis 	      TYPE_LENGTH (type));
1036b725ae77Skettenis     }
1037b725ae77Skettenis   else
1038b725ae77Skettenis     {
1039b725ae77Skettenis       /* Aggregates and return values > 8 bytes are returned in memory,
1040b725ae77Skettenis          pointed to by R6. */
1041b725ae77Skettenis       return_buffer =
1042b725ae77Skettenis 	extract_unsigned_integer (regbuf + DEPRECATED_REGISTER_BYTE (E_V0_REGNUM),
1043*11efff7fSkettenis 				  register_size (current_gdbarch, E_V0_REGNUM));
1044b725ae77Skettenis 
1045b725ae77Skettenis       read_memory (return_buffer, valbuf, TYPE_LENGTH (type));
1046b725ae77Skettenis     }
1047b725ae77Skettenis }
1048b725ae77Skettenis 
1049b725ae77Skettenis const static unsigned char *
v850_breakpoint_from_pc(CORE_ADDR * pcptr,int * lenptr)1050b725ae77Skettenis v850_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
1051b725ae77Skettenis {
1052b725ae77Skettenis   static unsigned char breakpoint[] = { 0x85, 0x05 };
1053b725ae77Skettenis   *lenptr = sizeof (breakpoint);
1054b725ae77Skettenis   return breakpoint;
1055b725ae77Skettenis }
1056b725ae77Skettenis 
1057b725ae77Skettenis static void
v850_store_return_value(struct type * type,char * valbuf)1058b725ae77Skettenis v850_store_return_value (struct type *type, char *valbuf)
1059b725ae77Skettenis {
1060b725ae77Skettenis   CORE_ADDR return_buffer;
1061b725ae77Skettenis 
1062b725ae77Skettenis   if (!v850_use_struct_convention (0, type))
1063b725ae77Skettenis     deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (E_V0_REGNUM), valbuf,
1064b725ae77Skettenis 				     TYPE_LENGTH (type));
1065b725ae77Skettenis   else
1066b725ae77Skettenis     {
1067b725ae77Skettenis       return_buffer = read_register (E_V0_REGNUM);
1068b725ae77Skettenis       write_memory (return_buffer, valbuf, TYPE_LENGTH (type));
1069b725ae77Skettenis     }
1070b725ae77Skettenis }
1071b725ae77Skettenis 
1072b725ae77Skettenis static void
v850_frame_init_saved_regs(struct frame_info * fi)1073b725ae77Skettenis v850_frame_init_saved_regs (struct frame_info *fi)
1074b725ae77Skettenis {
1075b725ae77Skettenis   struct prologue_info pi;
1076b725ae77Skettenis   struct pifsr pifsrs[E_NUM_REGS + 1], *pifsr;
1077b725ae77Skettenis   CORE_ADDR func_addr, func_end;
1078b725ae77Skettenis 
1079b725ae77Skettenis   if (!deprecated_get_frame_saved_regs (fi))
1080b725ae77Skettenis     {
1081b725ae77Skettenis       frame_saved_regs_zalloc (fi);
1082b725ae77Skettenis 
1083b725ae77Skettenis       /* The call dummy doesn't save any registers on the stack, so we
1084b725ae77Skettenis          can return now.  */
1085*11efff7fSkettenis       if (deprecated_pc_in_call_dummy (get_frame_pc (fi)))
1086b725ae77Skettenis 	return;
1087b725ae77Skettenis 
1088b725ae77Skettenis       /* Find the beginning of this function, so we can analyze its
1089b725ae77Skettenis          prologue. */
1090b725ae77Skettenis       if (find_pc_partial_function (get_frame_pc (fi), NULL, &func_addr, &func_end))
1091b725ae77Skettenis 	{
1092b725ae77Skettenis 	  pi.pifsrs = pifsrs;
1093b725ae77Skettenis 
1094b725ae77Skettenis 	  v850_scan_prologue (get_frame_pc (fi), &pi);
1095b725ae77Skettenis 
1096b725ae77Skettenis 	  if (!get_next_frame (fi) && pi.framereg == E_SP_REGNUM)
1097b725ae77Skettenis 	    deprecated_update_frame_base_hack (fi, read_register (pi.framereg) - pi.frameoffset);
1098b725ae77Skettenis 
1099b725ae77Skettenis 	  for (pifsr = pifsrs; pifsr->framereg; pifsr++)
1100b725ae77Skettenis 	    {
1101b725ae77Skettenis 	      deprecated_get_frame_saved_regs (fi)[pifsr->reg] = pifsr->offset + get_frame_base (fi);
1102b725ae77Skettenis 
1103b725ae77Skettenis 	      if (pifsr->framereg == E_SP_REGNUM)
1104b725ae77Skettenis 		deprecated_get_frame_saved_regs (fi)[pifsr->reg] += pi.frameoffset;
1105b725ae77Skettenis 	    }
1106b725ae77Skettenis 	}
1107b725ae77Skettenis       /* Else we're out of luck (can't debug completely stripped code).
1108b725ae77Skettenis          FIXME. */
1109b725ae77Skettenis     }
1110b725ae77Skettenis }
1111b725ae77Skettenis 
1112b725ae77Skettenis /* Function: init_extra_frame_info
1113b725ae77Skettenis    Setup the frame's frame pointer, pc, and frame addresses for saved
1114b725ae77Skettenis    registers.  Most of the work is done in scan_prologue().
1115b725ae77Skettenis 
1116b725ae77Skettenis    Note that when we are called for the last frame (currently active frame),
1117b725ae77Skettenis    that get_frame_pc (fi) and fi->frame will already be setup.  However, fi->frame will
1118b725ae77Skettenis    be valid only if this routine uses FP.  For previous frames, fi-frame will
1119b725ae77Skettenis    always be correct (since that is derived from v850_frame_chain ()).
1120b725ae77Skettenis 
1121b725ae77Skettenis    We can be called with the PC in the call dummy under two
1122b725ae77Skettenis    circumstances.  First, during normal backtracing, second, while
1123b725ae77Skettenis    figuring out the frame pointer just prior to calling the target
1124b725ae77Skettenis    function (see call_function_by_hand).  */
1125b725ae77Skettenis 
1126b725ae77Skettenis static void
v850_init_extra_frame_info(int fromleaf,struct frame_info * fi)1127b725ae77Skettenis v850_init_extra_frame_info (int fromleaf, struct frame_info *fi)
1128b725ae77Skettenis {
1129b725ae77Skettenis   struct prologue_info pi;
1130b725ae77Skettenis 
1131b725ae77Skettenis   if (get_next_frame (fi))
1132b725ae77Skettenis     deprecated_update_frame_pc_hack (fi, DEPRECATED_FRAME_SAVED_PC (get_next_frame (fi)));
1133b725ae77Skettenis 
1134b725ae77Skettenis   v850_frame_init_saved_regs (fi);
1135b725ae77Skettenis }
1136b725ae77Skettenis 
1137b725ae77Skettenis static void
v850_store_struct_return(CORE_ADDR addr,CORE_ADDR sp)1138b725ae77Skettenis v850_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
1139b725ae77Skettenis {
1140b725ae77Skettenis   write_register (E_ARG0_REGNUM, addr);
1141b725ae77Skettenis }
1142b725ae77Skettenis 
1143b725ae77Skettenis static CORE_ADDR
v850_target_read_fp(void)1144b725ae77Skettenis v850_target_read_fp (void)
1145b725ae77Skettenis {
1146b725ae77Skettenis   return read_register (E_FP_RAW_REGNUM);
1147b725ae77Skettenis }
1148b725ae77Skettenis 
1149b725ae77Skettenis static struct gdbarch *
v850_gdbarch_init(struct gdbarch_info info,struct gdbarch_list * arches)1150b725ae77Skettenis v850_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
1151b725ae77Skettenis {
1152b725ae77Skettenis   struct gdbarch_tdep *tdep = NULL;
1153b725ae77Skettenis   struct gdbarch *gdbarch;
1154b725ae77Skettenis   int i;
1155b725ae77Skettenis 
1156b725ae77Skettenis   /* find a candidate among the list of pre-declared architectures. */
1157b725ae77Skettenis   arches = gdbarch_list_lookup_by_info (arches, &info);
1158b725ae77Skettenis   if (arches != NULL)
1159b725ae77Skettenis     return (arches->gdbarch);
1160b725ae77Skettenis 
1161b725ae77Skettenis #if 0
1162b725ae77Skettenis   tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
1163b725ae77Skettenis #endif
1164b725ae77Skettenis 
1165b725ae77Skettenis   /* Change the register names based on the current machine type. */
1166b725ae77Skettenis   if (info.bfd_arch_info->arch != bfd_arch_v850)
1167b725ae77Skettenis     return 0;
1168b725ae77Skettenis 
1169b725ae77Skettenis   gdbarch = gdbarch_alloc (&info, 0);
1170b725ae77Skettenis 
1171b725ae77Skettenis   /* NOTE: cagney/2002-12-06: This can be deleted when this arch is
1172b725ae77Skettenis      ready to unwind the PC first (see frame.c:get_prev_frame()).  */
1173b725ae77Skettenis   set_gdbarch_deprecated_init_frame_pc (gdbarch, deprecated_init_frame_pc_default);
1174b725ae77Skettenis 
1175b725ae77Skettenis   for (i = 0; v850_processor_type_table[i].regnames != NULL; i++)
1176b725ae77Skettenis     {
1177b725ae77Skettenis       if (v850_processor_type_table[i].mach == info.bfd_arch_info->mach)
1178b725ae77Skettenis 	{
1179b725ae77Skettenis 	  v850_register_names = v850_processor_type_table[i].regnames;
1180b725ae77Skettenis 	  break;
1181b725ae77Skettenis 	}
1182b725ae77Skettenis     }
1183b725ae77Skettenis 
1184b725ae77Skettenis   /*
1185b725ae77Skettenis    * Basic register fields and methods.
1186b725ae77Skettenis    */
1187b725ae77Skettenis   set_gdbarch_num_regs (gdbarch, E_NUM_REGS);
1188b725ae77Skettenis   set_gdbarch_num_pseudo_regs (gdbarch, 0);
1189b725ae77Skettenis   set_gdbarch_sp_regnum (gdbarch, E_SP_REGNUM);
1190b725ae77Skettenis   set_gdbarch_deprecated_fp_regnum (gdbarch, E_FP_REGNUM);
1191b725ae77Skettenis   set_gdbarch_pc_regnum (gdbarch, E_PC_REGNUM);
1192b725ae77Skettenis   set_gdbarch_register_name (gdbarch, v850_register_name);
1193b725ae77Skettenis   set_gdbarch_deprecated_register_size (gdbarch, v850_reg_size);
1194b725ae77Skettenis   set_gdbarch_deprecated_register_byte (gdbarch, v850_register_byte);
1195*11efff7fSkettenis   set_gdbarch_deprecated_register_raw_size (current_gdbarch, gdbarch, v850_register_raw_size);
1196b725ae77Skettenis   set_gdbarch_deprecated_register_virtual_size (gdbarch, v850_register_raw_size);
1197b725ae77Skettenis   set_gdbarch_deprecated_register_virtual_type (gdbarch, v850_reg_virtual_type);
1198b725ae77Skettenis 
1199b725ae77Skettenis   set_gdbarch_deprecated_target_read_fp (gdbarch, v850_target_read_fp);
1200b725ae77Skettenis 
1201b725ae77Skettenis   /*
1202b725ae77Skettenis    * Frame Info
1203b725ae77Skettenis    */
1204b725ae77Skettenis   set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, v850_frame_init_saved_regs);
1205b725ae77Skettenis   set_gdbarch_deprecated_init_extra_frame_info (gdbarch, v850_init_extra_frame_info);
1206b725ae77Skettenis   set_gdbarch_deprecated_frame_chain (gdbarch, v850_frame_chain);
1207b725ae77Skettenis   set_gdbarch_deprecated_saved_pc_after_call (gdbarch, v850_saved_pc_after_call);
1208b725ae77Skettenis   set_gdbarch_deprecated_frame_saved_pc (gdbarch, v850_frame_saved_pc);
1209b725ae77Skettenis   set_gdbarch_skip_prologue (gdbarch, v850_skip_prologue);
1210b725ae77Skettenis 
1211b725ae77Skettenis   /*
1212b725ae77Skettenis    * Miscelany
1213b725ae77Skettenis    */
1214b725ae77Skettenis   /* Stack grows up. */
1215b725ae77Skettenis   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
1216b725ae77Skettenis 
1217b725ae77Skettenis   /*
1218b725ae77Skettenis    * Call Dummies
1219b725ae77Skettenis    *
1220b725ae77Skettenis    * These values and methods are used when gdb calls a target function.  */
1221b725ae77Skettenis   set_gdbarch_deprecated_push_return_address (gdbarch, v850_push_return_address);
1222b725ae77Skettenis   set_gdbarch_deprecated_extract_return_value (gdbarch, v850_extract_return_value);
1223b725ae77Skettenis   set_gdbarch_deprecated_push_arguments (gdbarch, v850_push_arguments);
1224b725ae77Skettenis   set_gdbarch_deprecated_pop_frame (gdbarch, v850_pop_frame);
1225b725ae77Skettenis   set_gdbarch_deprecated_store_struct_return (gdbarch, v850_store_struct_return);
1226b725ae77Skettenis   set_gdbarch_deprecated_store_return_value (gdbarch, v850_store_return_value);
1227*11efff7fSkettenis   set_gdbarch_deprecated_use_struct_convention (gdbarch, v850_use_struct_convention);
1228b725ae77Skettenis   set_gdbarch_breakpoint_from_pc (gdbarch, v850_breakpoint_from_pc);
1229b725ae77Skettenis 
1230b725ae77Skettenis   set_gdbarch_int_bit (gdbarch, 4 * TARGET_CHAR_BIT);
1231b725ae77Skettenis   set_gdbarch_ptr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
1232b725ae77Skettenis   set_gdbarch_addr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
1233b725ae77Skettenis   set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
1234b725ae77Skettenis 
1235b725ae77Skettenis   /* Should be using push_dummy_call.  */
1236b725ae77Skettenis   set_gdbarch_deprecated_dummy_write_sp (gdbarch, deprecated_write_sp);
1237b725ae77Skettenis 
1238b725ae77Skettenis   set_gdbarch_print_insn (gdbarch, print_insn_v850);
1239b725ae77Skettenis 
1240b725ae77Skettenis   return gdbarch;
1241b725ae77Skettenis }
1242b725ae77Skettenis 
1243b725ae77Skettenis extern initialize_file_ftype _initialize_v850_tdep; /* -Wmissing-prototypes */
1244b725ae77Skettenis 
1245b725ae77Skettenis void
_initialize_v850_tdep(void)1246b725ae77Skettenis _initialize_v850_tdep (void)
1247b725ae77Skettenis {
1248b725ae77Skettenis   register_gdbarch_init (bfd_arch_v850, v850_gdbarch_init);
1249b725ae77Skettenis }
1250