xref: /openbsd/gnu/usr.bin/binutils/gdb/m88k-tdep.c (revision d0a35373)
1ee684603Skettenis /* Target-dependent code for the Motorola 88000 series.
2ee684603Skettenis 
3ee684603Skettenis    Copyright 2004 Free Software Foundation, Inc.
4ee684603Skettenis 
5ee684603Skettenis    This file is part of GDB.
6ee684603Skettenis 
7ee684603Skettenis    This program is free software; you can redistribute it and/or modify
8ee684603Skettenis    it under the terms of the GNU General Public License as published by
9ee684603Skettenis    the Free Software Foundation; either version 2 of the License, or
10ee684603Skettenis    (at your option) any later version.
11ee684603Skettenis 
12ee684603Skettenis    This program is distributed in the hope that it will be useful,
13ee684603Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
14ee684603Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15ee684603Skettenis    GNU General Public License for more details.
16ee684603Skettenis 
17ee684603Skettenis    You should have received a copy of the GNU General Public License
18ee684603Skettenis    along with this program; if not, write to the Free Software
19ee684603Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
20ee684603Skettenis    Boston, MA 02111-1307, USA.  */
21ee684603Skettenis 
22ee684603Skettenis #include "defs.h"
23ee684603Skettenis #include "arch-utils.h"
24ee684603Skettenis #include "dis-asm.h"
25ee684603Skettenis #include "frame.h"
26ee684603Skettenis #include "frame-base.h"
27ee684603Skettenis #include "frame-unwind.h"
28ee684603Skettenis #include "gdbcore.h"
29ee684603Skettenis #include "gdbtypes.h"
30ee684603Skettenis #include "regcache.h"
31ee684603Skettenis #include "regset.h"
32ee684603Skettenis #include "symtab.h"
33ee684603Skettenis #include "trad-frame.h"
34ee684603Skettenis #include "value.h"
35ee684603Skettenis 
36ee684603Skettenis #include "gdb_assert.h"
37ee684603Skettenis #include "gdb_string.h"
38ee684603Skettenis 
39ee684603Skettenis #include "m88k-tdep.h"
40ee684603Skettenis 
41ee684603Skettenis /* Fetch the instruction at PC.  */
42ee684603Skettenis 
43ee684603Skettenis static unsigned long
m88k_fetch_instruction(CORE_ADDR pc)44ee684603Skettenis m88k_fetch_instruction (CORE_ADDR pc)
45ee684603Skettenis {
46ee684603Skettenis   return read_memory_unsigned_integer (pc, 4);
47ee684603Skettenis }
48ee684603Skettenis 
49ee684603Skettenis /* Register information.  */
50ee684603Skettenis 
51ee684603Skettenis /* Return the name of register REGNUM.  */
52ee684603Skettenis 
53ee684603Skettenis static const char *
m88k_register_name(int regnum)54ee684603Skettenis m88k_register_name (int regnum)
55ee684603Skettenis {
56ee684603Skettenis   static char *register_names[] =
57ee684603Skettenis   {
58ee684603Skettenis     "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
59ee684603Skettenis     "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
60ee684603Skettenis     "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
61ee684603Skettenis     "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
62ee684603Skettenis     "epsr", "fpsr", "fpcr", "sxip", "snip", "sfip"
63ee684603Skettenis   };
64ee684603Skettenis 
65ee684603Skettenis   if (regnum >= 0 && regnum < ARRAY_SIZE (register_names))
66ee684603Skettenis     return register_names[regnum];
67ee684603Skettenis 
68ee684603Skettenis   return NULL;
69ee684603Skettenis }
70ee684603Skettenis 
71ee684603Skettenis /* Return the GDB type object for the "standard" data type of data in
72ee684603Skettenis    register REGNUM. */
73ee684603Skettenis 
74ee684603Skettenis static struct type *
m88k_register_type(struct gdbarch * gdbarch,int regnum)75ee684603Skettenis m88k_register_type (struct gdbarch *gdbarch, int regnum)
76ee684603Skettenis {
77ee684603Skettenis   /* SXIP, SNIP, SFIP and R1 contain code addresses.  */
78ee684603Skettenis   if ((regnum >= M88K_SXIP_REGNUM && regnum <= M88K_SFIP_REGNUM)
79ee684603Skettenis       || regnum == M88K_R1_REGNUM)
80ee684603Skettenis     return builtin_type_void_func_ptr;
81ee684603Skettenis 
82ee684603Skettenis   /* R30 and R31 typically contains data addresses.  */
83ee684603Skettenis   if (regnum == M88K_R30_REGNUM || regnum == M88K_R31_REGNUM)
84ee684603Skettenis     return builtin_type_void_data_ptr;
85ee684603Skettenis 
86ee684603Skettenis   return builtin_type_int32;
87ee684603Skettenis }
88ee684603Skettenis 
89ee684603Skettenis 
90ee684603Skettenis static CORE_ADDR
m88k_addr_bits_remove(CORE_ADDR addr)91ee684603Skettenis m88k_addr_bits_remove (CORE_ADDR addr)
92ee684603Skettenis {
93ee684603Skettenis   /* All instructures are 4-byte aligned.  The lower 2 bits of SXIP,
94ee684603Skettenis      SNIP and SFIP are used for special purposes: bit 0 is the
95ee684603Skettenis      exception bit and bit 1 is the valid bit.  */
96ee684603Skettenis   return addr & ~0x3;
97ee684603Skettenis }
98ee684603Skettenis 
99ee684603Skettenis /* Use the program counter to determine the contents and size of a
100ee684603Skettenis    breakpoint instruction.  Return a pointer to a string of bytes that
101ee684603Skettenis    encode a breakpoint instruction, store the length of the string in
102ee684603Skettenis    *LEN and optionally adjust *PC to point to the correct memory
103ee684603Skettenis    location for inserting the breakpoint.  */
104ee684603Skettenis 
105ee684603Skettenis static const unsigned char *
m88k_breakpoint_from_pc(CORE_ADDR * pc,int * len)106ee684603Skettenis m88k_breakpoint_from_pc (CORE_ADDR *pc, int *len)
107ee684603Skettenis {
108ee684603Skettenis   /* tb 0,r0,511 */
109ee684603Skettenis   static unsigned char break_insn[] = { 0xf0, 0x00, 0xd1, 0xff };
110ee684603Skettenis 
111ee684603Skettenis   *len = sizeof (break_insn);
112ee684603Skettenis   return break_insn;
113ee684603Skettenis }
114ee684603Skettenis 
115ee684603Skettenis static CORE_ADDR
m88k_unwind_pc(struct gdbarch * gdbarch,struct frame_info * next_frame)116ee684603Skettenis m88k_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
117ee684603Skettenis {
118ee684603Skettenis   CORE_ADDR pc;
119ee684603Skettenis 
120ee684603Skettenis   pc = frame_unwind_register_unsigned (next_frame, M88K_SXIP_REGNUM);
121ee684603Skettenis   return m88k_addr_bits_remove (pc);
122ee684603Skettenis }
123ee684603Skettenis 
124ee684603Skettenis static void
m88k_write_pc(CORE_ADDR pc,ptid_t ptid)125ee684603Skettenis m88k_write_pc (CORE_ADDR pc, ptid_t ptid)
126ee684603Skettenis {
127ee684603Skettenis   /* According to the MC88100 RISC Microprocessor User's Manual,
128ee684603Skettenis      section 6.4.3.1.2:
129ee684603Skettenis 
130ee684603Skettenis      "... can be made to return to a particular instruction by placing
131ee684603Skettenis      a valid instruction address in the SNIP and the next sequential
132ee684603Skettenis      instruction address in the SFIP (with V bits set and E bits
133ee684603Skettenis      clear).  The rte resumes execution at the instruction pointed to
134ee684603Skettenis      by the SNIP, then the SFIP."
135ee684603Skettenis 
136ee684603Skettenis      The E bit is the least significant bit (bit 0).  The V (valid)
137ee684603Skettenis      bit is bit 1.  This is why we logical or 2 into the values we are
138ee684603Skettenis      writing below.  It turns out that SXIP plays no role when
139ee684603Skettenis      returning from an exception so nothing special has to be done
140ee684603Skettenis      with it.  We could even (presumably) give it a totally bogus
141ee684603Skettenis      value.  */
142ee684603Skettenis 
143ee684603Skettenis   write_register_pid (M88K_SXIP_REGNUM, pc, ptid);
144ee684603Skettenis   write_register_pid (M88K_SNIP_REGNUM, pc | 2, ptid);
145ee684603Skettenis   write_register_pid (M88K_SFIP_REGNUM, (pc + 4) | 2, ptid);
146ee684603Skettenis }
147ee684603Skettenis 
148ee684603Skettenis 
149ee684603Skettenis /* The functions on this page are intended to be used to classify
150ee684603Skettenis    function arguments.  */
151ee684603Skettenis 
152ee684603Skettenis /* Check whether TYPE is "Integral or Pointer".  */
153ee684603Skettenis 
154ee684603Skettenis static int
m88k_integral_or_pointer_p(const struct type * type)155ee684603Skettenis m88k_integral_or_pointer_p (const struct type *type)
156ee684603Skettenis {
157ee684603Skettenis   switch (TYPE_CODE (type))
158ee684603Skettenis     {
159ee684603Skettenis     case TYPE_CODE_INT:
160ee684603Skettenis     case TYPE_CODE_BOOL:
161ee684603Skettenis     case TYPE_CODE_CHAR:
162ee684603Skettenis     case TYPE_CODE_ENUM:
163ee684603Skettenis     case TYPE_CODE_RANGE:
164ee684603Skettenis       {
165ee684603Skettenis 	/* We have byte, half-word, word and extended-word/doubleword
166ee684603Skettenis            integral types.  */
167ee684603Skettenis 	int len = TYPE_LENGTH (type);
168ee684603Skettenis 	return (len == 1 || len == 2 || len == 4 || len == 8);
169ee684603Skettenis       }
170ee684603Skettenis       return 1;
171ee684603Skettenis     case TYPE_CODE_PTR:
172ee684603Skettenis     case TYPE_CODE_REF:
173ee684603Skettenis       {
174ee684603Skettenis 	/* Allow only 32-bit pointers.  */
175ee684603Skettenis 	return (TYPE_LENGTH (type) == 4);
176ee684603Skettenis       }
177ee684603Skettenis       return 1;
178ee684603Skettenis     default:
179ee684603Skettenis       break;
180ee684603Skettenis     }
181ee684603Skettenis 
182ee684603Skettenis   return 0;
183ee684603Skettenis }
184ee684603Skettenis 
185ee684603Skettenis /* Check whether TYPE is "Floating".  */
186ee684603Skettenis 
187ee684603Skettenis static int
m88k_floating_p(const struct type * type)188ee684603Skettenis m88k_floating_p (const struct type *type)
189ee684603Skettenis {
190ee684603Skettenis   switch (TYPE_CODE (type))
191ee684603Skettenis     {
192ee684603Skettenis     case TYPE_CODE_FLT:
193ee684603Skettenis       {
194ee684603Skettenis 	int len = TYPE_LENGTH (type);
195ee684603Skettenis 	return (len == 4 || len == 8);
196ee684603Skettenis       }
197ee684603Skettenis     default:
198ee684603Skettenis       break;
199ee684603Skettenis     }
200ee684603Skettenis 
201ee684603Skettenis   return 0;
202ee684603Skettenis }
203ee684603Skettenis 
204ee684603Skettenis /* Check whether TYPE is "Structure or Union".  */
205ee684603Skettenis 
206ee684603Skettenis static int
m88k_structure_or_union_p(const struct type * type)207ee684603Skettenis m88k_structure_or_union_p (const struct type *type)
208ee684603Skettenis {
209ee684603Skettenis   switch (TYPE_CODE (type))
210ee684603Skettenis     {
211ee684603Skettenis     case TYPE_CODE_STRUCT:
212ee684603Skettenis     case TYPE_CODE_UNION:
213ee684603Skettenis       return 1;
214ee684603Skettenis     default:
215ee684603Skettenis       break;
216ee684603Skettenis     }
217ee684603Skettenis 
218ee684603Skettenis   return 0;
219ee684603Skettenis }
220ee684603Skettenis 
221ee684603Skettenis /* Check whether TYPE has 8-byte alignment.  */
222ee684603Skettenis 
223ee684603Skettenis static int
m88k_8_byte_align_p(struct type * type)224ee684603Skettenis m88k_8_byte_align_p (struct type *type)
225ee684603Skettenis {
226ee684603Skettenis   if (m88k_structure_or_union_p (type))
227ee684603Skettenis     {
228ee684603Skettenis       int i;
229ee684603Skettenis 
230ee684603Skettenis       for (i = 0; i < TYPE_NFIELDS (type); i++)
231ee684603Skettenis 	{
232ee684603Skettenis 	  struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i));
233ee684603Skettenis 
234ee684603Skettenis 	  if (m88k_8_byte_align_p (subtype))
235ee684603Skettenis 	    return 1;
236ee684603Skettenis 	}
237ee684603Skettenis     }
238ee684603Skettenis 
239ee684603Skettenis   if (m88k_integral_or_pointer_p (type) || m88k_floating_p (type))
240ee684603Skettenis     return (TYPE_LENGTH (type) == 8);
241ee684603Skettenis 
242ee684603Skettenis   return 0;
243ee684603Skettenis }
244ee684603Skettenis 
245ee684603Skettenis /* Check whether TYPE can be passed in a register.  */
246ee684603Skettenis 
247ee684603Skettenis static int
m88k_in_register_p(struct type * type)248ee684603Skettenis m88k_in_register_p (struct type *type)
249ee684603Skettenis {
250ee684603Skettenis   if (m88k_integral_or_pointer_p (type) || m88k_floating_p (type))
251ee684603Skettenis     return 1;
252ee684603Skettenis 
253ee684603Skettenis   if (m88k_structure_or_union_p (type) && TYPE_LENGTH (type) == 4)
254ee684603Skettenis     return 1;
255ee684603Skettenis 
256ee684603Skettenis   return 0;
257ee684603Skettenis }
258ee684603Skettenis 
259ee684603Skettenis static CORE_ADDR
m88k_store_arguments(struct regcache * regcache,int nargs,struct value ** args,CORE_ADDR sp)260ee684603Skettenis m88k_store_arguments (struct regcache *regcache, int nargs,
261ee684603Skettenis 		      struct value **args, CORE_ADDR sp)
262ee684603Skettenis {
263ee684603Skettenis   int num_register_words = 0;
264ee684603Skettenis   int num_stack_words = 0;
265ee684603Skettenis   int i;
266ee684603Skettenis 
267ee684603Skettenis   for (i = 0; i < nargs; i++)
268ee684603Skettenis     {
269ee684603Skettenis       struct type *type = VALUE_TYPE (args[i]);
270ee684603Skettenis       int len = TYPE_LENGTH (type);
271ee684603Skettenis 
272ee684603Skettenis       if (m88k_integral_or_pointer_p (type) && len < 4)
273ee684603Skettenis 	{
274ee684603Skettenis 	  args[i] = value_cast (builtin_type_int32, args[i]);
275ee684603Skettenis 	  type = VALUE_TYPE (args[i]);
276ee684603Skettenis 	  len = TYPE_LENGTH (type);
277ee684603Skettenis 	}
278ee684603Skettenis 
279ee684603Skettenis       if (m88k_in_register_p (type))
280ee684603Skettenis 	{
281ee684603Skettenis 	  int num_words = 0;
282ee684603Skettenis 
283ee684603Skettenis 	  if (num_register_words % 2 == 1 && m88k_8_byte_align_p (type))
284ee684603Skettenis 	    num_words++;
285ee684603Skettenis 
286ee684603Skettenis 	  num_words += ((len + 3) / 4);
287ee684603Skettenis 	  if (num_register_words + num_words <= 8)
288ee684603Skettenis 	    {
289ee684603Skettenis 	      num_register_words += num_words;
290ee684603Skettenis 	      continue;
291ee684603Skettenis 	    }
292ee684603Skettenis 
293ee684603Skettenis 	  /* We've run out of available registers.  Pass the argument
294ee684603Skettenis              on the stack.  */
295ee684603Skettenis 	}
296ee684603Skettenis 
297ee684603Skettenis       if (num_stack_words % 2 == 1 && m88k_8_byte_align_p (type))
298ee684603Skettenis 	num_stack_words++;
299ee684603Skettenis 
300ee684603Skettenis       num_stack_words += ((len + 3) / 4);
301ee684603Skettenis     }
302ee684603Skettenis 
303ee684603Skettenis   /* Allocate stack space.  */
304ee684603Skettenis   sp = align_down (sp - 32 - num_stack_words * 4, 16);
305ee684603Skettenis   num_stack_words = num_register_words = 0;
306ee684603Skettenis 
307ee684603Skettenis   for (i = 0; i < nargs; i++)
308ee684603Skettenis     {
309ee684603Skettenis       char *valbuf = VALUE_CONTENTS (args[i]);
310ee684603Skettenis       struct type *type = VALUE_TYPE (args[i]);
311ee684603Skettenis       int len = TYPE_LENGTH (type);
312ee684603Skettenis       int stack_word = num_stack_words;
313ee684603Skettenis 
314ee684603Skettenis       if (m88k_in_register_p (type))
315ee684603Skettenis 	{
316ee684603Skettenis 	  int register_word = num_register_words;
317ee684603Skettenis 
318ee684603Skettenis 	  if (register_word % 2 == 1 && m88k_8_byte_align_p (type))
319ee684603Skettenis 	    register_word++;
320ee684603Skettenis 
321ee684603Skettenis 	  gdb_assert (len == 4 || len == 8);
322ee684603Skettenis 
323ee684603Skettenis 	  if (register_word + len / 8 < 8)
324ee684603Skettenis 	    {
325ee684603Skettenis 	      int regnum = M88K_R2_REGNUM + register_word;
326ee684603Skettenis 
327ee684603Skettenis 	      regcache_raw_write (regcache, regnum, valbuf);
328ee684603Skettenis 	      if (len > 4)
329ee684603Skettenis 		regcache_raw_write (regcache, regnum + 1, valbuf + 4);
330ee684603Skettenis 
331ee684603Skettenis 	      num_register_words = (register_word + len / 4);
332ee684603Skettenis 	      continue;
333ee684603Skettenis 	    }
334ee684603Skettenis 	}
335ee684603Skettenis 
336ee684603Skettenis       if (stack_word % 2 == -1 && m88k_8_byte_align_p (type))
337ee684603Skettenis 	stack_word++;
338ee684603Skettenis 
339ee684603Skettenis       write_memory (sp + stack_word * 4, valbuf, len);
340ee684603Skettenis       num_stack_words = (stack_word + (len + 3) / 4);
341ee684603Skettenis     }
342ee684603Skettenis 
343ee684603Skettenis   return sp;
344ee684603Skettenis }
345ee684603Skettenis 
346ee684603Skettenis static CORE_ADDR
m88k_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)34711efff7fSkettenis m88k_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
348ee684603Skettenis 		      struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
349ee684603Skettenis 		      struct value **args, CORE_ADDR sp, int struct_return,
350ee684603Skettenis 		      CORE_ADDR struct_addr)
351ee684603Skettenis {
352ee684603Skettenis   /* Set up the function arguments.  */
353ee684603Skettenis   sp = m88k_store_arguments (regcache, nargs, args, sp);
354ee684603Skettenis   gdb_assert (sp % 16 == 0);
355ee684603Skettenis 
356ee684603Skettenis   /* Store return value address.  */
357ee684603Skettenis   if (struct_return)
358ee684603Skettenis     regcache_raw_write_unsigned (regcache, M88K_R12_REGNUM, struct_addr);
359ee684603Skettenis 
360ee684603Skettenis   /* Store the stack pointer and return address in the appropriate
361ee684603Skettenis      registers.  */
362ee684603Skettenis   regcache_raw_write_unsigned (regcache, M88K_R31_REGNUM, sp);
363ee684603Skettenis   regcache_raw_write_unsigned (regcache, M88K_R1_REGNUM, bp_addr);
364ee684603Skettenis 
365ee684603Skettenis   /* Return the stack pointer.  */
366ee684603Skettenis   return sp;
367ee684603Skettenis }
368ee684603Skettenis 
369ee684603Skettenis static struct frame_id
m88k_unwind_dummy_id(struct gdbarch * arch,struct frame_info * next_frame)370ee684603Skettenis m88k_unwind_dummy_id (struct gdbarch *arch, struct frame_info *next_frame)
371ee684603Skettenis {
372ee684603Skettenis   CORE_ADDR sp;
373ee684603Skettenis 
374ee684603Skettenis   sp = frame_unwind_register_unsigned (next_frame, M88K_R31_REGNUM);
375ee684603Skettenis   return frame_id_build (sp, frame_pc_unwind (next_frame));
376ee684603Skettenis }
377ee684603Skettenis 
378ee684603Skettenis 
379ee684603Skettenis /* Determine, for architecture GDBARCH, how a return value of TYPE
380ee684603Skettenis    should be returned.  If it is supposed to be returned in registers,
381ee684603Skettenis    and READBUF is non-zero, read the appropriate value from REGCACHE,
382ee684603Skettenis    and copy it into READBUF.  If WRITEBUF is non-zero, write the value
383ee684603Skettenis    from WRITEBUF into REGCACHE.  */
384ee684603Skettenis 
385ee684603Skettenis static enum return_value_convention
m88k_return_value(struct gdbarch * gdbarch,struct type * type,struct regcache * regcache,void * readbuf,const void * writebuf)386ee684603Skettenis m88k_return_value (struct gdbarch *gdbarch, struct type *type,
387ee684603Skettenis 		   struct regcache *regcache, void *readbuf,
388ee684603Skettenis 		   const void *writebuf)
389ee684603Skettenis {
390ee684603Skettenis   int len = TYPE_LENGTH (type);
391ee684603Skettenis   char buf[8];
392ee684603Skettenis 
393ee684603Skettenis   if (!m88k_integral_or_pointer_p (type) && !m88k_floating_p (type))
394ee684603Skettenis     return RETURN_VALUE_STRUCT_CONVENTION;
395ee684603Skettenis 
396ee684603Skettenis   if (readbuf)
397ee684603Skettenis     {
398ee684603Skettenis       /* Read the contents of R2 and (if necessary) R3.  */
399ee684603Skettenis       regcache_cooked_read (regcache, M88K_R2_REGNUM, buf);
400ee684603Skettenis       if (len > 4)
401ee684603Skettenis 	{
402ee684603Skettenis 	  regcache_cooked_read (regcache, M88K_R3_REGNUM, buf + 4);
403ee684603Skettenis 	  gdb_assert (len == 8);
404ee684603Skettenis 	  memcpy (readbuf, buf, len);
405ee684603Skettenis 	}
406ee684603Skettenis       else
407ee684603Skettenis 	{
408ee684603Skettenis 	  /* Just stripping off any unused bytes should preserve the
409ee684603Skettenis              signed-ness just fine.  */
410ee684603Skettenis 	  memcpy (readbuf, buf + 4 - len, len);
411ee684603Skettenis 	}
412ee684603Skettenis     }
413ee684603Skettenis 
414ee684603Skettenis   if (writebuf)
415ee684603Skettenis     {
416ee684603Skettenis       /* Read the contents to R2 and (if necessary) R3.  */
417ee684603Skettenis       if (len > 4)
418ee684603Skettenis 	{
419ee684603Skettenis 	  gdb_assert (len == 8);
420ee684603Skettenis 	  memcpy (buf, writebuf, 8);
421ee684603Skettenis 	  regcache_cooked_write (regcache, M88K_R3_REGNUM, buf + 4);
422ee684603Skettenis 	}
423ee684603Skettenis       else
424ee684603Skettenis 	{
425ee684603Skettenis 	  /* ??? Do we need to do any sign-extension here?  */
426ee684603Skettenis 	  memcpy (buf + 4 - len, writebuf, len);
427ee684603Skettenis 	}
428ee684603Skettenis       regcache_cooked_write (regcache, M88K_R2_REGNUM, buf);
429ee684603Skettenis     }
430ee684603Skettenis 
431ee684603Skettenis   return RETURN_VALUE_REGISTER_CONVENTION;
432ee684603Skettenis }
433ee684603Skettenis 
434ee684603Skettenis /* Default frame unwinder.  */
435ee684603Skettenis 
436ee684603Skettenis struct m88k_frame_cache
437ee684603Skettenis {
438ee684603Skettenis   /* Base address.  */
439ee684603Skettenis   CORE_ADDR base;
440ee684603Skettenis   CORE_ADDR pc;
441ee684603Skettenis 
442ee684603Skettenis   int sp_offset;
443ee684603Skettenis   int fp_offset;
444ee684603Skettenis 
445ee684603Skettenis   /* Table of saved registers.  */
446ee684603Skettenis   struct trad_frame_saved_reg *saved_regs;
447ee684603Skettenis };
448ee684603Skettenis 
449ee684603Skettenis /* Prologue analysis.  */
450ee684603Skettenis 
451ee684603Skettenis /* Macros for extracting fields from instructions.  */
452ee684603Skettenis 
453ee684603Skettenis #define BITMASK(pos, width) (((0x1 << (width)) - 1) << (pos))
454ee684603Skettenis #define EXTRACT_FIELD(val, pos, width) ((val) >> (pos) & BITMASK (0, width))
455ee684603Skettenis #define	SUBU_OFFSET(x)	((unsigned)(x & 0xFFFF))
456ee684603Skettenis #define	ST_OFFSET(x)	((unsigned)((x) & 0xFFFF))
457ee684603Skettenis #define	ST_SRC(x)	EXTRACT_FIELD ((x), 21, 5)
458ee684603Skettenis #define	ADDU_OFFSET(x)	((unsigned)(x & 0xFFFF))
459ee684603Skettenis 
460ee684603Skettenis /* Possible actions to be taken by the prologue analyzer for the
461ee684603Skettenis    instructions it encounters.  */
462ee684603Skettenis 
463ee684603Skettenis enum m88k_prologue_insn_action
464ee684603Skettenis {
465ee684603Skettenis   M88K_PIA_SKIP,		/* Ignore.  */
466ee684603Skettenis   M88K_PIA_NOTE_ST,		/* Note register store.  */
467ee684603Skettenis   M88K_PIA_NOTE_STD,		/* Note register pair store.  */
468ee684603Skettenis   M88K_PIA_NOTE_SP_ADJUSTMENT,	/* Note stack pointer adjustment.  */
469ee684603Skettenis   M88K_PIA_NOTE_FP_ASSIGNMENT,	/* Note frame pointer assignment.  */
470ee684603Skettenis   M88K_PIA_NOTE_BRANCH,		/* Note branch.  */
471ee684603Skettenis   M88K_PIA_NOTE_PROLOGUE_END	/* Note end of prologue.  */
472ee684603Skettenis };
473ee684603Skettenis 
474ee684603Skettenis /* Table of instructions that may comprise a function prologue.  */
475ee684603Skettenis 
476ee684603Skettenis struct m88k_prologue_insn
477ee684603Skettenis {
478ee684603Skettenis   unsigned long insn;
479ee684603Skettenis   unsigned long mask;
480ee684603Skettenis   enum m88k_prologue_insn_action action;
481ee684603Skettenis };
482ee684603Skettenis 
483ee684603Skettenis struct m88k_prologue_insn m88k_prologue_insn_table[] =
484ee684603Skettenis {
485ee684603Skettenis   /* Various register move instructions.  */
486ee684603Skettenis   { 0x58000000, 0xf800ffff, M88K_PIA_SKIP },     /* or/or.u with immed of 0 */
487ee684603Skettenis   { 0xf4005800, 0xfc1fffe0, M88K_PIA_SKIP },     /* or rd,r0,rs */
488ee684603Skettenis   { 0xf4005800, 0xfc00ffff, M88K_PIA_SKIP },     /* or rd,rs,r0 */
489ee684603Skettenis 
490ee684603Skettenis   /* Various other instructions.  */
491ee684603Skettenis   { 0x58000000, 0xf8000000, M88K_PIA_SKIP },     /* or/or.u */
492ee684603Skettenis 
493ee684603Skettenis   /* Stack pointer setup: "subu sp,sp,n" where n is a multiple of 8.  */
494ee684603Skettenis   { 0x67ff0000, 0xffff0007, M88K_PIA_NOTE_SP_ADJUSTMENT },
495ee684603Skettenis 
496ee684603Skettenis   /* Frame pointer assignment: "addu r30,r31,n".  */
497ee684603Skettenis   { 0x63df0000, 0xffff0000, M88K_PIA_NOTE_FP_ASSIGNMENT },
498ee684603Skettenis 
499ee684603Skettenis   /* Store to stack instructions; either "st rx,sp,n" or "st.d rx,sp,n".  */
500ee684603Skettenis   { 0x241f0000, 0xfc1f0000, M88K_PIA_NOTE_ST },  /* st rx,sp,n */
501ee684603Skettenis   { 0x201f0000, 0xfc1f0000, M88K_PIA_NOTE_STD }, /* st.d rs,sp,n */
502ee684603Skettenis 
503ee684603Skettenis   /* Instructions needed for setting up r25 for pic code.  */
504ee684603Skettenis   { 0x5f200000, 0xffff0000, M88K_PIA_SKIP },     /* or.u r25,r0,offset_high */
505ee684603Skettenis   { 0xcc000002, 0xffffffff, M88K_PIA_SKIP },     /* bsr.n Lab */
506ee684603Skettenis   { 0x5b390000, 0xffff0000, M88K_PIA_SKIP },     /* or r25,r25,offset_low */
507ee684603Skettenis   { 0xf7396001, 0xffffffff, M88K_PIA_SKIP },     /* Lab: addu r25,r25,r1 */
508ee684603Skettenis 
509ee684603Skettenis   /* Various branch or jump instructions which have a delay slot --
510ee684603Skettenis      these do not form part of the prologue, but the instruction in
511ee684603Skettenis      the delay slot might be a store instruction which should be
512ee684603Skettenis      noted.  */
513ee684603Skettenis   { 0xc4000000, 0xe4000000, M88K_PIA_NOTE_BRANCH },
514ee684603Skettenis                                       /* br.n, bsr.n, bb0.n, or bb1.n */
515ee684603Skettenis   { 0xec000000, 0xfc000000, M88K_PIA_NOTE_BRANCH }, /* bcnd.n */
516ee684603Skettenis   { 0xf400c400, 0xfffff7e0, M88K_PIA_NOTE_BRANCH }, /* jmp.n or jsr.n */
517ee684603Skettenis 
518ee684603Skettenis   /* Catch all.  Ends prologue analysis.  */
519ee684603Skettenis   { 0x00000000, 0x00000000, M88K_PIA_NOTE_PROLOGUE_END }
520ee684603Skettenis };
521ee684603Skettenis 
522ee684603Skettenis /* Do a full analysis of the function prologue at PC and update CACHE
523ee684603Skettenis    accordingly.  Bail out early if LIMIT is reached.  Return the
524ee684603Skettenis    address where the analysis stopped.  If LIMIT points beyond the
525ee684603Skettenis    function prologue, the return address should be the end of the
526ee684603Skettenis    prologue.  */
527ee684603Skettenis 
528ee684603Skettenis static CORE_ADDR
m88k_analyze_prologue(CORE_ADDR pc,CORE_ADDR limit,struct m88k_frame_cache * cache)529ee684603Skettenis m88k_analyze_prologue (CORE_ADDR pc, CORE_ADDR limit,
530ee684603Skettenis 		       struct m88k_frame_cache *cache)
531ee684603Skettenis {
532ee684603Skettenis   CORE_ADDR end = limit;
533ee684603Skettenis 
534ee684603Skettenis   /* Provide a dummy cache if necessary.  */
535ee684603Skettenis   if (cache == NULL)
536ee684603Skettenis     {
537ee684603Skettenis       size_t sizeof_saved_regs =
538ee684603Skettenis 	(M88K_R31_REGNUM + 1) * sizeof (struct trad_frame_saved_reg);
539ee684603Skettenis 
540ee684603Skettenis       cache = alloca (sizeof (struct m88k_frame_cache));
541ee684603Skettenis       cache->saved_regs = alloca (sizeof_saved_regs);
542ee684603Skettenis 
543ee684603Skettenis       /* We only initialize the members we care about.  */
544ee684603Skettenis       cache->saved_regs[M88K_R1_REGNUM].addr = -1;
545ee684603Skettenis       cache->fp_offset = -1;
546ee684603Skettenis     }
547ee684603Skettenis 
548ee684603Skettenis   while (pc < limit)
549ee684603Skettenis     {
550ee684603Skettenis       struct m88k_prologue_insn *pi = m88k_prologue_insn_table;
551ee684603Skettenis       unsigned long insn = m88k_fetch_instruction (pc);
552ee684603Skettenis 
553ee684603Skettenis       while ((insn & pi->mask) != pi->insn)
554ee684603Skettenis 	pi++;
555ee684603Skettenis 
556ee684603Skettenis       switch (pi->action)
557ee684603Skettenis 	{
558ee684603Skettenis 	case M88K_PIA_SKIP:
559ee684603Skettenis 	  /* If we have a frame pointer, and R1 has been saved,
560ee684603Skettenis              consider this instruction as not being part of the
561ee684603Skettenis              prologue.  */
562ee684603Skettenis 	  if (cache->fp_offset != -1
563ee684603Skettenis 	      && cache->saved_regs[M88K_R1_REGNUM].addr != -1)
564ee684603Skettenis 	    return min (pc, end);
565ee684603Skettenis 	  break;
566ee684603Skettenis 
567ee684603Skettenis 	case M88K_PIA_NOTE_ST:
568ee684603Skettenis 	case M88K_PIA_NOTE_STD:
569ee684603Skettenis 	  /* If no frame has been allocated, the stores aren't part of
570ee684603Skettenis              the prologue.  */
571ee684603Skettenis 	  if (cache->sp_offset == 0)
572ee684603Skettenis 	    return min (pc, end);
573ee684603Skettenis 
574ee684603Skettenis 	  /* Record location of saved registers.  */
575ee684603Skettenis 	  {
576ee684603Skettenis 	    int regnum = ST_SRC (insn) + M88K_R0_REGNUM;
577ee684603Skettenis 	    ULONGEST offset = ST_OFFSET (insn);
578ee684603Skettenis 
579ee684603Skettenis 	    cache->saved_regs[regnum].addr = offset;
580ee684603Skettenis 	    if (pi->action == M88K_PIA_NOTE_STD && regnum < M88K_R31_REGNUM)
581ee684603Skettenis 	      cache->saved_regs[regnum + 1].addr = offset + 4;
582ee684603Skettenis 	  }
583ee684603Skettenis 	  break;
584ee684603Skettenis 
585ee684603Skettenis 	case M88K_PIA_NOTE_SP_ADJUSTMENT:
586ee684603Skettenis 	  /* A second stack pointer adjustment isn't part of the
587ee684603Skettenis              prologue.  */
588ee684603Skettenis 	  if (cache->sp_offset != 0)
589ee684603Skettenis 	    return min (pc, end);
590ee684603Skettenis 
591ee684603Skettenis 	  /* Store stack pointer adjustment.  */
592ee684603Skettenis 	  cache->sp_offset = -SUBU_OFFSET (insn);
593ee684603Skettenis 	  break;
594ee684603Skettenis 
595ee684603Skettenis 	case M88K_PIA_NOTE_FP_ASSIGNMENT:
596ee684603Skettenis 	  /* A second frame pointer assignment isn't part of the
597ee684603Skettenis              prologue.  */
598ee684603Skettenis 	  if (cache->fp_offset != -1)
599ee684603Skettenis 	    return min (pc, end);
600ee684603Skettenis 
601ee684603Skettenis 	  /* Record frame pointer assignment.  */
602ee684603Skettenis 	  cache->fp_offset = ADDU_OFFSET (insn);
603ee684603Skettenis 	  break;
604ee684603Skettenis 
605ee684603Skettenis 	case M88K_PIA_NOTE_BRANCH:
606ee684603Skettenis 	  /* The branch instruction isn't part of the prologue, but
607ee684603Skettenis              the instruction in the delay slot might be.  Limit the
608ee684603Skettenis              prologue analysis to the delay slot and record the branch
609ee684603Skettenis              instruction as the end of the prologue.  */
61028cbedccSkettenis 	  limit = min (limit, pc + 2 * M88K_INSN_SIZE);
611ee684603Skettenis 	  end = pc;
612ee684603Skettenis 	  break;
613ee684603Skettenis 
614ee684603Skettenis 	case M88K_PIA_NOTE_PROLOGUE_END:
615ee684603Skettenis 	  return min (pc, end);
616ee684603Skettenis 	}
617ee684603Skettenis 
618ee684603Skettenis       pc += M88K_INSN_SIZE;
619ee684603Skettenis     }
620ee684603Skettenis 
621ee684603Skettenis   return end;
622ee684603Skettenis }
623ee684603Skettenis 
624ee684603Skettenis /* An upper limit to the size of the prologue.  */
625ee684603Skettenis const int m88k_max_prologue_size = 128 * M88K_INSN_SIZE;
626ee684603Skettenis 
627ee684603Skettenis /* Return the address of first real instruction of the function
628ee684603Skettenis    starting at PC.  */
629ee684603Skettenis 
630ee684603Skettenis static CORE_ADDR
m88k_skip_prologue(CORE_ADDR pc)631ee684603Skettenis m88k_skip_prologue (CORE_ADDR pc)
632ee684603Skettenis {
633ee684603Skettenis   struct symtab_and_line sal;
634ee684603Skettenis   CORE_ADDR func_start, func_end;
635ee684603Skettenis 
636ee684603Skettenis   /* This is the preferred method, find the end of the prologue by
637ee684603Skettenis      using the debugging information.  */
638ee684603Skettenis   if (find_pc_partial_function (pc, NULL, &func_start, &func_end))
639ee684603Skettenis     {
640ee684603Skettenis       sal = find_pc_line (func_start, 0);
641ee684603Skettenis 
642ee684603Skettenis       if (sal.end < func_end && pc <= sal.end)
643ee684603Skettenis 	return sal.end;
644ee684603Skettenis     }
645ee684603Skettenis 
646ee684603Skettenis   return m88k_analyze_prologue (pc, pc + m88k_max_prologue_size, NULL);
647ee684603Skettenis }
648ee684603Skettenis 
649ee684603Skettenis struct m88k_frame_cache *
m88k_frame_cache(struct frame_info * next_frame,void ** this_cache)650ee684603Skettenis m88k_frame_cache (struct frame_info *next_frame, void **this_cache)
651ee684603Skettenis {
652ee684603Skettenis   struct m88k_frame_cache *cache;
653ee684603Skettenis   CORE_ADDR frame_sp;
654ee684603Skettenis 
655ee684603Skettenis   if (*this_cache)
656ee684603Skettenis     return *this_cache;
657ee684603Skettenis 
658ee684603Skettenis   cache = FRAME_OBSTACK_ZALLOC (struct m88k_frame_cache);
659ee684603Skettenis   cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
660ee684603Skettenis   cache->fp_offset = -1;
661ee684603Skettenis 
662ee684603Skettenis   cache->pc = frame_func_unwind (next_frame);
663ee684603Skettenis   if (cache->pc != 0)
664ee684603Skettenis     {
665ee684603Skettenis       CORE_ADDR addr_in_block = frame_unwind_address_in_block (next_frame);
666ee684603Skettenis       m88k_analyze_prologue (cache->pc, addr_in_block, cache);
667ee684603Skettenis     }
668ee684603Skettenis 
669ee684603Skettenis   /* Calculate the stack pointer used in the prologue.  */
670ee684603Skettenis   if (cache->fp_offset != -1)
671ee684603Skettenis     {
672ee684603Skettenis       CORE_ADDR fp;
673ee684603Skettenis 
674ee684603Skettenis       fp = frame_unwind_register_unsigned (next_frame, M88K_R30_REGNUM);
675ee684603Skettenis       frame_sp = fp - cache->fp_offset;
676ee684603Skettenis     }
677ee684603Skettenis   else
678ee684603Skettenis     {
679ee684603Skettenis       /* If we know where the return address is saved, we can take a
680ee684603Skettenis          solid guess at what the frame pointer should be.  */
681ee684603Skettenis       if (cache->saved_regs[M88K_R1_REGNUM].addr != -1)
682ee684603Skettenis 	cache->fp_offset = cache->saved_regs[M88K_R1_REGNUM].addr - 4;
683ee684603Skettenis       frame_sp = frame_unwind_register_unsigned (next_frame, M88K_R31_REGNUM);
684ee684603Skettenis     }
685ee684603Skettenis 
686ee684603Skettenis   /* Now that we know the stack pointer, adjust the location of the
687ee684603Skettenis      saved registers.  */
688ee684603Skettenis   {
689ee684603Skettenis     int regnum;
690ee684603Skettenis 
691ee684603Skettenis     for (regnum = M88K_R0_REGNUM; regnum < M88K_R31_REGNUM; regnum ++)
692ee684603Skettenis       if (cache->saved_regs[regnum].addr != -1)
693ee684603Skettenis 	cache->saved_regs[regnum].addr += frame_sp;
694ee684603Skettenis   }
695ee684603Skettenis 
696ee684603Skettenis   /* Calculate the frame's base.  */
697ee684603Skettenis   cache->base = frame_sp - cache->sp_offset;
698ee684603Skettenis   trad_frame_set_value (cache->saved_regs, M88K_R31_REGNUM, cache->base);
699ee684603Skettenis 
700ee684603Skettenis   /* Identify SXIP with the return address in R1.  */
701ee684603Skettenis   cache->saved_regs[M88K_SXIP_REGNUM] = cache->saved_regs[M88K_R1_REGNUM];
702ee684603Skettenis 
703ee684603Skettenis   *this_cache = cache;
704ee684603Skettenis   return cache;
705ee684603Skettenis }
706ee684603Skettenis 
707ee684603Skettenis static void
m88k_frame_this_id(struct frame_info * next_frame,void ** this_cache,struct frame_id * this_id)708ee684603Skettenis m88k_frame_this_id (struct frame_info *next_frame, void **this_cache,
709ee684603Skettenis 		    struct frame_id *this_id)
710ee684603Skettenis {
711ee684603Skettenis   struct m88k_frame_cache *cache = m88k_frame_cache (next_frame, this_cache);
712ee684603Skettenis 
713ee684603Skettenis   /* This marks the outermost frame.  */
714ee684603Skettenis   if (cache->base == 0)
715ee684603Skettenis     return;
716ee684603Skettenis 
717ee684603Skettenis   (*this_id) = frame_id_build (cache->base, cache->pc);
718ee684603Skettenis }
719ee684603Skettenis 
720ee684603Skettenis static void
m88k_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)721ee684603Skettenis m88k_frame_prev_register (struct frame_info *next_frame, void **this_cache,
722ee684603Skettenis 			  int regnum, int *optimizedp,
723ee684603Skettenis 			  enum lval_type *lvalp, CORE_ADDR *addrp,
724ee684603Skettenis 			  int *realnump, void *valuep)
725ee684603Skettenis {
726ee684603Skettenis   struct m88k_frame_cache *cache = m88k_frame_cache (next_frame, this_cache);
727ee684603Skettenis 
728ee684603Skettenis   if (regnum == M88K_SNIP_REGNUM || regnum == M88K_SFIP_REGNUM)
729ee684603Skettenis     {
730ee684603Skettenis       if (valuep)
731ee684603Skettenis 	{
732ee684603Skettenis 	  CORE_ADDR pc;
733ee684603Skettenis 
73411efff7fSkettenis 	  trad_frame_get_prev_register (next_frame, cache->saved_regs,
735ee684603Skettenis 					M88K_SXIP_REGNUM, optimizedp,
736ee684603Skettenis 					lvalp, addrp, realnump, valuep);
737ee684603Skettenis 
738ee684603Skettenis 	  pc = extract_unsigned_integer (valuep, 4);
73928cbedccSkettenis 	  if (regnum == M88K_SFIP_REGNUM)
740ee684603Skettenis 	    pc += 4;
74128cbedccSkettenis 	  store_unsigned_integer (valuep, 4, pc + 4);
742ee684603Skettenis 	}
743ee684603Skettenis 
744ee684603Skettenis       /* It's a computed value.  */
745ee684603Skettenis       *optimizedp = 0;
746ee684603Skettenis       *lvalp = not_lval;
747ee684603Skettenis       *addrp = 0;
748ee684603Skettenis       *realnump = -1;
749ee684603Skettenis       return;
750ee684603Skettenis     }
751ee684603Skettenis 
75211efff7fSkettenis   trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum,
753ee684603Skettenis 				optimizedp, lvalp, addrp, realnump, valuep);
754ee684603Skettenis }
755ee684603Skettenis 
756ee684603Skettenis static const struct frame_unwind m88k_frame_unwind =
757ee684603Skettenis {
758ee684603Skettenis   NORMAL_FRAME,
759ee684603Skettenis   m88k_frame_this_id,
760ee684603Skettenis   m88k_frame_prev_register
761ee684603Skettenis };
762ee684603Skettenis 
763ee684603Skettenis static const struct frame_unwind *
m88k_frame_sniffer(struct frame_info * next_frame)764ee684603Skettenis m88k_frame_sniffer (struct frame_info *next_frame)
765ee684603Skettenis {
766ee684603Skettenis   return &m88k_frame_unwind;
767ee684603Skettenis }
768ee684603Skettenis 
769ee684603Skettenis 
770ee684603Skettenis static CORE_ADDR
m88k_frame_base_address(struct frame_info * next_frame,void ** this_cache)771ee684603Skettenis m88k_frame_base_address (struct frame_info *next_frame, void **this_cache)
772ee684603Skettenis {
773ee684603Skettenis   struct m88k_frame_cache *cache = m88k_frame_cache (next_frame, this_cache);
774ee684603Skettenis 
775ee684603Skettenis   if (cache->fp_offset != -1)
776ee684603Skettenis     return cache->base + cache->sp_offset + cache->fp_offset;
777ee684603Skettenis 
778ee684603Skettenis   return 0;
779ee684603Skettenis }
780ee684603Skettenis 
781ee684603Skettenis static const struct frame_base m88k_frame_base =
782ee684603Skettenis {
783ee684603Skettenis   &m88k_frame_unwind,
784ee684603Skettenis   m88k_frame_base_address,
785ee684603Skettenis   m88k_frame_base_address,
786ee684603Skettenis   m88k_frame_base_address
787ee684603Skettenis };
788ee684603Skettenis 
789ee684603Skettenis 
790ee684603Skettenis /* Core file support.  */
791ee684603Skettenis 
792ee684603Skettenis /* Supply register REGNUM from the buffer specified by GREGS and LEN
793ee684603Skettenis    in the general-purpose register set REGSET to register cache
794ee684603Skettenis    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
795ee684603Skettenis 
796ee684603Skettenis static void
m88k_supply_gregset(const struct regset * regset,struct regcache * regcache,int regnum,const void * gregs,size_t len)797ee684603Skettenis m88k_supply_gregset (const struct regset *regset,
798ee684603Skettenis 		     struct regcache *regcache,
799ee684603Skettenis 		     int regnum, const void *gregs, size_t len)
800ee684603Skettenis {
801ee684603Skettenis   const char *regs = gregs;
802ee684603Skettenis   int i;
803ee684603Skettenis 
804ee684603Skettenis   for (i = 0; i < M88K_NUM_REGS; i++)
805ee684603Skettenis     {
806ee684603Skettenis       if (regnum == i || regnum == -1)
807ee684603Skettenis 	regcache_raw_supply (regcache, i, regs + i * 4);
808ee684603Skettenis     }
809ee684603Skettenis }
810ee684603Skettenis 
811ee684603Skettenis /* Motorola 88000 register set.  */
812ee684603Skettenis 
813ee684603Skettenis static struct regset m88k_gregset =
814ee684603Skettenis {
815ee684603Skettenis   NULL,
816ee684603Skettenis   m88k_supply_gregset
817ee684603Skettenis };
818ee684603Skettenis 
819ee684603Skettenis /* Return the appropriate register set for the core section identified
820ee684603Skettenis    by SECT_NAME and SECT_SIZE.  */
821ee684603Skettenis 
822ee684603Skettenis static const struct regset *
m88k_regset_from_core_section(struct gdbarch * gdbarch,const char * sect_name,size_t sect_size)823ee684603Skettenis m88k_regset_from_core_section (struct gdbarch *gdbarch,
824ee684603Skettenis 			       const char *sect_name, size_t sect_size)
825ee684603Skettenis {
826ee684603Skettenis   if (strcmp (sect_name, ".reg") == 0 && sect_size >= M88K_NUM_REGS * 4)
827ee684603Skettenis     return &m88k_gregset;
828ee684603Skettenis 
829ee684603Skettenis   return NULL;
830ee684603Skettenis }
831ee684603Skettenis 
832ee684603Skettenis 
833ee684603Skettenis static struct gdbarch *
m88k_gdbarch_init(struct gdbarch_info info,struct gdbarch_list * arches)834ee684603Skettenis m88k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
835ee684603Skettenis {
836ee684603Skettenis   struct gdbarch *gdbarch;
837ee684603Skettenis 
838ee684603Skettenis   /* If there is already a candidate, use it.  */
839ee684603Skettenis   arches = gdbarch_list_lookup_by_info (arches, &info);
840ee684603Skettenis   if (arches != NULL)
841ee684603Skettenis     return arches->gdbarch;
842ee684603Skettenis 
843ee684603Skettenis   /* Allocate space for the new architecture.  */
844ee684603Skettenis   gdbarch = gdbarch_alloc (&info, NULL);
845ee684603Skettenis 
846ee684603Skettenis   /* There is no real `long double'.  */
847ee684603Skettenis   set_gdbarch_long_double_bit (gdbarch, 64);
848ee684603Skettenis   set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
849ee684603Skettenis 
850ee684603Skettenis   set_gdbarch_num_regs (gdbarch, M88K_NUM_REGS);
851ee684603Skettenis   set_gdbarch_register_name (gdbarch, m88k_register_name);
852ee684603Skettenis   set_gdbarch_register_type (gdbarch, m88k_register_type);
853ee684603Skettenis 
854ee684603Skettenis   /* Register numbers of various important registers.  */
855ee684603Skettenis   set_gdbarch_sp_regnum (gdbarch, M88K_R31_REGNUM);
856ee684603Skettenis   set_gdbarch_pc_regnum (gdbarch, M88K_SXIP_REGNUM);
857ee684603Skettenis 
858ee684603Skettenis   /* Core file support.  */
859ee684603Skettenis   set_gdbarch_regset_from_core_section
860ee684603Skettenis     (gdbarch, m88k_regset_from_core_section);
861ee684603Skettenis 
862ee684603Skettenis   set_gdbarch_print_insn (gdbarch, print_insn_m88k);
863ee684603Skettenis 
864ee684603Skettenis   set_gdbarch_skip_prologue (gdbarch, m88k_skip_prologue);
865ee684603Skettenis 
866ee684603Skettenis   /* Stack grows downward.  */
867ee684603Skettenis   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
868ee684603Skettenis 
869ee684603Skettenis   /* Call dummy code.  */
870ee684603Skettenis   set_gdbarch_push_dummy_call (gdbarch, m88k_push_dummy_call);
871ee684603Skettenis   set_gdbarch_unwind_dummy_id (gdbarch, m88k_unwind_dummy_id);
872ee684603Skettenis 
873ee684603Skettenis   /* Return value info */
874ee684603Skettenis   set_gdbarch_return_value (gdbarch, m88k_return_value);
875ee684603Skettenis 
876ee684603Skettenis   set_gdbarch_addr_bits_remove (gdbarch, m88k_addr_bits_remove);
877ee684603Skettenis   set_gdbarch_breakpoint_from_pc (gdbarch, m88k_breakpoint_from_pc);
878ee684603Skettenis   set_gdbarch_unwind_pc (gdbarch, m88k_unwind_pc);
879ee684603Skettenis   set_gdbarch_write_pc (gdbarch, m88k_write_pc);
880ee684603Skettenis 
881ee684603Skettenis   frame_base_set_default (gdbarch, &m88k_frame_base);
882*d0a35373Smiod 
883*d0a35373Smiod   /* Hook in ABI-specific overrides, if they have been registered.  */
884*d0a35373Smiod   gdbarch_init_osabi (info, gdbarch);
885*d0a35373Smiod 
886ee684603Skettenis   frame_unwind_append_sniffer (gdbarch, m88k_frame_sniffer);
887ee684603Skettenis 
888ee684603Skettenis   return gdbarch;
889ee684603Skettenis }
890ee684603Skettenis 
891ee684603Skettenis 
892ee684603Skettenis /* Provide a prototype to silence -Wmissing-prototypes.  */
893ee684603Skettenis void _initialize_m88k_tdep (void);
894ee684603Skettenis 
895ee684603Skettenis void
_initialize_m88k_tdep(void)896ee684603Skettenis _initialize_m88k_tdep (void)
897ee684603Skettenis {
898ee684603Skettenis   gdbarch_register (bfd_arch_m88k, m88k_gdbarch_init, NULL);
899ee684603Skettenis }
900