]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/m68k-tdep.c
Initial creation of sourceware repository
[thirdparty/binutils-gdb.git] / gdb / m68k-tdep.c
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 \f
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 \f
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 }