* h8300-tdep.c, tm-h8300.h: turn off some experimental features
[external/binutils.git] / gdb / h8300-tdep.c
1 /* Target-machine dependent code for Hitachi H8/300, for GDB.
2    Copyright (C) 1988, 1990, 1991 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 /*
21  Contributed by Steve Chamberlain
22                 sac@cygnus.com
23  */
24
25 #include "defs.h"
26 #include "frame.h"
27 #include "obstack.h"
28 #include "symtab.h"
29 #undef NUM_REGS
30 #define NUM_REGS 11
31
32 #define UNSIGNED_SHORT(X) ((X) & 0xffff)
33
34 /* an easy to debug H8 stack frame looks like:
35 0x6df6          push    r6
36 0x0d76          mov.w   r7,r6
37 0x6dfn          push    reg
38 0x7905 nnnn     mov.w  #n,r5    or   0x1b87  subs #2,sp
39 0x1957          sub.w  r5,sp
40
41  */
42
43 #define IS_PUSH(x) ((x & 0xff00)==0x6d00)
44 #define IS_PUSH_FP(x) (x == 0x6df6)
45 #define IS_MOVE_FP(x) (x == 0x0d76)
46 #define IS_MOV_SP_FP(x) (x == 0x0d76)
47 #define IS_SUB2_SP(x) (x==0x1b87)
48 #define IS_MOVK_R5(x) (x==0x7905)
49 #define IS_SUB_R5SP(x) (x==0x1957)
50 CORE_ADDR examine_prologue ();
51
52 void frame_find_saved_regs ();
53 CORE_ADDR 
54 h8300_skip_prologue (start_pc)
55      CORE_ADDR start_pc;
56
57 {
58   short int w;
59
60   w = read_memory_short (start_pc);
61   /* Skip past all push insns */
62   while (IS_PUSH_FP (w))
63     {
64       start_pc += 2;
65       w = read_memory_short (start_pc);
66     }
67
68   /* Skip past a move to FP */
69   if (IS_MOVE_FP (w))
70     {
71       start_pc += 2;
72       w = read_memory_short (start_pc);
73     }
74
75   /* Skip the stack adjust */
76
77   if (IS_MOVK_R5 (w))
78     {
79       start_pc += 2;
80       w = read_memory_short (start_pc);
81     }
82   if (IS_SUB_R5SP (w))
83     {
84       start_pc += 2;
85       w = read_memory_short (start_pc);
86     }
87   while (IS_SUB2_SP (w))
88     {
89       start_pc += 2;
90       w = read_memory_short (start_pc);
91     }
92
93   return start_pc;
94
95 }
96
97 int
98 print_insn (memaddr, stream)
99      CORE_ADDR memaddr;
100      FILE *stream;
101 {
102   /* Nothing is bigger than 8 bytes */
103   char data[8];
104
105   read_memory (memaddr, data, sizeof (data));
106   return print_insn_h8300 (memaddr, data, stream);
107 }
108
109 /* Given a GDB frame, determine the address of the calling function's frame.
110    This will be used to create a new GDB frame struct, and then
111    INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
112
113    For us, the frame address is its stack pointer value, so we look up
114    the function prologue to determine the caller's sp value, and return it.  */
115
116 FRAME_ADDR
117 FRAME_CHAIN (thisframe)
118      FRAME thisframe;
119 {
120
121   frame_find_saved_regs (thisframe, (struct frame_saved_regs *) 0);
122   return thisframe->fsr->regs[SP_REGNUM];
123 }
124
125 /* Put here the code to store, into a struct frame_saved_regs,
126    the addresses of the saved registers of frame described by FRAME_INFO.
127    This includes special registers such as pc and fp saved in special
128    ways in the stack frame.  sp is even more special:
129    the address we return for it IS the sp for the next frame.
130
131    We cache the result of doing this in the frame_cache_obstack, since
132    it is fairly expensive.  */
133
134 void
135 frame_find_saved_regs (fi, fsr)
136      struct frame_info *fi;
137      struct frame_saved_regs *fsr;
138 {
139   register CORE_ADDR next_addr;
140   register CORE_ADDR *saved_regs;
141   register int regnum;
142   register struct frame_saved_regs *cache_fsr;
143   extern struct obstack frame_cache_obstack;
144   CORE_ADDR ip;
145   struct symtab_and_line sal;
146   CORE_ADDR limit;
147
148   if (!fi->fsr)
149     {
150       cache_fsr = (struct frame_saved_regs *)
151         obstack_alloc (&frame_cache_obstack,
152                        sizeof (struct frame_saved_regs));
153       bzero (cache_fsr, sizeof (struct frame_saved_regs));
154
155       fi->fsr = cache_fsr;
156
157       /* Find the start and end of the function prologue.  If the PC
158          is in the function prologue, we only consider the part that
159          has executed already.  */
160
161       ip = get_pc_function_start (fi->pc);
162       sal = find_pc_line (ip, 0);
163       limit = (sal.end && sal.end < fi->pc) ? sal.end : fi->pc;
164
165       /* This will fill in fields in *fi as well as in cache_fsr.  */
166       examine_prologue (ip, limit, fi->frame, cache_fsr, fi);
167     }
168
169   if (fsr)
170     *fsr = *fi->fsr;
171 }
172
173 /* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
174    is not the address of a valid instruction, the address of the next
175    instruction beyond ADDR otherwise.  *PWORD1 receives the first word
176    of the instruction.*/
177
178 CORE_ADDR
179 NEXT_PROLOGUE_INSN (addr, lim, pword1)
180      CORE_ADDR addr;
181      CORE_ADDR lim;
182      short *pword1;
183 {
184   if (addr < lim + 8)
185     {
186       read_memory (addr, pword1, sizeof (*pword1));
187       SWAP_TARGET_AND_HOST (pword1, sizeof (short));
188
189       return addr + 2;
190     }
191   return 0;
192 }
193
194 /* Examine the prologue of a function.  `ip' points to the first instruction.
195    `limit' is the limit of the prologue (e.g. the addr of the first
196    linenumber, or perhaps the program counter if we're stepping through).
197    `frame_sp' is the stack pointer value in use in this frame.
198    `fsr' is a pointer to a frame_saved_regs structure into which we put
199    info about the registers saved by this frame.
200    `fi' is a struct frame_info pointer; we fill in various fields in it
201    to reflect the offsets of the arg pointer and the locals pointer.  */
202
203 static CORE_ADDR
204 examine_prologue (ip, limit, after_prolog_fp, fsr, fi)
205      register CORE_ADDR ip;
206      register CORE_ADDR limit;
207      FRAME_ADDR after_prolog_fp;
208      struct frame_saved_regs *fsr;
209      struct frame_info *fi;
210 {
211   register CORE_ADDR next_ip;
212   int r;
213   int i;
214   int have_fp = 0;
215
216   register int src;
217   register struct pic_prologue_code *pcode;
218   INSN_WORD insn_word;
219   int size, offset;
220   unsigned int reg_save_depth = 2;      /* Number of things pushed onto
221                                       stack, starts at 2, 'cause the
222                                       PC is already there */
223
224   unsigned int auto_depth = 0;  /* Number of bytes of autos */
225
226   char in_frame[8];     /* One for each reg */
227
228   memset (in_frame, 1, 8);
229   for (r = 0; r < 8; r++)
230     {
231       fsr->regs[r] = 0;
232     }
233   if (after_prolog_fp == 0)
234     {
235       after_prolog_fp = read_register (SP_REGNUM);
236     }
237   if (ip == 0 || ip & ~0xffff)
238     return 0;
239
240   next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
241
242   /* Skip over any fp push instructions */
243   fsr->regs[6] = after_prolog_fp;
244   while (next_ip && IS_PUSH_FP (insn_word))
245     {
246       ip = next_ip;
247
248       in_frame[insn_word & 0x7] = reg_save_depth;
249       next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
250       reg_save_depth += 2;
251     }
252
253   /* Is this a move into the fp */
254   if (next_ip && IS_MOV_SP_FP (insn_word))
255     {
256       ip = next_ip;
257       next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
258       have_fp = 1;
259     }
260
261   /* Skip over any stack adjustment, happens either with a number of
262      sub#2,sp or a mov #x,r5 sub r5,sp */
263
264   if (next_ip && IS_SUB2_SP (insn_word))
265     {
266       while (next_ip && IS_SUB2_SP (insn_word))
267         {
268           auto_depth += 2;
269           ip = next_ip;
270           next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
271         }
272     }
273   else
274     {
275       if (next_ip && IS_MOVK_R5 (insn_word))
276         {
277           ip = next_ip;
278           next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
279           auto_depth += insn_word;
280
281           next_ip = NEXT_PROLOGUE_INSN (next_ip, limit, &insn_word);
282           auto_depth += insn_word;
283
284         }
285     }
286   /* Work out which regs are stored where */
287   while (next_ip && IS_PUSH (insn_word))
288     {
289       ip = next_ip;
290       next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
291       fsr->regs[r] = after_prolog_fp + auto_depth;
292       auto_depth += 2;
293     }
294
295   /* The args are always reffed based from the stack pointer */
296   fi->args_pointer = after_prolog_fp;
297   /* Locals are always reffed based from the fp */
298   fi->locals_pointer = after_prolog_fp;
299   /* The PC is at a known place */
300   fi->from_pc = read_memory_short (after_prolog_fp + 2);
301
302   /* Rememeber any others too */
303   in_frame[PC_REGNUM] = 0;
304
305   if (have_fp)
306     /* We keep the old FP in the SP spot */
307     fsr->regs[SP_REGNUM] = (read_memory_short (fsr->regs[6]));
308   else
309     fsr->regs[SP_REGNUM] = after_prolog_fp + auto_depth;
310
311   return (ip);
312 }
313
314 void
315 init_extra_frame_info (fromleaf, fi)
316      int fromleaf;
317      struct frame_info *fi;
318 {
319   fi->fsr = 0;                  /* Not yet allocated */
320   fi->args_pointer = 0;         /* Unknown */
321   fi->locals_pointer = 0;       /* Unknown */
322   fi->from_pc = 0;
323
324 }
325
326 /* Return the saved PC from this frame.
327
328    If the frame has a memory copy of SRP_REGNUM, use that.  If not,
329    just use the register SRP_REGNUM itself.  */
330
331 CORE_ADDR
332 frame_saved_pc (frame)
333      FRAME frame;
334
335 {
336   return frame->from_pc;
337 }
338
339 CORE_ADDR
340 frame_locals_address (fi)
341      struct frame_info *fi;
342 {
343   if (!fi->locals_pointer)
344     {
345       struct frame_saved_regs ignore;
346
347       get_frame_saved_regs (fi, &ignore);
348
349     }
350   return fi->locals_pointer;
351 }
352
353 /* Return the address of the argument block for the frame
354    described by FI.  Returns 0 if the address is unknown.  */
355
356 CORE_ADDR
357 frame_args_address (fi)
358      struct frame_info *fi;
359 {
360   if (!fi->args_pointer)
361     {
362       struct frame_saved_regs ignore;
363
364       get_frame_saved_regs (fi, &ignore);
365
366     }
367
368   return fi->args_pointer;
369 }
370
371 void 
372 h8300_pop_frame ()
373 {
374   unsigned regnum;
375   struct frame_saved_regs fsr;
376   struct frame_info *fi;
377
378   FRAME frame = get_current_frame ();
379
380   fi = get_frame_info (frame);
381   get_frame_saved_regs (fi, &fsr);
382
383   for (regnum = 0; regnum < 8; regnum++)
384     {
385       if (fsr.regs[regnum])
386         {
387           write_register (regnum, read_memory_short (fsr.regs[regnum]));
388         }
389
390       flush_cached_frames ();
391       set_current_frame (create_new_frame (read_register (FP_REGNUM),
392                                            read_pc ()));
393
394     }
395
396 }
397
398 void
399 print_register_hook (regno)
400 {
401   if (regno == 8)
402     {
403       /* CCR register */
404
405       int C, Z, N, V;
406       unsigned char b[2];
407       unsigned char l;
408
409       read_relative_register_raw_bytes (regno, b);
410       l = b[1];
411       printf ("\t");
412       printf ("I-%d - ", (l & 0x80) != 0);
413       printf ("H-%d - ", (l & 0x20) != 0);
414       N = (l & 0x8) != 0;
415       Z = (l & 0x4) != 0;
416       V = (l & 0x2) != 0;
417       C = (l & 0x1) != 0;
418       printf ("N-%d ", N);
419       printf ("Z-%d ", Z);
420       printf ("V-%d ", V);
421       printf ("C-%d ", C);
422       if ((C | Z) == 0)
423         printf ("u> ");
424       if ((C | Z) == 1)
425         printf ("u<= ");
426       if ((C == 0))
427         printf ("u>= ");
428       if (C == 1)
429         printf ("u< ");
430       if (Z == 0)
431         printf ("!= ");
432       if (Z == 1)
433         printf ("== ");
434       if ((N ^ V) == 0)
435         printf (">= ");
436       if ((N ^ V) == 1)
437         printf ("< ");
438       if ((Z | (N ^ V)) == 0)
439         printf ("> ");
440       if ((Z | (N ^ V)) == 1)
441         printf ("<= ");
442     }
443 }