1 /* Target dependent code for the Motorola 68000 series.
2 Copyright (C) 1990, 1992 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
25 #include "gdb_string.h"
29 /* The only reason this is here is the tm-altos.h reference below. It
30 was moved back here from tm-m68k.h. FIXME? */
33 altos_skip_prologue (pc
)
36 register int op
= read_memory_integer (pc
, 2);
38 pc
+= 4; /* Skip link #word */
39 else if (op
== 0044016)
40 pc
+= 6; /* Skip link #long */
41 /* Not sure why branches are here. */
42 /* From tm-isi.h, tm-altos.h */
43 else if (op
== 0060000)
44 pc
+= 4; /* Skip bra #word */
45 else if (op
== 00600377)
46 pc
+= 6; /* skip bra #long */
47 else if ((op
& 0177400) == 0060000)
48 pc
+= 2; /* skip bra #char */
52 /* The only reason this is here is the tm-isi.h reference below. It
53 was moved back here from tm-m68k.h. FIXME? */
56 isi_skip_prologue (pc
)
59 register int op
= read_memory_integer (pc
, 2);
61 pc
+= 4; /* Skip link #word */
62 else if (op
== 0044016)
63 pc
+= 6; /* Skip link #long */
64 /* Not sure why branches are here. */
65 /* From tm-isi.h, tm-altos.h */
66 else if (op
== 0060000)
67 pc
+= 4; /* Skip bra #word */
68 else if (op
== 00600377)
69 pc
+= 6; /* skip bra #long */
70 else if ((op
& 0177400) == 0060000)
71 pc
+= 2; /* skip bra #char */
75 /* Return number of args passed to a frame.
76 Can return -1, meaning no way to tell. */
79 isi_frame_num_args (fi
)
80 struct frame_info
*fi
;
83 CORE_ADDR pc
= FRAME_SAVED_PC (fi
);
84 int insn
= 0177777 & read_memory_integer (pc
, 2);
86 if (insn
== 0047757 || insn
== 0157374) /* lea W(sp),sp or addaw #W,sp */
87 val
= read_memory_integer (pc
+ 2, 2);
88 else if ((insn
& 0170777) == 0050217 /* addql #N, sp */
89 || (insn
& 0170777) == 0050117) /* addqw */
91 val
= (insn
>> 9) & 7;
95 else if (insn
== 0157774) /* addal #WW, sp */
96 val
= read_memory_integer (pc
+ 2, 4);
102 delta68_frame_num_args (fi
)
103 struct frame_info
*fi
;
106 CORE_ADDR pc
= FRAME_SAVED_PC (fi
);
107 int insn
= 0177777 & read_memory_integer (pc
, 2);
109 if (insn
== 0047757 || insn
== 0157374) /* lea W(sp),sp or addaw #W,sp */
110 val
= read_memory_integer (pc
+ 2, 2);
111 else if ((insn
& 0170777) == 0050217 /* addql #N, sp */
112 || (insn
& 0170777) == 0050117) /* addqw */
114 val
= (insn
>> 9) & 7;
118 else if (insn
== 0157774) /* addal #WW, sp */
119 val
= read_memory_integer (pc
+ 2, 4);
125 news_frame_num_args (fi
)
126 struct frame_info
*fi
;
129 CORE_ADDR pc
= FRAME_SAVED_PC (fi
);
130 int insn
= 0177777 & read_memory_integer (pc
, 2);
132 if (insn
== 0047757 || insn
== 0157374) /* lea W(sp),sp or addaw #W,sp */
133 val
= read_memory_integer (pc
+ 2, 2);
134 else if ((insn
& 0170777) == 0050217 /* addql #N, sp */
135 || (insn
& 0170777) == 0050117) /* addqw */
137 val
= (insn
>> 9) & 7;
141 else if (insn
== 0157774) /* addal #WW, sp */
142 val
= read_memory_integer (pc
+ 2, 4);
147 /* Push an empty stack frame, to record the current PC, etc. */
150 m68k_push_dummy_frame ()
152 register CORE_ADDR sp
= read_register (SP_REGNUM
);
156 sp
= push_word (sp
, read_register (PC_REGNUM
));
157 sp
= push_word (sp
, read_register (FP_REGNUM
));
158 write_register (FP_REGNUM
, sp
);
160 /* Always save the floating-point registers, whether they exist on
161 this target or not. */
162 for (regnum
= FP0_REGNUM
+ 7; regnum
>= FP0_REGNUM
; regnum
--)
164 read_register_bytes (REGISTER_BYTE (regnum
), raw_buffer
, 12);
165 sp
= push_bytes (sp
, raw_buffer
, 12);
168 for (regnum
= FP_REGNUM
- 1; regnum
>= 0; regnum
--)
170 sp
= push_word (sp
, read_register (regnum
));
172 sp
= push_word (sp
, read_register (PS_REGNUM
));
173 write_register (SP_REGNUM
, sp
);
176 /* Discard from the stack the innermost frame,
177 restoring all saved registers. */
182 register struct frame_info
*frame
= get_current_frame ();
183 register CORE_ADDR fp
;
185 struct frame_saved_regs fsr
;
188 fp
= FRAME_FP (frame
);
189 get_frame_saved_regs (frame
, &fsr
);
190 for (regnum
= FP0_REGNUM
+ 7 ; regnum
>= FP0_REGNUM
; regnum
--)
192 if (fsr
.regs
[regnum
])
194 read_memory (fsr
.regs
[regnum
], raw_buffer
, 12);
195 write_register_bytes (REGISTER_BYTE (regnum
), raw_buffer
, 12);
198 for (regnum
= FP_REGNUM
- 1 ; regnum
>= 0 ; regnum
--)
200 if (fsr
.regs
[regnum
])
202 write_register (regnum
, read_memory_integer (fsr
.regs
[regnum
], 4));
205 if (fsr
.regs
[PS_REGNUM
])
207 write_register (PS_REGNUM
, read_memory_integer (fsr
.regs
[PS_REGNUM
], 4));
209 write_register (FP_REGNUM
, read_memory_integer (fp
, 4));
210 write_register (PC_REGNUM
, read_memory_integer (fp
+ 4, 4));
211 write_register (SP_REGNUM
, fp
+ 8);
212 flush_cached_frames ();
216 /* Given an ip value corresponding to the start of a function,
217 return the ip of the first instruction after the function
218 prologue. This is the generic m68k support. Machines which
219 require something different can override the SKIP_PROLOGUE
220 macro to point elsewhere.
222 Some instructions which typically may appear in a function
225 A link instruction, word form:
227 link.w %a6,&0 4e56 XXXX
229 A link instruction, long form:
231 link.l %fp,&F%1 480e XXXX XXXX
233 A movm instruction to preserve integer regs:
235 movm.l &M%1,(4,%sp) 48ef XXXX XXXX
237 A fmovm instruction to preserve float regs:
239 fmovm &FPM%1,(FPO%1,%sp) f237 XXXX XXXX XXXX XXXX
241 Some profiling setup code (FIXME, not recognized yet):
243 lea.l (.L3,%pc),%a1 43fb XXXX XXXX XXXX
244 bsr _mcount 61ff XXXX XXXX
248 #define P_LINK_L 0x480e
249 #define P_LINK_W 0x4e56
250 #define P_MOV_L 0x207c
253 #define P_LEA_L 0x43fb
254 #define P_MOVM_L 0x48ef
255 #define P_FMOVM 0xf237
256 #define P_TRAP 0x4e40
259 m68k_skip_prologue (ip
)
262 register CORE_ADDR limit
;
263 struct symtab_and_line sal
;
266 /* Find out if there is a known limit for the extent of the prologue.
267 If so, ensure we don't go past it. If not, assume "infinity". */
269 sal
= find_pc_line (ip
, 0);
270 limit
= (sal
.end
) ? sal
.end
: (CORE_ADDR
) ~0;
274 op
= read_memory_integer (ip
, 2);
279 ip
+= 4; /* Skip link.w */
281 else if (op
== 0x4856)
282 ip
+= 2; /* Skip pea %fp */
283 else if (op
== 0x2c4f)
284 ip
+= 2; /* Skip move.l %sp, %fp */
285 else if (op
== P_LINK_L
)
287 ip
+= 6; /* Skip link.l */
289 else if (op
== P_MOVM_L
)
291 ip
+= 6; /* Skip movm.l */
293 else if (op
== P_FMOVM
)
295 ip
+= 10; /* Skip fmovm */
299 break; /* Found unknown code, bail out. */
306 m68k_find_saved_regs (frame_info
, saved_regs
)
307 struct frame_info
*frame_info
;
308 struct frame_saved_regs
*saved_regs
;
311 register int regmask
;
312 register CORE_ADDR next_addr
;
313 register CORE_ADDR pc
;
315 /* First possible address for a pc in a call dummy for this frame. */
316 CORE_ADDR possible_call_dummy_start
=
317 (frame_info
)->frame
- CALL_DUMMY_LENGTH
- FP_REGNUM
*4 - 4 - 8*12;
320 memset (saved_regs
, 0, sizeof (*saved_regs
));
321 if ((frame_info
)->pc
>= possible_call_dummy_start
322 && (frame_info
)->pc
<= (frame_info
)->frame
)
325 /* It is a call dummy. We could just stop now, since we know
326 what the call dummy saves and where. But this code proceeds
327 to parse the "prologue" which is part of the call dummy.
328 This is needlessly complex and confusing. FIXME. */
330 next_addr
= (frame_info
)->frame
;
331 pc
= possible_call_dummy_start
;
335 pc
= get_pc_function_start ((frame_info
)->pc
);
337 if (0x4856 == read_memory_integer (pc
, 2)
338 && 0x2c4f == read_memory_integer (pc
+ 2, 2))
345 next_addr
= frame_info
->frame
;
347 else if (044016 == read_memory_integer (pc
, 2))
349 /* Find the address above the saved
350 regs using the amount of storage from the link instruction. */
351 next_addr
= (frame_info
)->frame
+ read_memory_integer (pc
+= 2, 4), pc
+=4;
352 else if (047126 == read_memory_integer (pc
, 2))
354 /* Find the address above the saved
355 regs using the amount of storage from the link instruction. */
356 next_addr
= (frame_info
)->frame
+ read_memory_integer (pc
+= 2, 2), pc
+=2;
359 /* If have an addal #-n, sp next, adjust next_addr. */
360 if ((0177777 & read_memory_integer (pc
, 2)) == 0157774)
361 next_addr
+= read_memory_integer (pc
+= 2, 4), pc
+= 4;
363 regmask
= read_memory_integer (pc
+ 2, 2);
365 /* Here can come an fmovem. Check for it. */
366 nextinsn
= 0xffff & read_memory_integer (pc
, 2);
367 if (0xf227 == nextinsn
368 && (regmask
& 0xff00) == 0xe000)
369 { pc
+= 4; /* Regmask's low bit is for register fp7, the first pushed */
370 for (regnum
= FP0_REGNUM
+ 7; regnum
>= FP0_REGNUM
; regnum
--, regmask
>>= 1)
372 saved_regs
->regs
[regnum
] = (next_addr
-= 12);
373 regmask
= read_memory_integer (pc
+ 2, 2); }
375 /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */
376 if (0044327 == read_memory_integer (pc
, 2))
377 { pc
+= 4; /* Regmask's low bit is for register 0, the first written */
378 for (regnum
= 0; regnum
< 16; regnum
++, regmask
>>= 1)
380 saved_regs
->regs
[regnum
] = (next_addr
+= 4) - 4; }
381 else if (0044347 == read_memory_integer (pc
, 2))
383 pc
+= 4; /* Regmask's low bit is for register 15, the first pushed */
384 for (regnum
= 15; regnum
>= 0; regnum
--, regmask
>>= 1)
386 saved_regs
->regs
[regnum
] = (next_addr
-= 4);
388 else if (0x2f00 == (0xfff0 & read_memory_integer (pc
, 2)))
390 regnum
= 0xf & read_memory_integer (pc
, 2); pc
+= 2;
391 saved_regs
->regs
[regnum
] = (next_addr
-= 4);
392 /* gcc, at least, may use a pair of movel instructions when saving
393 exactly 2 registers. */
394 if (0x2f00 == (0xfff0 & read_memory_integer (pc
, 2)))
396 regnum
= 0xf & read_memory_integer (pc
, 2);
398 saved_regs
->regs
[regnum
] = (next_addr
-= 4);
402 /* fmovemx to index of sp may follow. */
403 regmask
= read_memory_integer (pc
+ 2, 2);
404 nextinsn
= 0xffff & read_memory_integer (pc
, 2);
405 if (0xf236 == nextinsn
406 && (regmask
& 0xff00) == 0xf000)
407 { pc
+= 10; /* Regmask's low bit is for register fp0, the first written */
408 for (regnum
= FP0_REGNUM
+ 7; regnum
>= FP0_REGNUM
; regnum
--, regmask
>>= 1)
410 saved_regs
->regs
[regnum
] = (next_addr
+= 12) - 12;
411 regmask
= read_memory_integer (pc
+ 2, 2); }
413 /* clrw -(sp); movw ccr,-(sp) may follow. */
414 if (0x426742e7 == read_memory_integer (pc
, 4))
415 saved_regs
->regs
[PS_REGNUM
] = (next_addr
-= 4);
417 saved_regs
->regs
[SP_REGNUM
] = (frame_info
)->frame
+ 8;
418 saved_regs
->regs
[FP_REGNUM
] = (frame_info
)->frame
;
419 saved_regs
->regs
[PC_REGNUM
] = (frame_info
)->frame
+ 4;
420 #ifdef SIG_SP_FP_OFFSET
421 /* Adjust saved SP_REGNUM for fake _sigtramp frames. */
422 if (frame_info
->signal_handler_caller
&& frame_info
->next
)
423 saved_regs
->regs
[SP_REGNUM
] = frame_info
->next
->frame
+ SIG_SP_FP_OFFSET
;
428 #ifdef USE_PROC_FS /* Target dependent support for /proc */
430 #include <sys/procfs.h>
432 /* The /proc interface divides the target machine's register set up into
433 two different sets, the general register set (gregset) and the floating
434 point register set (fpregset). For each set, there is an ioctl to get
435 the current register set and another ioctl to set the current values.
437 The actual structure passed through the ioctl interface is, of course,
438 naturally machine dependent, and is different for each set of registers.
439 For the m68k for example, the general register set is typically defined
442 typedef int gregset_t[18];
448 and the floating point set by:
450 typedef struct fpregset {
454 int f_fpregs[8][3]; (8 regs, 96 bits each)
457 These routines provide the packing and unpacking of gregset_t and
458 fpregset_t formatted data.
462 /* Atari SVR4 has R_SR but not R_PS */
464 #if !defined (R_PS) && defined (R_SR)
468 /* Given a pointer to a general register set in /proc format (gregset_t *),
469 unpack the register contents and supply them as gdb's idea of the current
473 supply_gregset (gregsetp
)
477 register greg_t
*regp
= (greg_t
*) gregsetp
;
479 for (regi
= 0 ; regi
< R_PC
; regi
++)
481 supply_register (regi
, (char *) (regp
+ regi
));
483 supply_register (PS_REGNUM
, (char *) (regp
+ R_PS
));
484 supply_register (PC_REGNUM
, (char *) (regp
+ R_PC
));
488 fill_gregset (gregsetp
, regno
)
493 register greg_t
*regp
= (greg_t
*) gregsetp
;
495 for (regi
= 0 ; regi
< R_PC
; regi
++)
497 if ((regno
== -1) || (regno
== regi
))
499 *(regp
+ regi
) = *(int *) ®isters
[REGISTER_BYTE (regi
)];
502 if ((regno
== -1) || (regno
== PS_REGNUM
))
504 *(regp
+ R_PS
) = *(int *) ®isters
[REGISTER_BYTE (PS_REGNUM
)];
506 if ((regno
== -1) || (regno
== PC_REGNUM
))
508 *(regp
+ R_PC
) = *(int *) ®isters
[REGISTER_BYTE (PC_REGNUM
)];
512 #if defined (FP0_REGNUM)
514 /* Given a pointer to a floating point register set in /proc format
515 (fpregset_t *), unpack the register contents and supply them as gdb's
516 idea of the current floating point register values. */
519 supply_fpregset (fpregsetp
)
520 fpregset_t
*fpregsetp
;
525 for (regi
= FP0_REGNUM
; regi
< FPC_REGNUM
; regi
++)
527 from
= (char *) &(fpregsetp
-> f_fpregs
[regi
-FP0_REGNUM
][0]);
528 supply_register (regi
, from
);
530 supply_register (FPC_REGNUM
, (char *) &(fpregsetp
-> f_pcr
));
531 supply_register (FPS_REGNUM
, (char *) &(fpregsetp
-> f_psr
));
532 supply_register (FPI_REGNUM
, (char *) &(fpregsetp
-> f_fpiaddr
));
535 /* Given a pointer to a floating point register set in /proc format
536 (fpregset_t *), update the register specified by REGNO from gdb's idea
537 of the current floating point register set. If REGNO is -1, update
541 fill_fpregset (fpregsetp
, regno
)
542 fpregset_t
*fpregsetp
;
549 for (regi
= FP0_REGNUM
; regi
< FPC_REGNUM
; regi
++)
551 if ((regno
== -1) || (regno
== regi
))
553 from
= (char *) ®isters
[REGISTER_BYTE (regi
)];
554 to
= (char *) &(fpregsetp
-> f_fpregs
[regi
-FP0_REGNUM
][0]);
555 memcpy (to
, from
, REGISTER_RAW_SIZE (regi
));
558 if ((regno
== -1) || (regno
== FPC_REGNUM
))
560 fpregsetp
-> f_pcr
= *(int *) ®isters
[REGISTER_BYTE (FPC_REGNUM
)];
562 if ((regno
== -1) || (regno
== FPS_REGNUM
))
564 fpregsetp
-> f_psr
= *(int *) ®isters
[REGISTER_BYTE (FPS_REGNUM
)];
566 if ((regno
== -1) || (regno
== FPI_REGNUM
))
568 fpregsetp
-> f_fpiaddr
= *(int *) ®isters
[REGISTER_BYTE (FPI_REGNUM
)];
572 #endif /* defined (FP0_REGNUM) */
574 #endif /* USE_PROC_FS */
576 #ifdef GET_LONGJMP_TARGET
577 /* Figure out where the longjmp will land. Slurp the args out of the stack.
578 We expect the first arg to be a pointer to the jmp_buf structure from which
579 we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
580 This routine returns true on success. */
583 get_longjmp_target(pc
)
586 char buf
[TARGET_PTR_BIT
/ TARGET_CHAR_BIT
];
587 CORE_ADDR sp
, jb_addr
;
589 sp
= read_register(SP_REGNUM
);
591 if (target_read_memory (sp
+ SP_ARG0
, /* Offset of first arg on stack */
593 TARGET_PTR_BIT
/ TARGET_CHAR_BIT
))
596 jb_addr
= extract_address (buf
, TARGET_PTR_BIT
/ TARGET_CHAR_BIT
);
598 if (target_read_memory (jb_addr
+ JB_PC
* JB_ELEMENT_SIZE
, buf
,
599 TARGET_PTR_BIT
/ TARGET_CHAR_BIT
))
602 *pc
= extract_address (buf
, TARGET_PTR_BIT
/ TARGET_CHAR_BIT
);
606 #endif /* GET_LONGJMP_TARGET */
608 /* Immediately after a function call, return the saved pc before the frame
609 is setup. For sun3's, we check for the common case of being inside of a
610 system call, and if so, we know that Sun pushes the call # on the stack
611 prior to doing the trap. */
614 m68k_saved_pc_after_call(frame
)
615 struct frame_info
*frame
;
620 op
= read_memory_integer (frame
->pc
- SYSCALL_TRAP_OFFSET
, 2);
622 if (op
== SYSCALL_TRAP
)
623 return read_memory_integer (read_register (SP_REGNUM
) + 4, 4);
625 #endif /* SYSCALL_TRAP */
626 return read_memory_integer (read_register (SP_REGNUM
), 4);
630 _initialize_m68k_tdep ()
632 tm_print_insn
= print_insn_m68k
;