xref: /openbsd/gnu/usr.bin/binutils/gdb/m68k-tdep.c (revision 07ea8d15)
1 /* Target dependent code for the Motorola 68000 series.
2    Copyright (C) 1990, 1992 Free Software Foundation, Inc.
3 
4 This file is part of GDB.
5 
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19 
20 #include "defs.h"
21 #include "frame.h"
22 #include "symtab.h"
23 #include "gdbcore.h"
24 #include "value.h"
25 #include "gdb_string.h"
26 
27 
28 /* Push an empty stack frame, to record the current PC, etc.  */
29 
30 void
31 m68k_push_dummy_frame ()
32 {
33   register CORE_ADDR sp = read_register (SP_REGNUM);
34   register int regnum;
35   char raw_buffer[12];
36 
37   sp = push_word (sp, read_register (PC_REGNUM));
38   sp = push_word (sp, read_register (FP_REGNUM));
39   write_register (FP_REGNUM, sp);
40 
41   /* Always save the floating-point registers, whether they exist on
42      this target or not.  */
43   for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)
44     {
45       read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
46       sp = push_bytes (sp, raw_buffer, 12);
47     }
48 
49   for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)
50     {
51       sp = push_word (sp, read_register (regnum));
52     }
53   sp = push_word (sp, read_register (PS_REGNUM));
54   write_register (SP_REGNUM, sp);
55 }
56 
57 /* Discard from the stack the innermost frame,
58    restoring all saved registers.  */
59 
60 void
61 m68k_pop_frame ()
62 {
63   register struct frame_info *frame = get_current_frame ();
64   register CORE_ADDR fp;
65   register int regnum;
66   struct frame_saved_regs fsr;
67   char raw_buffer[12];
68 
69   fp = FRAME_FP (frame);
70   get_frame_saved_regs (frame, &fsr);
71   for (regnum = FP0_REGNUM + 7 ; regnum >= FP0_REGNUM ; regnum--)
72     {
73       if (fsr.regs[regnum])
74 	{
75 	  read_memory (fsr.regs[regnum], raw_buffer, 12);
76 	  write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
77 	}
78     }
79   for (regnum = FP_REGNUM - 1 ; regnum >= 0 ; regnum--)
80     {
81       if (fsr.regs[regnum])
82 	{
83 	  write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
84 	}
85     }
86   if (fsr.regs[PS_REGNUM])
87     {
88       write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4));
89     }
90   write_register (FP_REGNUM, read_memory_integer (fp, 4));
91   write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
92   write_register (SP_REGNUM, fp + 8);
93   flush_cached_frames ();
94 }
95 
96 
97 /* Given an ip value corresponding to the start of a function,
98    return the ip of the first instruction after the function
99    prologue.  This is the generic m68k support.  Machines which
100    require something different can override the SKIP_PROLOGUE
101    macro to point elsewhere.
102 
103    Some instructions which typically may appear in a function
104    prologue include:
105 
106    A link instruction, word form:
107 
108 	link.w	%a6,&0			4e56  XXXX
109 
110    A link instruction, long form:
111 
112 	link.l  %fp,&F%1		480e  XXXX  XXXX
113 
114    A movm instruction to preserve integer regs:
115 
116 	movm.l  &M%1,(4,%sp)		48ef  XXXX  XXXX
117 
118    A fmovm instruction to preserve float regs:
119 
120 	fmovm   &FPM%1,(FPO%1,%sp)	f237  XXXX  XXXX  XXXX  XXXX
121 
122    Some profiling setup code (FIXME, not recognized yet):
123 
124 	lea.l   (.L3,%pc),%a1		43fb  XXXX  XXXX  XXXX
125 	bsr     _mcount			61ff  XXXX  XXXX
126 
127   */
128 
129 #define P_LINK_L	0x480e
130 #define P_LINK_W	0x4e56
131 #define P_MOV_L		0x207c
132 #define P_JSR		0x4eb9
133 #define P_BSR		0x61ff
134 #define P_LEA_L		0x43fb
135 #define P_MOVM_L	0x48ef
136 #define P_FMOVM		0xf237
137 #define P_TRAP		0x4e40
138 
139 CORE_ADDR
140 m68k_skip_prologue (ip)
141 CORE_ADDR ip;
142 {
143   register CORE_ADDR limit;
144   struct symtab_and_line sal;
145   register int op;
146 
147   /* Find out if there is a known limit for the extent of the prologue.
148      If so, ensure we don't go past it.  If not, assume "infinity". */
149 
150   sal = find_pc_line (ip, 0);
151   limit = (sal.end) ? sal.end : (CORE_ADDR) ~0;
152 
153   while (ip < limit)
154     {
155       op = read_memory_integer (ip, 2);
156       op &= 0xFFFF;
157 
158       if (op == P_LINK_W)
159 	{
160 	  ip += 4;	/* Skip link.w */
161 	}
162       else if (op == 0x4856)
163 	ip += 2; /* Skip pea %fp */
164       else if (op == 0x2c4f)
165 	ip += 2; /* Skip move.l %sp, %fp */
166       else if (op == P_LINK_L)
167 	{
168 	  ip += 6;	/* Skip link.l */
169 	}
170       else if (op == P_MOVM_L)
171 	{
172 	  ip += 6;	/* Skip movm.l */
173 	}
174       else if (op == P_FMOVM)
175 	{
176 	  ip += 10;	/* Skip fmovm */
177 	}
178       else
179 	{
180 	  break;	/* Found unknown code, bail out. */
181 	}
182     }
183   return (ip);
184 }
185 
186 void
187 m68k_find_saved_regs (frame_info, saved_regs)
188      struct frame_info *frame_info;
189      struct frame_saved_regs *saved_regs;
190 {
191   register int regnum;
192   register int regmask;
193   register CORE_ADDR next_addr;
194   register CORE_ADDR pc;
195 
196   /* First possible address for a pc in a call dummy for this frame.  */
197   CORE_ADDR possible_call_dummy_start =
198     (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 4 - 8*12;
199 
200   int nextinsn;
201   memset (saved_regs, 0, sizeof (*saved_regs));
202   if ((frame_info)->pc >= possible_call_dummy_start
203       && (frame_info)->pc <= (frame_info)->frame)
204     {
205 
206       /* It is a call dummy.  We could just stop now, since we know
207 	 what the call dummy saves and where.  But this code proceeds
208 	 to parse the "prologue" which is part of the call dummy.
209 	 This is needlessly complex and confusing.  FIXME.  */
210 
211       next_addr = (frame_info)->frame;
212       pc = possible_call_dummy_start;
213     }
214   else
215     {
216       pc = get_pc_function_start ((frame_info)->pc);
217 
218       if (0x4856 == read_memory_integer (pc, 2)
219 	  && 0x2c4f == read_memory_integer (pc + 2, 2))
220 	{
221 	  /*
222 	    pea %fp
223             move.l %sp, %fp */
224 
225 	  pc += 4;
226 	  next_addr = frame_info->frame;
227 	}
228       else if (044016 == read_memory_integer (pc, 2))
229 	/* link.l %fp */
230 	/* Find the address above the saved
231 	   regs using the amount of storage from the link instruction.  */
232 	next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 4), pc+=4;
233       else if (047126 == read_memory_integer (pc, 2))
234 	/* link.w %fp */
235 	/* Find the address above the saved
236 	   regs using the amount of storage from the link instruction.  */
237 	next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 2), pc+=2;
238       else goto lose;
239 
240       /* If have an addal #-n, sp next, adjust next_addr.  */
241       if ((0177777 & read_memory_integer (pc, 2)) == 0157774)
242 	next_addr += read_memory_integer (pc += 2, 4), pc += 4;
243     }
244   regmask = read_memory_integer (pc + 2, 2);
245 
246   /* Here can come an fmovem.  Check for it.  */
247   nextinsn = 0xffff & read_memory_integer (pc, 2);
248   if (0xf227 == nextinsn
249       && (regmask & 0xff00) == 0xe000)
250     { pc += 4; /* Regmask's low bit is for register fp7, the first pushed */
251       for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1)
252 	if (regmask & 1)
253           saved_regs->regs[regnum] = (next_addr -= 12);
254       regmask = read_memory_integer (pc + 2, 2); }
255 
256   /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */
257   if (0044327 == read_memory_integer (pc, 2))
258     { pc += 4; /* Regmask's low bit is for register 0, the first written */
259       for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)
260 	if (regmask & 1)
261           saved_regs->regs[regnum] = (next_addr += 4) - 4; }
262   else if (0044347 == read_memory_integer (pc, 2))
263     {
264       pc += 4; /* Regmask's low bit is for register 15, the first pushed */
265       for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1)
266 	if (regmask & 1)
267           saved_regs->regs[regnum] = (next_addr -= 4);
268     }
269   else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2)))
270     {
271       regnum = 0xf & read_memory_integer (pc, 2); pc += 2;
272       saved_regs->regs[regnum] = (next_addr -= 4);
273       /* gcc, at least, may use a pair of movel instructions when saving
274 	 exactly 2 registers.  */
275       if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2)))
276 	{
277 	  regnum = 0xf & read_memory_integer (pc, 2);
278 	  pc += 2;
279 	  saved_regs->regs[regnum] = (next_addr -= 4);
280 	}
281     }
282 
283   /* fmovemx to index of sp may follow.  */
284   regmask = read_memory_integer (pc + 2, 2);
285   nextinsn = 0xffff & read_memory_integer (pc, 2);
286   if (0xf236 == nextinsn
287       && (regmask & 0xff00) == 0xf000)
288     { pc += 10; /* Regmask's low bit is for register fp0, the first written */
289       for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1)
290 	if (regmask & 1)
291           saved_regs->regs[regnum] = (next_addr += 12) - 12;
292       regmask = read_memory_integer (pc + 2, 2); }
293 
294   /* clrw -(sp); movw ccr,-(sp) may follow.  */
295   if (0x426742e7 == read_memory_integer (pc, 4))
296     saved_regs->regs[PS_REGNUM] = (next_addr -= 4);
297   lose: ;
298   saved_regs->regs[SP_REGNUM] = (frame_info)->frame + 8;
299   saved_regs->regs[FP_REGNUM] = (frame_info)->frame;
300   saved_regs->regs[PC_REGNUM] = (frame_info)->frame + 4;
301 #ifdef SIG_SP_FP_OFFSET
302   /* Adjust saved SP_REGNUM for fake _sigtramp frames.  */
303   if (frame_info->signal_handler_caller && frame_info->next)
304     saved_regs->regs[SP_REGNUM] = frame_info->next->frame + SIG_SP_FP_OFFSET;
305 #endif
306 }
307 
308 
309 #ifdef USE_PROC_FS	/* Target dependent support for /proc */
310 
311 #include <sys/procfs.h>
312 
313 /*  The /proc interface divides the target machine's register set up into
314     two different sets, the general register set (gregset) and the floating
315     point register set (fpregset).  For each set, there is an ioctl to get
316     the current register set and another ioctl to set the current values.
317 
318     The actual structure passed through the ioctl interface is, of course,
319     naturally machine dependent, and is different for each set of registers.
320     For the m68k for example, the general register set is typically defined
321     by:
322 
323 	typedef int gregset_t[18];
324 
325 	#define	R_D0	0
326 	...
327 	#define	R_PS	17
328 
329     and the floating point set by:
330 
331     	typedef	struct fpregset {
332 	  int	f_pcr;
333 	  int	f_psr;
334 	  int	f_fpiaddr;
335 	  int	f_fpregs[8][3];		(8 regs, 96 bits each)
336 	} fpregset_t;
337 
338     These routines provide the packing and unpacking of gregset_t and
339     fpregset_t formatted data.
340 
341  */
342 
343 /* Atari SVR4 has R_SR but not R_PS */
344 
345 #if !defined (R_PS) && defined (R_SR)
346 #define R_PS R_SR
347 #endif
348 
349 /*  Given a pointer to a general register set in /proc format (gregset_t *),
350     unpack the register contents and supply them as gdb's idea of the current
351     register values. */
352 
353 void
354 supply_gregset (gregsetp)
355 gregset_t *gregsetp;
356 {
357   register int regi;
358   register greg_t *regp = (greg_t *) gregsetp;
359 
360   for (regi = 0 ; regi < R_PC ; regi++)
361     {
362       supply_register (regi, (char *) (regp + regi));
363     }
364   supply_register (PS_REGNUM, (char *) (regp + R_PS));
365   supply_register (PC_REGNUM, (char *) (regp + R_PC));
366 }
367 
368 void
369 fill_gregset (gregsetp, regno)
370 gregset_t *gregsetp;
371 int regno;
372 {
373   register int regi;
374   register greg_t *regp = (greg_t *) gregsetp;
375   extern char registers[];
376 
377   for (regi = 0 ; regi < R_PC ; regi++)
378     {
379       if ((regno == -1) || (regno == regi))
380 	{
381 	  *(regp + regi) = *(int *) &registers[REGISTER_BYTE (regi)];
382 	}
383     }
384   if ((regno == -1) || (regno == PS_REGNUM))
385     {
386       *(regp + R_PS) = *(int *) &registers[REGISTER_BYTE (PS_REGNUM)];
387     }
388   if ((regno == -1) || (regno == PC_REGNUM))
389     {
390       *(regp + R_PC) = *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
391     }
392 }
393 
394 #if defined (FP0_REGNUM)
395 
396 /*  Given a pointer to a floating point register set in /proc format
397     (fpregset_t *), unpack the register contents and supply them as gdb's
398     idea of the current floating point register values. */
399 
400 void
401 supply_fpregset (fpregsetp)
402 fpregset_t *fpregsetp;
403 {
404   register int regi;
405   char *from;
406 
407   for (regi = FP0_REGNUM ; regi < FPC_REGNUM ; regi++)
408     {
409       from = (char *) &(fpregsetp -> f_fpregs[regi-FP0_REGNUM][0]);
410       supply_register (regi, from);
411     }
412   supply_register (FPC_REGNUM, (char *) &(fpregsetp -> f_pcr));
413   supply_register (FPS_REGNUM, (char *) &(fpregsetp -> f_psr));
414   supply_register (FPI_REGNUM, (char *) &(fpregsetp -> f_fpiaddr));
415 }
416 
417 /*  Given a pointer to a floating point register set in /proc format
418     (fpregset_t *), update the register specified by REGNO from gdb's idea
419     of the current floating point register set.  If REGNO is -1, update
420     them all. */
421 
422 void
423 fill_fpregset (fpregsetp, regno)
424 fpregset_t *fpregsetp;
425 int regno;
426 {
427   int regi;
428   char *to;
429   char *from;
430   extern char registers[];
431 
432   for (regi = FP0_REGNUM ; regi < FPC_REGNUM ; regi++)
433     {
434       if ((regno == -1) || (regno == regi))
435 	{
436 	  from = (char *) &registers[REGISTER_BYTE (regi)];
437 	  to = (char *) &(fpregsetp -> f_fpregs[regi-FP0_REGNUM][0]);
438 	  memcpy (to, from, REGISTER_RAW_SIZE (regi));
439 	}
440     }
441   if ((regno == -1) || (regno == FPC_REGNUM))
442     {
443       fpregsetp -> f_pcr = *(int *) &registers[REGISTER_BYTE (FPC_REGNUM)];
444     }
445   if ((regno == -1) || (regno == FPS_REGNUM))
446     {
447       fpregsetp -> f_psr = *(int *) &registers[REGISTER_BYTE (FPS_REGNUM)];
448     }
449   if ((regno == -1) || (regno == FPI_REGNUM))
450     {
451       fpregsetp -> f_fpiaddr = *(int *) &registers[REGISTER_BYTE (FPI_REGNUM)];
452     }
453 }
454 
455 #endif	/* defined (FP0_REGNUM) */
456 
457 #endif  /* USE_PROC_FS */
458 
459 #ifdef GET_LONGJMP_TARGET
460 /* Figure out where the longjmp will land.  Slurp the args out of the stack.
461    We expect the first arg to be a pointer to the jmp_buf structure from which
462    we extract the pc (JB_PC) that we will land at.  The pc is copied into PC.
463    This routine returns true on success. */
464 
465 int
466 get_longjmp_target(pc)
467      CORE_ADDR *pc;
468 {
469   char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
470   CORE_ADDR sp, jb_addr;
471 
472   sp = read_register(SP_REGNUM);
473 
474   if (target_read_memory (sp + SP_ARG0, /* Offset of first arg on stack */
475 			  buf,
476 			  TARGET_PTR_BIT / TARGET_CHAR_BIT))
477     return 0;
478 
479   jb_addr = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
480 
481   if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
482 			  TARGET_PTR_BIT / TARGET_CHAR_BIT))
483     return 0;
484 
485   *pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
486 
487   return 1;
488 }
489 #endif /* GET_LONGJMP_TARGET */
490 
491 /* Immediately after a function call, return the saved pc before the frame
492    is setup.  For sun3's, we check for the common case of being inside of a
493    system call, and if so, we know that Sun pushes the call # on the stack
494    prior to doing the trap. */
495 
496 CORE_ADDR
497 m68k_saved_pc_after_call(frame)
498      struct frame_info *frame;
499 {
500 #ifdef SYSCALL_TRAP
501   int op;
502 
503   op = read_memory_integer (frame->pc - SYSCALL_TRAP_OFFSET, 2);
504 
505   if (op == SYSCALL_TRAP)
506     return read_memory_integer (read_register (SP_REGNUM) + 4, 4);
507   else
508 #endif /* SYSCALL_TRAP */
509     return read_memory_integer (read_register (SP_REGNUM), 4);
510 }
511 
512 void
513 _initialize_m68k_tdep ()
514 {
515   tm_print_insn = print_insn_m68k;
516 }
517