* MAINTAINERS: Remove self from specific maintenance domains
[deliverable/binutils-gdb.git] / gdb / m68k-tdep.c
1 /* Target dependent code for the Motorola 68000 series.
2 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001
3 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include "defs.h"
23 #include "frame.h"
24 #include "symtab.h"
25 #include "gdbcore.h"
26 #include "value.h"
27 #include "gdb_string.h"
28 #include "inferior.h"
29 #include "regcache.h"
30 \f
31
32 #define P_LINKL_FP 0x480e
33 #define P_LINKW_FP 0x4e56
34 #define P_PEA_FP 0x4856
35 #define P_MOVL_SP_FP 0x2c4f
36 #define P_MOVL 0x207c
37 #define P_JSR 0x4eb9
38 #define P_BSR 0x61ff
39 #define P_LEAL 0x43fb
40 #define P_MOVML 0x48ef
41 #define P_FMOVM 0xf237
42 #define P_TRAP 0x4e40
43
44 /* The only reason this is here is the tm-altos.h reference below. It
45 was moved back here from tm-m68k.h. FIXME? */
46
47 extern CORE_ADDR
48 altos_skip_prologue (CORE_ADDR pc)
49 {
50 register int op = read_memory_integer (pc, 2);
51 if (op == P_LINKW_FP)
52 pc += 4; /* Skip link #word */
53 else if (op == P_LINKL_FP)
54 pc += 6; /* Skip link #long */
55 /* Not sure why branches are here. */
56 /* From tm-isi.h, tm-altos.h */
57 else if (op == 0060000)
58 pc += 4; /* Skip bra #word */
59 else if (op == 00600377)
60 pc += 6; /* skip bra #long */
61 else if ((op & 0177400) == 0060000)
62 pc += 2; /* skip bra #char */
63 return pc;
64 }
65
66 /* The only reason this is here is the tm-isi.h reference below. It
67 was moved back here from tm-m68k.h. FIXME? */
68
69 extern CORE_ADDR
70 isi_skip_prologue (CORE_ADDR pc)
71 {
72 register int op = read_memory_integer (pc, 2);
73 if (op == P_LINKW_FP)
74 pc += 4; /* Skip link #word */
75 else if (op == P_LINKL_FP)
76 pc += 6; /* Skip link #long */
77 /* Not sure why branches are here. */
78 /* From tm-isi.h, tm-altos.h */
79 else if (op == 0060000)
80 pc += 4; /* Skip bra #word */
81 else if (op == 00600377)
82 pc += 6; /* skip bra #long */
83 else if ((op & 0177400) == 0060000)
84 pc += 2; /* skip bra #char */
85 return pc;
86 }
87
88 int
89 delta68_in_sigtramp (CORE_ADDR pc, char *name)
90 {
91 if (name != NULL)
92 return strcmp (name, "_sigcode") == 0;
93 else
94 return 0;
95 }
96
97 CORE_ADDR
98 delta68_frame_args_address (struct frame_info *frame_info)
99 {
100 /* we assume here that the only frameless functions are the system calls
101 or other functions who do not put anything on the stack. */
102 if (frame_info->signal_handler_caller)
103 return frame_info->frame + 12;
104 else if (frameless_look_for_prologue (frame_info))
105 {
106 /* Check for an interrupted system call */
107 if (frame_info->next && frame_info->next->signal_handler_caller)
108 return frame_info->next->frame + 16;
109 else
110 return frame_info->frame + 4;
111 }
112 else
113 return frame_info->frame;
114 }
115
116 CORE_ADDR
117 delta68_frame_saved_pc (struct frame_info *frame_info)
118 {
119 return read_memory_integer (delta68_frame_args_address (frame_info) + 4, 4);
120 }
121
122 /* Return number of args passed to a frame.
123 Can return -1, meaning no way to tell. */
124
125 int
126 isi_frame_num_args (struct frame_info *fi)
127 {
128 int val;
129 CORE_ADDR pc = FRAME_SAVED_PC (fi);
130 int insn = 0177777 & read_memory_integer (pc, 2);
131 val = 0;
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 */
136 {
137 val = (insn >> 9) & 7;
138 if (val == 0)
139 val = 8;
140 }
141 else if (insn == 0157774) /* addal #WW, sp */
142 val = read_memory_integer (pc + 2, 4);
143 val >>= 2;
144 return val;
145 }
146
147 int
148 delta68_frame_num_args (struct frame_info *fi)
149 {
150 int val;
151 CORE_ADDR pc = FRAME_SAVED_PC (fi);
152 int insn = 0177777 & read_memory_integer (pc, 2);
153 val = 0;
154 if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */
155 val = read_memory_integer (pc + 2, 2);
156 else if ((insn & 0170777) == 0050217 /* addql #N, sp */
157 || (insn & 0170777) == 0050117) /* addqw */
158 {
159 val = (insn >> 9) & 7;
160 if (val == 0)
161 val = 8;
162 }
163 else if (insn == 0157774) /* addal #WW, sp */
164 val = read_memory_integer (pc + 2, 4);
165 val >>= 2;
166 return val;
167 }
168
169 int
170 news_frame_num_args (struct frame_info *fi)
171 {
172 int val;
173 CORE_ADDR pc = FRAME_SAVED_PC (fi);
174 int insn = 0177777 & read_memory_integer (pc, 2);
175 val = 0;
176 if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */
177 val = read_memory_integer (pc + 2, 2);
178 else if ((insn & 0170777) == 0050217 /* addql #N, sp */
179 || (insn & 0170777) == 0050117) /* addqw */
180 {
181 val = (insn >> 9) & 7;
182 if (val == 0)
183 val = 8;
184 }
185 else if (insn == 0157774) /* addal #WW, sp */
186 val = read_memory_integer (pc + 2, 4);
187 val >>= 2;
188 return val;
189 }
190
191 /* Push an empty stack frame, to record the current PC, etc. */
192
193 void
194 m68k_push_dummy_frame (void)
195 {
196 register CORE_ADDR sp = read_register (SP_REGNUM);
197 register int regnum;
198 char raw_buffer[12];
199
200 sp = push_word (sp, read_register (PC_REGNUM));
201 sp = push_word (sp, read_register (FP_REGNUM));
202 write_register (FP_REGNUM, sp);
203
204 /* Always save the floating-point registers, whether they exist on
205 this target or not. */
206 for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)
207 {
208 read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
209 sp = push_bytes (sp, raw_buffer, 12);
210 }
211
212 for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)
213 {
214 sp = push_word (sp, read_register (regnum));
215 }
216 sp = push_word (sp, read_register (PS_REGNUM));
217 write_register (SP_REGNUM, sp);
218 }
219
220 /* Discard from the stack the innermost frame,
221 restoring all saved registers. */
222
223 void
224 m68k_pop_frame (void)
225 {
226 register struct frame_info *frame = get_current_frame ();
227 register CORE_ADDR fp;
228 register int regnum;
229 struct frame_saved_regs fsr;
230 char raw_buffer[12];
231
232 fp = FRAME_FP (frame);
233 get_frame_saved_regs (frame, &fsr);
234 for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)
235 {
236 if (fsr.regs[regnum])
237 {
238 read_memory (fsr.regs[regnum], raw_buffer, 12);
239 write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
240 }
241 }
242 for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)
243 {
244 if (fsr.regs[regnum])
245 {
246 write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
247 }
248 }
249 if (fsr.regs[PS_REGNUM])
250 {
251 write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4));
252 }
253 write_register (FP_REGNUM, read_memory_integer (fp, 4));
254 write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
255 write_register (SP_REGNUM, fp + 8);
256 flush_cached_frames ();
257 }
258 \f
259
260 /* Given an ip value corresponding to the start of a function,
261 return the ip of the first instruction after the function
262 prologue. This is the generic m68k support. Machines which
263 require something different can override the SKIP_PROLOGUE
264 macro to point elsewhere.
265
266 Some instructions which typically may appear in a function
267 prologue include:
268
269 A link instruction, word form:
270
271 link.w %a6,&0 4e56 XXXX
272
273 A link instruction, long form:
274
275 link.l %fp,&F%1 480e XXXX XXXX
276
277 A movm instruction to preserve integer regs:
278
279 movm.l &M%1,(4,%sp) 48ef XXXX XXXX
280
281 A fmovm instruction to preserve float regs:
282
283 fmovm &FPM%1,(FPO%1,%sp) f237 XXXX XXXX XXXX XXXX
284
285 Some profiling setup code (FIXME, not recognized yet):
286
287 lea.l (.L3,%pc),%a1 43fb XXXX XXXX XXXX
288 bsr _mcount 61ff XXXX XXXX
289
290 */
291
292 CORE_ADDR
293 m68k_skip_prologue (CORE_ADDR ip)
294 {
295 register CORE_ADDR limit;
296 struct symtab_and_line sal;
297 register int op;
298
299 /* Find out if there is a known limit for the extent of the prologue.
300 If so, ensure we don't go past it. If not, assume "infinity". */
301
302 sal = find_pc_line (ip, 0);
303 limit = (sal.end) ? sal.end : (CORE_ADDR) ~ 0;
304
305 while (ip < limit)
306 {
307 op = read_memory_integer (ip, 2);
308 op &= 0xFFFF;
309
310 if (op == P_LINKW_FP)
311 ip += 4; /* Skip link.w */
312 else if (op == P_PEA_FP)
313 ip += 2; /* Skip pea %fp */
314 else if (op == P_MOVL_SP_FP)
315 ip += 2; /* Skip move.l %sp, %fp */
316 else if (op == P_LINKL_FP)
317 ip += 6; /* Skip link.l */
318 else if (op == P_MOVML)
319 ip += 6; /* Skip movm.l */
320 else if (op == P_FMOVM)
321 ip += 10; /* Skip fmovm */
322 else
323 break; /* Found unknown code, bail out. */
324 }
325 return (ip);
326 }
327
328 void
329 m68k_find_saved_regs (struct frame_info *frame_info,
330 struct frame_saved_regs *saved_regs)
331 {
332 register int regnum;
333 register int regmask;
334 register CORE_ADDR next_addr;
335 register CORE_ADDR pc;
336
337 /* First possible address for a pc in a call dummy for this frame. */
338 CORE_ADDR possible_call_dummy_start =
339 (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 4 - 8 * 12;
340
341 int nextinsn;
342 memset (saved_regs, 0, sizeof (*saved_regs));
343 if ((frame_info)->pc >= possible_call_dummy_start
344 && (frame_info)->pc <= (frame_info)->frame)
345 {
346
347 /* It is a call dummy. We could just stop now, since we know
348 what the call dummy saves and where. But this code proceeds
349 to parse the "prologue" which is part of the call dummy.
350 This is needlessly complex and confusing. FIXME. */
351
352 next_addr = (frame_info)->frame;
353 pc = possible_call_dummy_start;
354 }
355 else
356 {
357 pc = get_pc_function_start ((frame_info)->pc);
358
359 nextinsn = read_memory_integer (pc, 2);
360 if (P_PEA_FP == nextinsn
361 && P_MOVL_SP_FP == read_memory_integer (pc + 2, 2))
362 {
363 /* pea %fp
364 move.l %sp, %fp */
365 next_addr = frame_info->frame;
366 pc += 4;
367 }
368 else if (P_LINKL_FP == nextinsn)
369 /* link.l %fp */
370 /* Find the address above the saved
371 regs using the amount of storage from the link instruction. */
372 {
373 next_addr = (frame_info)->frame + read_memory_integer (pc + 2, 4);
374 pc += 6;
375 }
376 else if (P_LINKW_FP == nextinsn)
377 /* link.w %fp */
378 /* Find the address above the saved
379 regs using the amount of storage from the link instruction. */
380 {
381 next_addr = (frame_info)->frame + read_memory_integer (pc + 2, 2);
382 pc += 4;
383 }
384 else
385 goto lose;
386
387 /* If have an addal #-n, sp next, adjust next_addr. */
388 if ((0177777 & read_memory_integer (pc, 2)) == 0157774)
389 next_addr += read_memory_integer (pc += 2, 4), pc += 4;
390 }
391
392 for ( ; ; )
393 {
394 nextinsn = 0xffff & read_memory_integer (pc, 2);
395 regmask = read_memory_integer (pc + 2, 2);
396 /* fmovemx to -(sp) */
397 if (0xf227 == nextinsn && (regmask & 0xff00) == 0xe000)
398 {
399 /* Regmask's low bit is for register fp7, the first pushed */
400 for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1)
401 if (regmask & 1)
402 saved_regs->regs[regnum] = (next_addr -= 12);
403 pc += 4;
404 }
405 /* fmovemx to (fp + displacement) */
406 else if (0171056 == nextinsn && (regmask & 0xff00) == 0xf000)
407 {
408 register CORE_ADDR addr;
409
410 addr = (frame_info)->frame + read_memory_integer (pc + 4, 2);
411 /* Regmask's low bit is for register fp7, the first pushed */
412 for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1)
413 if (regmask & 1)
414 {
415 saved_regs->regs[regnum] = addr;
416 addr += 12;
417 }
418 pc += 6;
419 }
420 /* moveml to (sp) */
421 else if (0044327 == nextinsn)
422 {
423 /* Regmask's low bit is for register 0, the first written */
424 for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)
425 if (regmask & 1)
426 {
427 saved_regs->regs[regnum] = next_addr;
428 next_addr += 4;
429 }
430 pc += 4;
431 }
432 /* moveml to (fp + displacement) */
433 else if (0044356 == nextinsn)
434 {
435 register CORE_ADDR addr;
436
437 addr = (frame_info)->frame + read_memory_integer (pc + 4, 2);
438 /* Regmask's low bit is for register 0, the first written */
439 for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)
440 if (regmask & 1)
441 {
442 saved_regs->regs[regnum] = addr;
443 addr += 4;
444 }
445 pc += 6;
446 }
447 /* moveml to -(sp) */
448 else if (0044347 == nextinsn)
449 {
450 /* Regmask's low bit is for register 15, the first pushed */
451 for (regnum = 16; --regnum >= 0; regmask >>= 1)
452 if (regmask & 1)
453 saved_regs->regs[regnum] = (next_addr -= 4);
454 pc += 4;
455 }
456 /* movl r,-(sp) */
457 else if (0x2f00 == (0xfff0 & nextinsn))
458 {
459 regnum = 0xf & nextinsn;
460 saved_regs->regs[regnum] = (next_addr -= 4);
461 pc += 2;
462 }
463 /* fmovemx to index of sp */
464 else if (0xf236 == nextinsn && (regmask & 0xff00) == 0xf000)
465 {
466 /* Regmask's low bit is for register fp0, the first written */
467 for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1)
468 if (regmask & 1)
469 {
470 saved_regs->regs[regnum] = next_addr;
471 next_addr += 12;
472 }
473 pc += 10;
474 }
475 /* clrw -(sp); movw ccr,-(sp) */
476 else if (0x4267 == nextinsn && 0x42e7 == regmask)
477 {
478 saved_regs->regs[PS_REGNUM] = (next_addr -= 4);
479 pc += 4;
480 }
481 else
482 break;
483 }
484 lose:;
485 saved_regs->regs[SP_REGNUM] = (frame_info)->frame + 8;
486 saved_regs->regs[FP_REGNUM] = (frame_info)->frame;
487 saved_regs->regs[PC_REGNUM] = (frame_info)->frame + 4;
488 #ifdef SIG_SP_FP_OFFSET
489 /* Adjust saved SP_REGNUM for fake _sigtramp frames. */
490 if (frame_info->signal_handler_caller && frame_info->next)
491 saved_regs->regs[SP_REGNUM] = frame_info->next->frame + SIG_SP_FP_OFFSET;
492 #endif
493 }
494
495
496 #ifdef USE_PROC_FS /* Target dependent support for /proc */
497
498 #include <sys/procfs.h>
499
500 /* Prototypes for supply_gregset etc. */
501 #include "gregset.h"
502
503 /* The /proc interface divides the target machine's register set up into
504 two different sets, the general register set (gregset) and the floating
505 point register set (fpregset). For each set, there is an ioctl to get
506 the current register set and another ioctl to set the current values.
507
508 The actual structure passed through the ioctl interface is, of course,
509 naturally machine dependent, and is different for each set of registers.
510 For the m68k for example, the general register set is typically defined
511 by:
512
513 typedef int gregset_t[18];
514
515 #define R_D0 0
516 ...
517 #define R_PS 17
518
519 and the floating point set by:
520
521 typedef struct fpregset {
522 int f_pcr;
523 int f_psr;
524 int f_fpiaddr;
525 int f_fpregs[8][3]; (8 regs, 96 bits each)
526 } fpregset_t;
527
528 These routines provide the packing and unpacking of gregset_t and
529 fpregset_t formatted data.
530
531 */
532
533 /* Atari SVR4 has R_SR but not R_PS */
534
535 #if !defined (R_PS) && defined (R_SR)
536 #define R_PS R_SR
537 #endif
538
539 /* Given a pointer to a general register set in /proc format (gregset_t *),
540 unpack the register contents and supply them as gdb's idea of the current
541 register values. */
542
543 void
544 supply_gregset (gregset_t *gregsetp)
545 {
546 register int regi;
547 register greg_t *regp = (greg_t *) gregsetp;
548
549 for (regi = 0; regi < R_PC; regi++)
550 {
551 supply_register (regi, (char *) (regp + regi));
552 }
553 supply_register (PS_REGNUM, (char *) (regp + R_PS));
554 supply_register (PC_REGNUM, (char *) (regp + R_PC));
555 }
556
557 void
558 fill_gregset (gregset_t *gregsetp, int regno)
559 {
560 register int regi;
561 register greg_t *regp = (greg_t *) gregsetp;
562
563 for (regi = 0; regi < R_PC; regi++)
564 {
565 if ((regno == -1) || (regno == regi))
566 {
567 *(regp + regi) = *(int *) &registers[REGISTER_BYTE (regi)];
568 }
569 }
570 if ((regno == -1) || (regno == PS_REGNUM))
571 {
572 *(regp + R_PS) = *(int *) &registers[REGISTER_BYTE (PS_REGNUM)];
573 }
574 if ((regno == -1) || (regno == PC_REGNUM))
575 {
576 *(regp + R_PC) = *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
577 }
578 }
579
580 #if defined (FP0_REGNUM)
581
582 /* Given a pointer to a floating point register set in /proc format
583 (fpregset_t *), unpack the register contents and supply them as gdb's
584 idea of the current floating point register values. */
585
586 void
587 supply_fpregset (fpregset_t *fpregsetp)
588 {
589 register int regi;
590 char *from;
591
592 for (regi = FP0_REGNUM; regi < FPC_REGNUM; regi++)
593 {
594 from = (char *) &(fpregsetp->f_fpregs[regi - FP0_REGNUM][0]);
595 supply_register (regi, from);
596 }
597 supply_register (FPC_REGNUM, (char *) &(fpregsetp->f_pcr));
598 supply_register (FPS_REGNUM, (char *) &(fpregsetp->f_psr));
599 supply_register (FPI_REGNUM, (char *) &(fpregsetp->f_fpiaddr));
600 }
601
602 /* Given a pointer to a floating point register set in /proc format
603 (fpregset_t *), update the register specified by REGNO from gdb's idea
604 of the current floating point register set. If REGNO is -1, update
605 them all. */
606
607 void
608 fill_fpregset (fpregset_t *fpregsetp, int regno)
609 {
610 int regi;
611 char *to;
612 char *from;
613
614 for (regi = FP0_REGNUM; regi < FPC_REGNUM; regi++)
615 {
616 if ((regno == -1) || (regno == regi))
617 {
618 from = (char *) &registers[REGISTER_BYTE (regi)];
619 to = (char *) &(fpregsetp->f_fpregs[regi - FP0_REGNUM][0]);
620 memcpy (to, from, REGISTER_RAW_SIZE (regi));
621 }
622 }
623 if ((regno == -1) || (regno == FPC_REGNUM))
624 {
625 fpregsetp->f_pcr = *(int *) &registers[REGISTER_BYTE (FPC_REGNUM)];
626 }
627 if ((regno == -1) || (regno == FPS_REGNUM))
628 {
629 fpregsetp->f_psr = *(int *) &registers[REGISTER_BYTE (FPS_REGNUM)];
630 }
631 if ((regno == -1) || (regno == FPI_REGNUM))
632 {
633 fpregsetp->f_fpiaddr = *(int *) &registers[REGISTER_BYTE (FPI_REGNUM)];
634 }
635 }
636
637 #endif /* defined (FP0_REGNUM) */
638
639 #endif /* USE_PROC_FS */
640
641 /* Figure out where the longjmp will land. Slurp the args out of the stack.
642 We expect the first arg to be a pointer to the jmp_buf structure from which
643 we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
644 This routine returns true on success. */
645
646 /* NOTE: cagney/2000-11-08: For this function to be fully multi-arched
647 the macro's JB_PC and JB_ELEMENT_SIZE would need to be moved into
648 the ``struct gdbarch_tdep'' object and then set on a target ISA/ABI
649 dependant basis. */
650
651 int
652 m68k_get_longjmp_target (CORE_ADDR *pc)
653 {
654 #if defined (JB_PC) && defined (JB_ELEMENT_SIZE)
655 char *buf;
656 CORE_ADDR sp, jb_addr;
657
658 buf = alloca (TARGET_PTR_BIT / TARGET_CHAR_BIT);
659 sp = read_register (SP_REGNUM);
660
661 if (target_read_memory (sp + SP_ARG0, /* Offset of first arg on stack */
662 buf,
663 TARGET_PTR_BIT / TARGET_CHAR_BIT))
664 return 0;
665
666 jb_addr = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
667
668 if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
669 TARGET_PTR_BIT / TARGET_CHAR_BIT))
670 return 0;
671
672 *pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
673
674 return 1;
675 #else
676 internal_error (__FILE__, __LINE__,
677 "m68k_get_longjmp_target: not implemented");
678 return 0;
679 #endif
680 }
681
682 /* Immediately after a function call, return the saved pc before the frame
683 is setup. For sun3's, we check for the common case of being inside of a
684 system call, and if so, we know that Sun pushes the call # on the stack
685 prior to doing the trap. */
686
687 CORE_ADDR
688 m68k_saved_pc_after_call (struct frame_info *frame)
689 {
690 #ifdef SYSCALL_TRAP
691 int op;
692
693 op = read_memory_integer (frame->pc - SYSCALL_TRAP_OFFSET, 2);
694
695 if (op == SYSCALL_TRAP)
696 return read_memory_integer (read_register (SP_REGNUM) + 4, 4);
697 else
698 #endif /* SYSCALL_TRAP */
699 return read_memory_integer (read_register (SP_REGNUM), 4);
700 }
701
702
703 void
704 _initialize_m68k_tdep (void)
705 {
706 tm_print_insn = print_insn_m68k;
707 }
This page took 0.060283 seconds and 4 git commands to generate.