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