xref: /openbsd-src/gnu/usr.bin/binutils/gdb/xstormy16-tdep.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
1b725ae77Skettenis /* Target-dependent code for the Sanyo Xstormy16a (LC590000) processor.
2b725ae77Skettenis 
3b725ae77Skettenis    Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4b725ae77Skettenis 
5b725ae77Skettenis    This file is part of GDB.
6b725ae77Skettenis 
7b725ae77Skettenis    This program is free software; you can redistribute it and/or modify
8b725ae77Skettenis    it under the terms of the GNU General Public License as published by
9b725ae77Skettenis    the Free Software Foundation; either version 2 of the License, or
10b725ae77Skettenis    (at your option) any later version.
11b725ae77Skettenis 
12b725ae77Skettenis    This program is distributed in the hope that it will be useful,
13b725ae77Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
14b725ae77Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15b725ae77Skettenis    GNU General Public License for more details.
16b725ae77Skettenis 
17b725ae77Skettenis    You should have received a copy of the GNU General Public License
18b725ae77Skettenis    along with this program; if not, write to the Free Software
19b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
20b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
21b725ae77Skettenis 
22b725ae77Skettenis #include "defs.h"
23*11efff7fSkettenis #include "frame.h"
24*11efff7fSkettenis #include "frame-base.h"
25*11efff7fSkettenis #include "frame-unwind.h"
26*11efff7fSkettenis #include "dwarf2-frame.h"
27*11efff7fSkettenis #include "symtab.h"
28*11efff7fSkettenis #include "gdbtypes.h"
29*11efff7fSkettenis #include "gdbcmd.h"
30b725ae77Skettenis #include "gdbcore.h"
31*11efff7fSkettenis #include "value.h"
32b725ae77Skettenis #include "dis-asm.h"
33*11efff7fSkettenis #include "inferior.h"
34*11efff7fSkettenis #include "gdb_string.h"
35*11efff7fSkettenis #include "gdb_assert.h"
36*11efff7fSkettenis #include "arch-utils.h"
37*11efff7fSkettenis #include "floatformat.h"
38*11efff7fSkettenis #include "regcache.h"
39*11efff7fSkettenis #include "doublest.h"
40*11efff7fSkettenis #include "osabi.h"
41*11efff7fSkettenis #include "objfiles.h"
42b725ae77Skettenis 
43b725ae77Skettenis enum gdb_regnum
44b725ae77Skettenis {
45b725ae77Skettenis   /* Xstormy16 has 16 general purpose registers (R0-R15) plus PC.
46b725ae77Skettenis      Functions will return their values in register R2-R7 as they fit.
47b725ae77Skettenis      Otherwise a hidden pointer to an big enough area is given as argument
48b725ae77Skettenis      to the function in r2. Further arguments are beginning in r3 then.
49b725ae77Skettenis      R13 is used as frame pointer when GCC compiles w/o optimization
50b725ae77Skettenis      R14 is used as "PSW", displaying the CPU status.
51b725ae77Skettenis      R15 is used implicitely as stack pointer. */
52b725ae77Skettenis   E_R0_REGNUM,
53b725ae77Skettenis   E_R1_REGNUM,
54b725ae77Skettenis   E_R2_REGNUM, E_1ST_ARG_REGNUM = E_R2_REGNUM, E_PTR_RET_REGNUM = E_R2_REGNUM,
55b725ae77Skettenis   E_R3_REGNUM,
56b725ae77Skettenis   E_R4_REGNUM,
57b725ae77Skettenis   E_R5_REGNUM,
58b725ae77Skettenis   E_R6_REGNUM,
59b725ae77Skettenis   E_R7_REGNUM, E_LST_ARG_REGNUM = E_R7_REGNUM,
60b725ae77Skettenis   E_R8_REGNUM,
61b725ae77Skettenis   E_R9_REGNUM,
62b725ae77Skettenis   E_R10_REGNUM,
63b725ae77Skettenis   E_R11_REGNUM,
64b725ae77Skettenis   E_R12_REGNUM,
65b725ae77Skettenis   E_R13_REGNUM, E_FP_REGNUM = E_R13_REGNUM,
66b725ae77Skettenis   E_R14_REGNUM, E_PSW_REGNUM = E_R14_REGNUM,
67b725ae77Skettenis   E_R15_REGNUM, E_SP_REGNUM = E_R15_REGNUM,
68b725ae77Skettenis   E_PC_REGNUM,
69b725ae77Skettenis   E_NUM_REGS
70b725ae77Skettenis };
71b725ae77Skettenis 
72*11efff7fSkettenis /* Use an invalid address value as 'not available' marker.  */
73*11efff7fSkettenis enum { REG_UNAVAIL = (CORE_ADDR) -1 };
74*11efff7fSkettenis 
75*11efff7fSkettenis struct xstormy16_frame_cache
76*11efff7fSkettenis {
77*11efff7fSkettenis   /* Base address.  */
78*11efff7fSkettenis   CORE_ADDR base;
79*11efff7fSkettenis   CORE_ADDR pc;
80*11efff7fSkettenis   LONGEST framesize;
81*11efff7fSkettenis   int uses_fp;
82*11efff7fSkettenis   CORE_ADDR saved_regs[E_NUM_REGS];
83*11efff7fSkettenis   CORE_ADDR saved_sp;
84*11efff7fSkettenis };
85*11efff7fSkettenis 
86b725ae77Skettenis /* Size of instructions, registers, etc. */
87b725ae77Skettenis enum
88b725ae77Skettenis {
89b725ae77Skettenis   xstormy16_inst_size = 2,
90b725ae77Skettenis   xstormy16_reg_size = 2,
91b725ae77Skettenis   xstormy16_pc_size = 4
92b725ae77Skettenis };
93b725ae77Skettenis 
94b725ae77Skettenis /* Size of return datatype which fits into the remaining return registers. */
95b725ae77Skettenis #define E_MAX_RETTYPE_SIZE(regnum)	((E_LST_ARG_REGNUM - (regnum) + 1) \
96b725ae77Skettenis 					* xstormy16_reg_size)
97b725ae77Skettenis 
98b725ae77Skettenis /* Size of return datatype which fits into all return registers. */
99b725ae77Skettenis enum
100b725ae77Skettenis {
101b725ae77Skettenis   E_MAX_RETTYPE_SIZE_IN_REGS = E_MAX_RETTYPE_SIZE (E_R2_REGNUM)
102b725ae77Skettenis };
103b725ae77Skettenis 
104b725ae77Skettenis /* Function: xstormy16_register_name
105b725ae77Skettenis    Returns the name of the standard Xstormy16 register N.  */
106b725ae77Skettenis 
107b725ae77Skettenis static const char *
xstormy16_register_name(int regnum)108b725ae77Skettenis xstormy16_register_name (int regnum)
109b725ae77Skettenis {
110b725ae77Skettenis   static char *register_names[] = {
111b725ae77Skettenis     "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
112b725ae77Skettenis     "r8", "r9", "r10", "r11", "r12", "r13",
113b725ae77Skettenis     "psw", "sp", "pc"
114b725ae77Skettenis   };
115b725ae77Skettenis 
116*11efff7fSkettenis   if (regnum < 0 || regnum >= E_NUM_REGS)
117b725ae77Skettenis     internal_error (__FILE__, __LINE__,
118b725ae77Skettenis 		    "xstormy16_register_name: illegal register number %d",
119b725ae77Skettenis 		    regnum);
120b725ae77Skettenis   else
121b725ae77Skettenis     return register_names[regnum];
122b725ae77Skettenis 
123b725ae77Skettenis }
124b725ae77Skettenis 
125b725ae77Skettenis static struct type *
xstormy16_register_type(struct gdbarch * gdbarch,int regnum)126*11efff7fSkettenis xstormy16_register_type (struct gdbarch *gdbarch, int regnum)
127b725ae77Skettenis {
128*11efff7fSkettenis   if (regnum == E_PC_REGNUM)
129b725ae77Skettenis     return builtin_type_uint32;
130b725ae77Skettenis   else
131b725ae77Skettenis     return builtin_type_uint16;
132b725ae77Skettenis }
133b725ae77Skettenis 
134b725ae77Skettenis /* Function: xstormy16_type_is_scalar
135b725ae77Skettenis    Makes the decision if a given type is a scalar types.  Scalar
136b725ae77Skettenis    types are returned in the registers r2-r7 as they fit.  */
137b725ae77Skettenis 
138b725ae77Skettenis static int
xstormy16_type_is_scalar(struct type * t)139b725ae77Skettenis xstormy16_type_is_scalar (struct type *t)
140b725ae77Skettenis {
141b725ae77Skettenis   return (TYPE_CODE(t) != TYPE_CODE_STRUCT
142b725ae77Skettenis 	  && TYPE_CODE(t) != TYPE_CODE_UNION
143b725ae77Skettenis 	  && TYPE_CODE(t) != TYPE_CODE_ARRAY);
144b725ae77Skettenis }
145b725ae77Skettenis 
146*11efff7fSkettenis /* Function: xstormy16_use_struct_convention
147*11efff7fSkettenis    Returns non-zero if the given struct type will be returned using
148*11efff7fSkettenis    a special convention, rather than the normal function return method.
149*11efff7fSkettenis    7sed in the contexts of the "return" command, and of
150*11efff7fSkettenis    target function calls from the debugger.  */
151*11efff7fSkettenis 
152*11efff7fSkettenis static int
xstormy16_use_struct_convention(struct type * type)153*11efff7fSkettenis xstormy16_use_struct_convention (struct type *type)
154*11efff7fSkettenis {
155*11efff7fSkettenis   return !xstormy16_type_is_scalar (type)
156*11efff7fSkettenis 	 || TYPE_LENGTH (type) > E_MAX_RETTYPE_SIZE_IN_REGS;
157*11efff7fSkettenis }
158*11efff7fSkettenis 
159b725ae77Skettenis /* Function: xstormy16_extract_return_value
160*11efff7fSkettenis    Find a function's return value in the appropriate registers (in
161*11efff7fSkettenis    regbuf), and copy it into valbuf.  */
162b725ae77Skettenis 
163b725ae77Skettenis static void
xstormy16_extract_return_value(struct type * type,struct regcache * regcache,void * valbuf)164*11efff7fSkettenis xstormy16_extract_return_value (struct type *type, struct regcache *regcache,
165*11efff7fSkettenis 				void *valbuf)
166b725ae77Skettenis {
167*11efff7fSkettenis   int len = TYPE_LENGTH (type);
168*11efff7fSkettenis   int i, regnum = E_1ST_ARG_REGNUM;
169b725ae77Skettenis 
170*11efff7fSkettenis   for (i = 0; i < len; i += xstormy16_reg_size)
171*11efff7fSkettenis     regcache_raw_read (regcache, regnum++, (char *) valbuf + i);
172*11efff7fSkettenis }
173*11efff7fSkettenis 
174*11efff7fSkettenis /* Function: xstormy16_store_return_value
175*11efff7fSkettenis    Copy the function return value from VALBUF into the
176*11efff7fSkettenis    proper location for a function return.
177*11efff7fSkettenis    Called only in the context of the "return" command.  */
178*11efff7fSkettenis 
179*11efff7fSkettenis static void
xstormy16_store_return_value(struct type * type,struct regcache * regcache,const void * valbuf)180*11efff7fSkettenis xstormy16_store_return_value (struct type *type, struct regcache *regcache,
181*11efff7fSkettenis 			      const void *valbuf)
182b725ae77Skettenis {
183*11efff7fSkettenis   if (TYPE_LENGTH (type) == 1)
184*11efff7fSkettenis     {
185*11efff7fSkettenis       /* Add leading zeros to the value. */
186*11efff7fSkettenis       char buf[xstormy16_reg_size];
187*11efff7fSkettenis       memset (buf, 0, xstormy16_reg_size);
188*11efff7fSkettenis       memcpy (buf, valbuf, 1);
189*11efff7fSkettenis       regcache_raw_write (regcache, E_1ST_ARG_REGNUM, buf);
190b725ae77Skettenis     }
191b725ae77Skettenis   else
192b725ae77Skettenis     {
193*11efff7fSkettenis       int len = TYPE_LENGTH (type);
194*11efff7fSkettenis       int i, regnum = E_1ST_ARG_REGNUM;
195b725ae77Skettenis 
196*11efff7fSkettenis       for (i = 0; i < len; i += xstormy16_reg_size)
197*11efff7fSkettenis         regcache_raw_write (regcache, regnum++, (char *) valbuf + i);
198b725ae77Skettenis     }
199b725ae77Skettenis }
200b725ae77Skettenis 
201*11efff7fSkettenis static enum return_value_convention
xstormy16_return_value(struct gdbarch * gdbarch,struct type * type,struct regcache * regcache,void * readbuf,const void * writebuf)202*11efff7fSkettenis xstormy16_return_value (struct gdbarch *gdbarch, struct type *type,
203*11efff7fSkettenis 			struct regcache *regcache,
204*11efff7fSkettenis 			void *readbuf, const void *writebuf)
205*11efff7fSkettenis {
206*11efff7fSkettenis   if (xstormy16_use_struct_convention (type))
207*11efff7fSkettenis     return RETURN_VALUE_STRUCT_CONVENTION;
208*11efff7fSkettenis   if (writebuf)
209*11efff7fSkettenis     xstormy16_store_return_value (type, regcache, writebuf);
210*11efff7fSkettenis   else if (readbuf)
211*11efff7fSkettenis     xstormy16_extract_return_value (type, regcache, readbuf);
212*11efff7fSkettenis   return RETURN_VALUE_REGISTER_CONVENTION;
213*11efff7fSkettenis }
214b725ae77Skettenis 
215b725ae77Skettenis static CORE_ADDR
xstormy16_frame_align(struct gdbarch * gdbarch,CORE_ADDR addr)216*11efff7fSkettenis xstormy16_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
217*11efff7fSkettenis {
218*11efff7fSkettenis   if (addr & 1)
219*11efff7fSkettenis     ++addr;
220*11efff7fSkettenis   return addr;
221*11efff7fSkettenis }
222*11efff7fSkettenis 
223*11efff7fSkettenis /* Function: xstormy16_push_dummy_call
224*11efff7fSkettenis    Setup the function arguments for GDB to call a function in the inferior.
225*11efff7fSkettenis    Called only in the context of a target function call from the debugger.
226*11efff7fSkettenis    Returns the value of the SP register after the args are pushed.  */
227*11efff7fSkettenis 
228*11efff7fSkettenis static CORE_ADDR
xstormy16_push_dummy_call(struct gdbarch * gdbarch,struct value * function,struct regcache * regcache,CORE_ADDR bp_addr,int nargs,struct value ** args,CORE_ADDR sp,int struct_return,CORE_ADDR struct_addr)229*11efff7fSkettenis xstormy16_push_dummy_call (struct gdbarch *gdbarch,
230*11efff7fSkettenis 			   struct value *function,
231*11efff7fSkettenis 			   struct regcache *regcache,
232*11efff7fSkettenis 			   CORE_ADDR bp_addr, int nargs,
233*11efff7fSkettenis 			   struct value **args,
234*11efff7fSkettenis 			   CORE_ADDR sp, int struct_return,
235*11efff7fSkettenis 			   CORE_ADDR struct_addr)
236b725ae77Skettenis {
237b725ae77Skettenis   CORE_ADDR stack_dest = sp;
238b725ae77Skettenis   int argreg = E_1ST_ARG_REGNUM;
239b725ae77Skettenis   int i, j;
240b725ae77Skettenis   int typelen, slacklen;
241b725ae77Skettenis   char *val;
242*11efff7fSkettenis   char buf[xstormy16_pc_size];
243b725ae77Skettenis 
244b725ae77Skettenis   /* If struct_return is true, then the struct return address will
245b725ae77Skettenis      consume one argument-passing register.  */
246b725ae77Skettenis   if (struct_return)
247*11efff7fSkettenis     {
248*11efff7fSkettenis       regcache_cooked_write_unsigned (regcache, E_PTR_RET_REGNUM, struct_addr);
249b725ae77Skettenis       argreg++;
250*11efff7fSkettenis     }
251b725ae77Skettenis 
252b725ae77Skettenis   /* Arguments are passed in R2-R7 as they fit. If an argument doesn't
253b725ae77Skettenis      fit in the remaining registers we're switching over to the stack.
254b725ae77Skettenis      No argument is put on stack partially and as soon as we switched
255b725ae77Skettenis      over to stack no further argument is put in a register even if it
256b725ae77Skettenis      would fit in the remaining unused registers.  */
257b725ae77Skettenis   for (i = 0; i < nargs && argreg <= E_LST_ARG_REGNUM; i++)
258b725ae77Skettenis     {
259b725ae77Skettenis       typelen = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[i]));
260b725ae77Skettenis       if (typelen > E_MAX_RETTYPE_SIZE (argreg))
261b725ae77Skettenis 	break;
262b725ae77Skettenis 
263b725ae77Skettenis       /* Put argument into registers wordwise. */
264b725ae77Skettenis       val = VALUE_CONTENTS (args[i]);
265b725ae77Skettenis       for (j = 0; j < typelen; j += xstormy16_reg_size)
266*11efff7fSkettenis 	regcache_cooked_write_unsigned (regcache, argreg++,
267b725ae77Skettenis 			extract_unsigned_integer (val + j,
268b725ae77Skettenis 						  typelen - j ==
269b725ae77Skettenis 						  1 ? 1 :
270b725ae77Skettenis 						  xstormy16_reg_size));
271b725ae77Skettenis     }
272b725ae77Skettenis 
273b725ae77Skettenis   /* Align SP */
274*11efff7fSkettenis   stack_dest = xstormy16_frame_align (gdbarch, stack_dest);
275b725ae77Skettenis 
276b725ae77Skettenis   /* Loop backwards through remaining arguments and push them on the stack,
277b725ae77Skettenis      wordaligned.  */
278b725ae77Skettenis   for (j = nargs - 1; j >= i; j--)
279b725ae77Skettenis     {
280b725ae77Skettenis       typelen = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[j]));
281b725ae77Skettenis       slacklen = typelen & 1;
282b725ae77Skettenis       val = alloca (typelen + slacklen);
283b725ae77Skettenis       memcpy (val, VALUE_CONTENTS (args[j]), typelen);
284b725ae77Skettenis       memset (val + typelen, 0, slacklen);
285b725ae77Skettenis 
286b725ae77Skettenis       /* Now write this data to the stack. The stack grows upwards. */
287b725ae77Skettenis       write_memory (stack_dest, val, typelen + slacklen);
288b725ae77Skettenis       stack_dest += typelen + slacklen;
289b725ae77Skettenis     }
290b725ae77Skettenis 
291*11efff7fSkettenis   store_unsigned_integer (buf, xstormy16_pc_size, bp_addr);
292*11efff7fSkettenis   write_memory (stack_dest, buf, xstormy16_pc_size);
293*11efff7fSkettenis   stack_dest += xstormy16_pc_size;
294b725ae77Skettenis 
295*11efff7fSkettenis   /* Update stack pointer.  */
296*11efff7fSkettenis   regcache_cooked_write_unsigned (regcache, E_SP_REGNUM, stack_dest);
297b725ae77Skettenis 
298*11efff7fSkettenis   /* Return the new stack pointer minus the return address slot since
299*11efff7fSkettenis      that's what DWARF2/GCC uses as the frame's CFA.  */
300*11efff7fSkettenis   return stack_dest - xstormy16_pc_size;
301b725ae77Skettenis }
302b725ae77Skettenis 
303b725ae77Skettenis /* Function: xstormy16_scan_prologue
304b725ae77Skettenis    Decode the instructions within the given address range.
305b725ae77Skettenis    Decide when we must have reached the end of the function prologue.
306b725ae77Skettenis    If a frame_info pointer is provided, fill in its saved_regs etc.
307b725ae77Skettenis 
308*11efff7fSkettenis    Returns the address of the first instruction after the prologue.  */
309b725ae77Skettenis 
310b725ae77Skettenis static CORE_ADDR
xstormy16_analyze_prologue(CORE_ADDR start_addr,CORE_ADDR end_addr,struct xstormy16_frame_cache * cache,struct frame_info * next_frame)311*11efff7fSkettenis xstormy16_analyze_prologue (CORE_ADDR start_addr, CORE_ADDR end_addr,
312*11efff7fSkettenis 			    struct xstormy16_frame_cache *cache,
313*11efff7fSkettenis 			    struct frame_info *next_frame)
314b725ae77Skettenis {
315b725ae77Skettenis   CORE_ADDR next_addr;
316b725ae77Skettenis   ULONGEST inst, inst2;
317b725ae77Skettenis   LONGEST offset;
318b725ae77Skettenis   int regnum;
319b725ae77Skettenis 
320b725ae77Skettenis   /* Initialize framesize with size of PC put on stack by CALLF inst. */
321*11efff7fSkettenis   cache->saved_regs[E_PC_REGNUM] = 0;
322*11efff7fSkettenis   cache->framesize = xstormy16_pc_size;
323*11efff7fSkettenis 
324*11efff7fSkettenis   if (start_addr >= end_addr)
325*11efff7fSkettenis     return end_addr;
326*11efff7fSkettenis 
327b725ae77Skettenis   for (next_addr = start_addr;
328b725ae77Skettenis        next_addr < end_addr; next_addr += xstormy16_inst_size)
329b725ae77Skettenis     {
330b725ae77Skettenis       inst = read_memory_unsigned_integer (next_addr, xstormy16_inst_size);
331b725ae77Skettenis       inst2 = read_memory_unsigned_integer (next_addr + xstormy16_inst_size,
332b725ae77Skettenis 					    xstormy16_inst_size);
333b725ae77Skettenis 
334b725ae77Skettenis       if (inst >= 0x0082 && inst <= 0x008d)	/* push r2 .. push r13 */
335b725ae77Skettenis 	{
336b725ae77Skettenis 	  regnum = inst & 0x000f;
337*11efff7fSkettenis 	  cache->saved_regs[regnum] = cache->framesize;
338*11efff7fSkettenis 	  cache->framesize += xstormy16_reg_size;
339b725ae77Skettenis 	}
340b725ae77Skettenis 
341b725ae77Skettenis       /* optional stack allocation for args and local vars <= 4 byte */
342b725ae77Skettenis       else if (inst == 0x301f || inst == 0x303f)	/* inc r15, #0x1/#0x3 */
343b725ae77Skettenis 	{
344*11efff7fSkettenis 	  cache->framesize += ((inst & 0x0030) >> 4) + 1;
345b725ae77Skettenis 	}
346b725ae77Skettenis 
347b725ae77Skettenis       /* optional stack allocation for args and local vars > 4 && < 16 byte */
348b725ae77Skettenis       else if ((inst & 0xff0f) == 0x510f)	/* 51Hf   add r15, #0xH */
349b725ae77Skettenis 	{
350*11efff7fSkettenis 	  cache->framesize += (inst & 0x00f0) >> 4;
351b725ae77Skettenis 	}
352b725ae77Skettenis 
353b725ae77Skettenis       /* optional stack allocation for args and local vars >= 16 byte */
354b725ae77Skettenis       else if (inst == 0x314f && inst2 >= 0x0010)	/* 314f HHHH  add r15, #0xH */
355b725ae77Skettenis 	{
356*11efff7fSkettenis 	  cache->framesize += inst2;
357b725ae77Skettenis 	  next_addr += xstormy16_inst_size;
358b725ae77Skettenis 	}
359b725ae77Skettenis 
360b725ae77Skettenis       else if (inst == 0x46fd)	/* mov r13, r15 */
361b725ae77Skettenis 	{
362*11efff7fSkettenis 	  cache->uses_fp = 1;
363b725ae77Skettenis 	}
364b725ae77Skettenis 
365b725ae77Skettenis       /* optional copying of args in r2-r7 to r10-r13 */
366b725ae77Skettenis       /* Probably only in optimized case but legal action for prologue */
367b725ae77Skettenis       else if ((inst & 0xff00) == 0x4600	/* 46SD   mov rD, rS */
368b725ae77Skettenis 	       && (inst & 0x00f0) >= 0x0020 && (inst & 0x00f0) <= 0x0070
369b725ae77Skettenis 	       && (inst & 0x000f) >= 0x00a0 && (inst & 0x000f) <= 0x000d)
370b725ae77Skettenis 	;
371b725ae77Skettenis 
372b725ae77Skettenis       /* optional copying of args in r2-r7 to stack */
373b725ae77Skettenis       /* 72DS HHHH   mov.b (rD, 0xHHHH), r(S-8) (bit3 always 1, bit2-0 = reg) */
374b725ae77Skettenis       /* 73DS HHHH   mov.w (rD, 0xHHHH), r(S-8) */
375b725ae77Skettenis       else if ((inst & 0xfed8) == 0x72d8 && (inst & 0x0007) >= 2)
376b725ae77Skettenis 	{
377b725ae77Skettenis 	  regnum = inst & 0x0007;
378b725ae77Skettenis 	  /* Only 12 of 16 bits of the argument are used for the
379b725ae77Skettenis 	     signed offset. */
380b725ae77Skettenis 	  offset = (LONGEST) (inst2 & 0x0fff);
381b725ae77Skettenis 	  if (offset & 0x0800)
382b725ae77Skettenis 	    offset -= 0x1000;
383b725ae77Skettenis 
384*11efff7fSkettenis 	  cache->saved_regs[regnum] = cache->framesize + offset;
385b725ae77Skettenis 	  next_addr += xstormy16_inst_size;
386b725ae77Skettenis 	}
387b725ae77Skettenis 
388b725ae77Skettenis       else			/* Not a prologue instruction. */
389b725ae77Skettenis 	break;
390b725ae77Skettenis     }
391b725ae77Skettenis 
392b725ae77Skettenis   return next_addr;
393b725ae77Skettenis }
394b725ae77Skettenis 
395b725ae77Skettenis /* Function: xstormy16_skip_prologue
396b725ae77Skettenis    If the input address is in a function prologue,
397b725ae77Skettenis    returns the address of the end of the prologue;
398b725ae77Skettenis    else returns the input address.
399b725ae77Skettenis 
400b725ae77Skettenis    Note: the input address is likely to be the function start,
401b725ae77Skettenis    since this function is mainly used for advancing a breakpoint
402b725ae77Skettenis    to the first line, or stepping to the first line when we have
403b725ae77Skettenis    stepped into a function call.  */
404b725ae77Skettenis 
405b725ae77Skettenis static CORE_ADDR
xstormy16_skip_prologue(CORE_ADDR pc)406b725ae77Skettenis xstormy16_skip_prologue (CORE_ADDR pc)
407b725ae77Skettenis {
408b725ae77Skettenis   CORE_ADDR func_addr = 0, func_end = 0;
409b725ae77Skettenis   char *func_name;
410b725ae77Skettenis 
411b725ae77Skettenis   if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end))
412b725ae77Skettenis     {
413b725ae77Skettenis       struct symtab_and_line sal;
414b725ae77Skettenis       struct symbol *sym;
415*11efff7fSkettenis       struct xstormy16_frame_cache cache;
416b725ae77Skettenis 
417b725ae77Skettenis       /* Don't trust line number debug info in frameless functions. */
418*11efff7fSkettenis       CORE_ADDR plg_end = xstormy16_analyze_prologue (func_addr, func_end,
419*11efff7fSkettenis 						      &cache, NULL);
420*11efff7fSkettenis       if (!cache.uses_fp)
421b725ae77Skettenis         return plg_end;
422b725ae77Skettenis 
423b725ae77Skettenis       /* Found a function.  */
424b725ae77Skettenis       sym = lookup_symbol (func_name, NULL, VAR_DOMAIN, NULL, NULL);
425b725ae77Skettenis       /* Don't use line number debug info for assembly source files. */
426b725ae77Skettenis       if (sym && SYMBOL_LANGUAGE (sym) != language_asm)
427b725ae77Skettenis 	{
428b725ae77Skettenis 	  sal = find_pc_line (func_addr, 0);
429b725ae77Skettenis 	  if (sal.end && sal.end < func_end)
430b725ae77Skettenis 	    {
431b725ae77Skettenis 	      /* Found a line number, use it as end of prologue.  */
432b725ae77Skettenis 	      return sal.end;
433b725ae77Skettenis 	    }
434b725ae77Skettenis 	}
435b725ae77Skettenis       /* No useable line symbol.  Use result of prologue parsing method. */
436b725ae77Skettenis       return plg_end;
437b725ae77Skettenis     }
438b725ae77Skettenis 
439b725ae77Skettenis   /* No function symbol -- just return the PC. */
440b725ae77Skettenis 
441b725ae77Skettenis   return (CORE_ADDR) pc;
442b725ae77Skettenis }
443b725ae77Skettenis 
444b725ae77Skettenis /* The epilogue is defined here as the area at the end of a function,
445b725ae77Skettenis    either on the `ret' instruction itself or after an instruction which
446b725ae77Skettenis    destroys the function's stack frame. */
447b725ae77Skettenis static int
xstormy16_in_function_epilogue_p(struct gdbarch * gdbarch,CORE_ADDR pc)448b725ae77Skettenis xstormy16_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
449b725ae77Skettenis {
450*11efff7fSkettenis   CORE_ADDR func_addr = 0, func_end = 0;
451b725ae77Skettenis 
452b725ae77Skettenis   if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
453b725ae77Skettenis     {
454b725ae77Skettenis       ULONGEST inst, inst2;
455b725ae77Skettenis       CORE_ADDR addr = func_end - xstormy16_inst_size;
456b725ae77Skettenis 
457b725ae77Skettenis       /* The Xstormy16 epilogue is max. 14 bytes long. */
458b725ae77Skettenis       if (pc < func_end - 7 * xstormy16_inst_size)
459b725ae77Skettenis 	return 0;
460b725ae77Skettenis 
461b725ae77Skettenis       /* Check if we're on a `ret' instruction.  Otherwise it's
462b725ae77Skettenis          too dangerous to proceed. */
463b725ae77Skettenis       inst = read_memory_unsigned_integer (addr, xstormy16_inst_size);
464b725ae77Skettenis       if (inst != 0x0003)
465b725ae77Skettenis 	return 0;
466b725ae77Skettenis 
467b725ae77Skettenis       while ((addr -= xstormy16_inst_size) >= func_addr)
468b725ae77Skettenis 	{
469b725ae77Skettenis 	  inst = read_memory_unsigned_integer (addr, xstormy16_inst_size);
470b725ae77Skettenis 	  if (inst >= 0x009a && inst <= 0x009d)	/* pop r10...r13 */
471b725ae77Skettenis 	    continue;
472b725ae77Skettenis 	  if (inst == 0x305f || inst == 0x307f)	/* dec r15, #0x1/#0x3 */
473b725ae77Skettenis 	    break;
474b725ae77Skettenis 	  inst2 = read_memory_unsigned_integer (addr - xstormy16_inst_size,
475b725ae77Skettenis 						xstormy16_inst_size);
476b725ae77Skettenis 	  if (inst2 == 0x314f && inst >= 0x8000)	/* add r15, neg. value */
477b725ae77Skettenis 	    {
478b725ae77Skettenis 	      addr -= xstormy16_inst_size;
479b725ae77Skettenis 	      break;
480b725ae77Skettenis 	    }
481b725ae77Skettenis 	  return 0;
482b725ae77Skettenis 	}
483b725ae77Skettenis       if (pc > addr)
484b725ae77Skettenis 	return 1;
485b725ae77Skettenis     }
486b725ae77Skettenis   return 0;
487b725ae77Skettenis }
488b725ae77Skettenis 
489b725ae77Skettenis const static unsigned char *
xstormy16_breakpoint_from_pc(CORE_ADDR * pcptr,int * lenptr)490b725ae77Skettenis xstormy16_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
491b725ae77Skettenis {
492b725ae77Skettenis   static unsigned char breakpoint[] = { 0x06, 0x0 };
493b725ae77Skettenis   *lenptr = sizeof (breakpoint);
494b725ae77Skettenis   return breakpoint;
495b725ae77Skettenis }
496b725ae77Skettenis 
497b725ae77Skettenis /* Given a pointer to a jump table entry, return the address
498b725ae77Skettenis    of the function it jumps to.  Return 0 if not found. */
499b725ae77Skettenis static CORE_ADDR
xstormy16_resolve_jmp_table_entry(CORE_ADDR faddr)500b725ae77Skettenis xstormy16_resolve_jmp_table_entry (CORE_ADDR faddr)
501b725ae77Skettenis {
502b725ae77Skettenis   struct obj_section *faddr_sect = find_pc_section (faddr);
503b725ae77Skettenis 
504b725ae77Skettenis   if (faddr_sect)
505b725ae77Skettenis     {
506b725ae77Skettenis       LONGEST inst, inst2, addr;
507b725ae77Skettenis       char buf[2 * xstormy16_inst_size];
508b725ae77Skettenis 
509b725ae77Skettenis       /* Return faddr if it's not pointing into the jump table. */
510b725ae77Skettenis       if (strcmp (faddr_sect->the_bfd_section->name, ".plt"))
511b725ae77Skettenis 	return faddr;
512b725ae77Skettenis 
513b725ae77Skettenis       if (!target_read_memory (faddr, buf, sizeof buf))
514b725ae77Skettenis 	{
515b725ae77Skettenis 	  inst = extract_unsigned_integer (buf, xstormy16_inst_size);
516b725ae77Skettenis 	  inst2 = extract_unsigned_integer (buf + xstormy16_inst_size,
517b725ae77Skettenis 					    xstormy16_inst_size);
518b725ae77Skettenis 	  addr = inst2 << 8 | (inst & 0xff);
519b725ae77Skettenis 	  return addr;
520b725ae77Skettenis 	}
521b725ae77Skettenis     }
522b725ae77Skettenis   return 0;
523b725ae77Skettenis }
524b725ae77Skettenis 
525b725ae77Skettenis /* Given a function's address, attempt to find (and return) the
526b725ae77Skettenis    address of the corresponding jump table entry.  Return 0 if
527b725ae77Skettenis    not found. */
528b725ae77Skettenis static CORE_ADDR
xstormy16_find_jmp_table_entry(CORE_ADDR faddr)529b725ae77Skettenis xstormy16_find_jmp_table_entry (CORE_ADDR faddr)
530b725ae77Skettenis {
531b725ae77Skettenis   struct obj_section *faddr_sect = find_pc_section (faddr);
532b725ae77Skettenis 
533b725ae77Skettenis   if (faddr_sect)
534b725ae77Skettenis     {
535b725ae77Skettenis       struct obj_section *osect;
536b725ae77Skettenis 
537b725ae77Skettenis       /* Return faddr if it's already a pointer to a jump table entry. */
538b725ae77Skettenis       if (!strcmp (faddr_sect->the_bfd_section->name, ".plt"))
539b725ae77Skettenis 	return faddr;
540b725ae77Skettenis 
541b725ae77Skettenis       ALL_OBJFILE_OSECTIONS (faddr_sect->objfile, osect)
542b725ae77Skettenis       {
543b725ae77Skettenis 	if (!strcmp (osect->the_bfd_section->name, ".plt"))
544b725ae77Skettenis 	  break;
545b725ae77Skettenis       }
546b725ae77Skettenis 
547b725ae77Skettenis       if (osect < faddr_sect->objfile->sections_end)
548b725ae77Skettenis 	{
549b725ae77Skettenis 	  CORE_ADDR addr;
550b725ae77Skettenis 	  for (addr = osect->addr;
551b725ae77Skettenis 	       addr < osect->endaddr; addr += 2 * xstormy16_inst_size)
552b725ae77Skettenis 	    {
553b725ae77Skettenis 	      LONGEST inst, inst2, faddr2;
554b725ae77Skettenis 	      char buf[2 * xstormy16_inst_size];
555b725ae77Skettenis 
556b725ae77Skettenis 	      if (target_read_memory (addr, buf, sizeof buf))
557b725ae77Skettenis 		return 0;
558b725ae77Skettenis 	      inst = extract_unsigned_integer (buf, xstormy16_inst_size);
559b725ae77Skettenis 	      inst2 = extract_unsigned_integer (buf + xstormy16_inst_size,
560b725ae77Skettenis 						xstormy16_inst_size);
561b725ae77Skettenis 	      faddr2 = inst2 << 8 | (inst & 0xff);
562b725ae77Skettenis 	      if (faddr == faddr2)
563b725ae77Skettenis 		return addr;
564b725ae77Skettenis 	    }
565b725ae77Skettenis 	}
566b725ae77Skettenis     }
567b725ae77Skettenis   return 0;
568b725ae77Skettenis }
569b725ae77Skettenis 
570b725ae77Skettenis static CORE_ADDR
xstormy16_skip_trampoline_code(CORE_ADDR pc)571b725ae77Skettenis xstormy16_skip_trampoline_code (CORE_ADDR pc)
572b725ae77Skettenis {
573*11efff7fSkettenis   CORE_ADDR tmp = xstormy16_resolve_jmp_table_entry (pc);
574b725ae77Skettenis 
575b725ae77Skettenis   if (tmp && tmp != pc)
576b725ae77Skettenis     return tmp;
577b725ae77Skettenis   return 0;
578b725ae77Skettenis }
579b725ae77Skettenis 
580b725ae77Skettenis static int
xstormy16_in_solib_call_trampoline(CORE_ADDR pc,char * name)581b725ae77Skettenis xstormy16_in_solib_call_trampoline (CORE_ADDR pc, char *name)
582b725ae77Skettenis {
583b725ae77Skettenis   return xstormy16_skip_trampoline_code (pc) != 0;
584b725ae77Skettenis }
585b725ae77Skettenis 
586*11efff7fSkettenis /* Function pointers are 16 bit.  The address space is 24 bit, using
587*11efff7fSkettenis    32 bit addresses.  Pointers to functions on the XStormy16 are implemented
588*11efff7fSkettenis    by using 16 bit pointers, which are either direct pointers in case the
589*11efff7fSkettenis    function begins below 0x10000, or indirect pointers into a jump table.
590*11efff7fSkettenis    The next two functions convert 16 bit pointers into 24 (32) bit addresses
591*11efff7fSkettenis    and vice versa.  */
592*11efff7fSkettenis 
593b725ae77Skettenis static CORE_ADDR
xstormy16_pointer_to_address(struct type * type,const void * buf)594b725ae77Skettenis xstormy16_pointer_to_address (struct type *type, const void *buf)
595b725ae77Skettenis {
596b725ae77Skettenis   enum type_code target = TYPE_CODE (TYPE_TARGET_TYPE (type));
597b725ae77Skettenis   CORE_ADDR addr = extract_unsigned_integer (buf, TYPE_LENGTH (type));
598b725ae77Skettenis 
599b725ae77Skettenis   if (target == TYPE_CODE_FUNC || target == TYPE_CODE_METHOD)
600b725ae77Skettenis     {
601b725ae77Skettenis       CORE_ADDR addr2 = xstormy16_resolve_jmp_table_entry (addr);
602b725ae77Skettenis       if (addr2)
603b725ae77Skettenis 	addr = addr2;
604b725ae77Skettenis     }
605b725ae77Skettenis 
606b725ae77Skettenis   return addr;
607b725ae77Skettenis }
608b725ae77Skettenis 
609b725ae77Skettenis static void
xstormy16_address_to_pointer(struct type * type,void * buf,CORE_ADDR addr)610b725ae77Skettenis xstormy16_address_to_pointer (struct type *type, void *buf, CORE_ADDR addr)
611b725ae77Skettenis {
612b725ae77Skettenis   enum type_code target = TYPE_CODE (TYPE_TARGET_TYPE (type));
613b725ae77Skettenis 
614b725ae77Skettenis   if (target == TYPE_CODE_FUNC || target == TYPE_CODE_METHOD)
615b725ae77Skettenis     {
616b725ae77Skettenis       CORE_ADDR addr2 = xstormy16_find_jmp_table_entry (addr);
617b725ae77Skettenis       if (addr2)
618b725ae77Skettenis 	addr = addr2;
619b725ae77Skettenis     }
620b725ae77Skettenis   store_unsigned_integer (buf, TYPE_LENGTH (type), addr);
621b725ae77Skettenis }
622b725ae77Skettenis 
623*11efff7fSkettenis static struct xstormy16_frame_cache *
xstormy16_alloc_frame_cache(void)624*11efff7fSkettenis xstormy16_alloc_frame_cache (void)
625b725ae77Skettenis {
626*11efff7fSkettenis   struct xstormy16_frame_cache *cache;
627*11efff7fSkettenis   int i;
628*11efff7fSkettenis 
629*11efff7fSkettenis   cache = FRAME_OBSTACK_ZALLOC (struct xstormy16_frame_cache);
630*11efff7fSkettenis 
631*11efff7fSkettenis   cache->base = 0;
632*11efff7fSkettenis   cache->saved_sp = 0;
633*11efff7fSkettenis   cache->pc = 0;
634*11efff7fSkettenis   cache->uses_fp = 0;
635*11efff7fSkettenis   cache->framesize = 0;
636*11efff7fSkettenis   for (i = 0; i < E_NUM_REGS; ++i)
637*11efff7fSkettenis     cache->saved_regs[i] = REG_UNAVAIL;
638*11efff7fSkettenis 
639*11efff7fSkettenis   return cache;
640*11efff7fSkettenis }
641*11efff7fSkettenis 
642*11efff7fSkettenis static struct xstormy16_frame_cache *
xstormy16_frame_cache(struct frame_info * next_frame,void ** this_cache)643*11efff7fSkettenis xstormy16_frame_cache (struct frame_info *next_frame, void **this_cache)
644*11efff7fSkettenis {
645*11efff7fSkettenis   struct xstormy16_frame_cache *cache;
646*11efff7fSkettenis   CORE_ADDR current_pc;
647*11efff7fSkettenis   int i;
648*11efff7fSkettenis 
649*11efff7fSkettenis   if (*this_cache)
650*11efff7fSkettenis     return *this_cache;
651*11efff7fSkettenis 
652*11efff7fSkettenis   cache = xstormy16_alloc_frame_cache ();
653*11efff7fSkettenis   *this_cache = cache;
654*11efff7fSkettenis 
655*11efff7fSkettenis   cache->base = frame_unwind_register_unsigned (next_frame, E_FP_REGNUM);
656*11efff7fSkettenis   if (cache->base == 0)
657*11efff7fSkettenis     return cache;
658*11efff7fSkettenis 
659*11efff7fSkettenis   cache->pc = frame_func_unwind (next_frame);
660*11efff7fSkettenis   current_pc = frame_pc_unwind (next_frame);
661*11efff7fSkettenis   if (cache->pc)
662*11efff7fSkettenis     xstormy16_analyze_prologue (cache->pc, current_pc, cache, next_frame);
663*11efff7fSkettenis 
664*11efff7fSkettenis   if (!cache->uses_fp)
665*11efff7fSkettenis     cache->base = frame_unwind_register_unsigned (next_frame, E_SP_REGNUM);
666*11efff7fSkettenis 
667*11efff7fSkettenis   cache->saved_sp = cache->base - cache->framesize;
668*11efff7fSkettenis 
669*11efff7fSkettenis   for (i = 0; i < E_NUM_REGS; ++i)
670*11efff7fSkettenis     if (cache->saved_regs[i] != REG_UNAVAIL)
671*11efff7fSkettenis       cache->saved_regs[i] += cache->saved_sp;
672*11efff7fSkettenis 
673*11efff7fSkettenis   return cache;
674b725ae77Skettenis }
675b725ae77Skettenis 
676b725ae77Skettenis static void
xstormy16_frame_prev_register(struct frame_info * next_frame,void ** this_cache,int regnum,int * optimizedp,enum lval_type * lvalp,CORE_ADDR * addrp,int * realnump,void * valuep)677*11efff7fSkettenis xstormy16_frame_prev_register (struct frame_info *next_frame, void **this_cache,
678*11efff7fSkettenis 			       int regnum, int *optimizedp,
679*11efff7fSkettenis 			       enum lval_type *lvalp, CORE_ADDR *addrp,
680*11efff7fSkettenis 			       int *realnump, void *valuep)
681b725ae77Skettenis {
682*11efff7fSkettenis   struct xstormy16_frame_cache *cache = xstormy16_frame_cache (next_frame,
683*11efff7fSkettenis                                                                this_cache);
684*11efff7fSkettenis   gdb_assert (regnum >= 0);
685*11efff7fSkettenis 
686*11efff7fSkettenis   if (regnum == E_SP_REGNUM && cache->saved_sp)
687*11efff7fSkettenis     {
688*11efff7fSkettenis       *optimizedp = 0;
689*11efff7fSkettenis       *lvalp = not_lval;
690*11efff7fSkettenis       *addrp = 0;
691*11efff7fSkettenis       *realnump = -1;
692*11efff7fSkettenis       if (valuep)
693*11efff7fSkettenis         {
694*11efff7fSkettenis           /* Store the value.  */
695*11efff7fSkettenis           store_unsigned_integer (valuep, xstormy16_reg_size, cache->saved_sp);
696b725ae77Skettenis         }
697*11efff7fSkettenis       return;
698*11efff7fSkettenis     }
699*11efff7fSkettenis 
700*11efff7fSkettenis   if (regnum < E_NUM_REGS && cache->saved_regs[regnum] != REG_UNAVAIL)
701*11efff7fSkettenis     {
702*11efff7fSkettenis       *optimizedp = 0;
703*11efff7fSkettenis       *lvalp = lval_memory;
704*11efff7fSkettenis       *addrp = cache->saved_regs[regnum];
705*11efff7fSkettenis       *realnump = -1;
706*11efff7fSkettenis       if (valuep)
707*11efff7fSkettenis         {
708*11efff7fSkettenis           /* Read the value in from memory.  */
709*11efff7fSkettenis           read_memory (*addrp, valuep,
710*11efff7fSkettenis                        register_size (current_gdbarch, regnum));
711*11efff7fSkettenis         }
712*11efff7fSkettenis       return;
713*11efff7fSkettenis     }
714*11efff7fSkettenis 
715*11efff7fSkettenis   frame_register_unwind (next_frame, regnum,
716*11efff7fSkettenis                          optimizedp, lvalp, addrp, realnump, valuep);
717*11efff7fSkettenis }
718*11efff7fSkettenis 
719*11efff7fSkettenis static void
xstormy16_frame_this_id(struct frame_info * next_frame,void ** this_cache,struct frame_id * this_id)720*11efff7fSkettenis xstormy16_frame_this_id (struct frame_info *next_frame, void **this_cache,
721*11efff7fSkettenis 			 struct frame_id *this_id)
722*11efff7fSkettenis {
723*11efff7fSkettenis   struct xstormy16_frame_cache *cache = xstormy16_frame_cache (next_frame,
724*11efff7fSkettenis 							       this_cache);
725*11efff7fSkettenis 
726*11efff7fSkettenis   /* This marks the outermost frame.  */
727*11efff7fSkettenis   if (cache->base == 0)
728*11efff7fSkettenis     return;
729*11efff7fSkettenis 
730*11efff7fSkettenis   *this_id = frame_id_build (cache->saved_sp, cache->pc);
731*11efff7fSkettenis }
732*11efff7fSkettenis 
733*11efff7fSkettenis static CORE_ADDR
xstormy16_frame_base_address(struct frame_info * next_frame,void ** this_cache)734*11efff7fSkettenis xstormy16_frame_base_address (struct frame_info *next_frame, void **this_cache)
735*11efff7fSkettenis {
736*11efff7fSkettenis   struct xstormy16_frame_cache *cache = xstormy16_frame_cache (next_frame,
737*11efff7fSkettenis 							       this_cache);
738*11efff7fSkettenis   return cache->base;
739*11efff7fSkettenis }
740*11efff7fSkettenis 
741*11efff7fSkettenis static const struct frame_unwind xstormy16_frame_unwind = {
742*11efff7fSkettenis   NORMAL_FRAME,
743*11efff7fSkettenis   xstormy16_frame_this_id,
744*11efff7fSkettenis   xstormy16_frame_prev_register
745*11efff7fSkettenis };
746*11efff7fSkettenis 
747*11efff7fSkettenis static const struct frame_base xstormy16_frame_base = {
748*11efff7fSkettenis   &xstormy16_frame_unwind,
749*11efff7fSkettenis   xstormy16_frame_base_address,
750*11efff7fSkettenis   xstormy16_frame_base_address,
751*11efff7fSkettenis   xstormy16_frame_base_address
752*11efff7fSkettenis };
753*11efff7fSkettenis 
754*11efff7fSkettenis static const struct frame_unwind *
xstormy16_frame_sniffer(struct frame_info * next_frame)755*11efff7fSkettenis xstormy16_frame_sniffer (struct frame_info *next_frame)
756*11efff7fSkettenis {
757*11efff7fSkettenis   return &xstormy16_frame_unwind;
758*11efff7fSkettenis }
759*11efff7fSkettenis 
760*11efff7fSkettenis static CORE_ADDR
xstormy16_unwind_sp(struct gdbarch * gdbarch,struct frame_info * next_frame)761*11efff7fSkettenis xstormy16_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
762*11efff7fSkettenis {
763*11efff7fSkettenis   return frame_unwind_register_unsigned (next_frame, E_SP_REGNUM);
764*11efff7fSkettenis }
765*11efff7fSkettenis 
766*11efff7fSkettenis static CORE_ADDR
xstormy16_unwind_pc(struct gdbarch * gdbarch,struct frame_info * next_frame)767*11efff7fSkettenis xstormy16_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
768*11efff7fSkettenis {
769*11efff7fSkettenis   return frame_unwind_register_unsigned (next_frame, E_PC_REGNUM);
770*11efff7fSkettenis }
771*11efff7fSkettenis 
772*11efff7fSkettenis static struct frame_id
xstormy16_unwind_dummy_id(struct gdbarch * gdbarch,struct frame_info * next_frame)773*11efff7fSkettenis xstormy16_unwind_dummy_id (struct gdbarch *gdbarch,
774*11efff7fSkettenis 			   struct frame_info *next_frame)
775*11efff7fSkettenis {
776*11efff7fSkettenis   return frame_id_build (xstormy16_unwind_sp (gdbarch, next_frame),
777*11efff7fSkettenis 			 frame_pc_unwind (next_frame));
778*11efff7fSkettenis }
779*11efff7fSkettenis 
780b725ae77Skettenis 
781b725ae77Skettenis /* Function: xstormy16_gdbarch_init
782b725ae77Skettenis    Initializer function for the xstormy16 gdbarch vector.
783b725ae77Skettenis    Called by gdbarch.  Sets up the gdbarch vector(s) for this target. */
784b725ae77Skettenis 
785b725ae77Skettenis static struct gdbarch *
xstormy16_gdbarch_init(struct gdbarch_info info,struct gdbarch_list * arches)786b725ae77Skettenis xstormy16_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
787b725ae77Skettenis {
788b725ae77Skettenis   struct gdbarch *gdbarch;
789b725ae77Skettenis 
790b725ae77Skettenis   /* find a candidate among the list of pre-declared architectures. */
791b725ae77Skettenis   arches = gdbarch_list_lookup_by_info (arches, &info);
792b725ae77Skettenis   if (arches != NULL)
793b725ae77Skettenis     return (arches->gdbarch);
794b725ae77Skettenis 
795*11efff7fSkettenis   gdbarch = gdbarch_alloc (&info, NULL);
796b725ae77Skettenis 
797b725ae77Skettenis   /*
798*11efff7fSkettenis    * Basic register fields and methods, datatype sizes and stuff.
799b725ae77Skettenis    */
800b725ae77Skettenis 
801b725ae77Skettenis   set_gdbarch_num_regs (gdbarch, E_NUM_REGS);
802b725ae77Skettenis   set_gdbarch_num_pseudo_regs (gdbarch, 0);
803b725ae77Skettenis   set_gdbarch_sp_regnum (gdbarch, E_SP_REGNUM);
804b725ae77Skettenis   set_gdbarch_pc_regnum (gdbarch, E_PC_REGNUM);
805b725ae77Skettenis   set_gdbarch_register_name (gdbarch, xstormy16_register_name);
806*11efff7fSkettenis   set_gdbarch_register_type (gdbarch, xstormy16_register_type);
807b725ae77Skettenis 
808b725ae77Skettenis   set_gdbarch_char_signed (gdbarch, 0);
809*11efff7fSkettenis   set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
810b725ae77Skettenis   set_gdbarch_int_bit (gdbarch, 2 * TARGET_CHAR_BIT);
811*11efff7fSkettenis   set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
812*11efff7fSkettenis   set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
813*11efff7fSkettenis 
814*11efff7fSkettenis   set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT);
815*11efff7fSkettenis   set_gdbarch_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
816*11efff7fSkettenis   set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
817*11efff7fSkettenis 
818b725ae77Skettenis   set_gdbarch_ptr_bit (gdbarch, 2 * TARGET_CHAR_BIT);
819b725ae77Skettenis   set_gdbarch_addr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
820b725ae77Skettenis 
821b725ae77Skettenis   set_gdbarch_address_to_pointer (gdbarch, xstormy16_address_to_pointer);
822b725ae77Skettenis   set_gdbarch_pointer_to_address (gdbarch, xstormy16_pointer_to_address);
823b725ae77Skettenis 
824*11efff7fSkettenis   set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
825b725ae77Skettenis 
826*11efff7fSkettenis   /* Stack grows up. */
827*11efff7fSkettenis   set_gdbarch_inner_than (gdbarch, core_addr_greaterthan);
828*11efff7fSkettenis 
829*11efff7fSkettenis   /*
830*11efff7fSkettenis    * Frame Info
831*11efff7fSkettenis    */
832*11efff7fSkettenis   set_gdbarch_unwind_sp (gdbarch, xstormy16_unwind_sp);
833*11efff7fSkettenis   set_gdbarch_unwind_pc (gdbarch, xstormy16_unwind_pc);
834*11efff7fSkettenis   set_gdbarch_unwind_dummy_id (gdbarch, xstormy16_unwind_dummy_id);
835*11efff7fSkettenis   set_gdbarch_frame_align (gdbarch, xstormy16_frame_align);
836*11efff7fSkettenis   frame_base_set_default (gdbarch, &xstormy16_frame_base);
837*11efff7fSkettenis 
838*11efff7fSkettenis   set_gdbarch_skip_prologue (gdbarch, xstormy16_skip_prologue);
839*11efff7fSkettenis   set_gdbarch_in_function_epilogue_p (gdbarch,
840*11efff7fSkettenis 				      xstormy16_in_function_epilogue_p);
841*11efff7fSkettenis 
842*11efff7fSkettenis   /* These values and methods are used when gdb calls a target function.  */
843*11efff7fSkettenis   set_gdbarch_push_dummy_call (gdbarch, xstormy16_push_dummy_call);
844*11efff7fSkettenis   set_gdbarch_breakpoint_from_pc (gdbarch, xstormy16_breakpoint_from_pc);
845*11efff7fSkettenis   set_gdbarch_return_value (gdbarch, xstormy16_return_value);
846b725ae77Skettenis 
847b725ae77Skettenis   set_gdbarch_skip_trampoline_code (gdbarch, xstormy16_skip_trampoline_code);
848b725ae77Skettenis   set_gdbarch_in_solib_call_trampoline (gdbarch,
849b725ae77Skettenis 					xstormy16_in_solib_call_trampoline);
850b725ae77Skettenis 
851b725ae77Skettenis   set_gdbarch_print_insn (gdbarch, print_insn_xstormy16);
852b725ae77Skettenis 
853*11efff7fSkettenis   gdbarch_init_osabi (info, gdbarch);
854*11efff7fSkettenis 
855*11efff7fSkettenis   frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
856*11efff7fSkettenis   frame_unwind_append_sniffer (gdbarch, xstormy16_frame_sniffer);
857*11efff7fSkettenis 
858b725ae77Skettenis   return gdbarch;
859b725ae77Skettenis }
860b725ae77Skettenis 
861b725ae77Skettenis /* Function: _initialize_xstormy16_tdep
862b725ae77Skettenis    Initializer function for the Sanyo Xstormy16a module.
863b725ae77Skettenis    Called by gdb at start-up. */
864b725ae77Skettenis 
865b725ae77Skettenis extern initialize_file_ftype _initialize_xstormy16_tdep; /* -Wmissing-prototypes */
866b725ae77Skettenis 
867b725ae77Skettenis void
_initialize_xstormy16_tdep(void)868b725ae77Skettenis _initialize_xstormy16_tdep (void)
869b725ae77Skettenis {
870b725ae77Skettenis   register_gdbarch_init (bfd_arch_xstormy16, xstormy16_gdbarch_init);
871b725ae77Skettenis }
872