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