]> Git Repo - binutils.git/blob - gdb/h8500-tdep.c
* h8500-tdep.c: General linting and cleanup.
[binutils.git] / gdb / h8500-tdep.c
1 /* Target-dependent code for Hitachi H8/500, for GDB.
2    Copyright 1993, 1994, 1995 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                 [email protected]
23  */
24
25 #include "defs.h"
26 #include "frame.h"
27 #include "obstack.h"
28 #include "symtab.h"
29 #include "gdbtypes.h"
30 #include "gdbcmd.h"
31 #include "value.h"
32 #include "dis-asm.h"
33 #include "gdbcore.h"
34
35 #define UNSIGNED_SHORT(X) ((X) & 0xffff)
36
37 static int code_size = 2;
38
39 static int data_size = 2;
40
41 /* Shape of an H8/500 frame :
42
43    arg-n
44    ..
45    arg-2
46    arg-1
47    return address <2 or 4 bytes>
48    old fp         <2 bytes>
49    auto-n
50    ..
51    auto-1
52    saved registers
53
54 */
55
56 /* an easy to debug H8 stack frame looks like:
57 0x6df6          push    r6
58 0x0d76          mov.w   r7,r6
59 0x6dfn          push    reg
60 0x7905 nnnn     mov.w  #n,r5    or   0x1b87  subs #2,sp
61 0x1957          sub.w  r5,sp
62
63  */
64
65 #define IS_PUSH(x) (((x) & 0xff00)==0x6d00)
66 #define IS_LINK_8(x) ((x) == 0x17)
67 #define IS_LINK_16(x) ((x) == 0x1f)
68 #define IS_MOVE_FP(x) ((x) == 0x0d76)
69 #define IS_MOV_SP_FP(x) ((x) == 0x0d76)
70 #define IS_SUB2_SP(x) ((x) == 0x1b87)
71 #define IS_MOVK_R5(x) ((x) == 0x7905)
72 #define IS_SUB_R5SP(x) ((x) == 0x1957)
73
74 #define LINK_8 0x17
75 #define LINK_16 0x1f
76
77 int minimum_mode = 1;
78
79 CORE_ADDR
80 h8500_skip_prologue (start_pc)
81      CORE_ADDR start_pc;
82 {
83   short int w;
84
85   w = read_memory_integer (start_pc, 1);
86   if (w == LINK_8)
87     {
88       start_pc += 2;
89       w = read_memory_integer (start_pc, 1);
90     }
91
92   if (w == LINK_16)
93     {
94       start_pc += 3;
95       w = read_memory_integer (start_pc, 2);
96     }
97
98   return start_pc;
99 }
100
101 /* Given a GDB frame, determine the address of the calling function's frame.
102    This will be used to create a new GDB frame struct, and then
103    INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
104
105    For us, the frame address is its stack pointer value, so we look up
106    the function prologue to determine the caller's sp value, and return it.  */
107
108 CORE_ADDR
109 h8500_frame_chain (thisframe)
110      struct frame_info *thisframe;
111 {
112   if (!inside_entry_file (thisframe->pc))
113     return (read_memory_integer (FRAME_FP (thisframe), PTR_SIZE));
114   else
115     return 0;
116 }
117
118 /* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
119    is not the address of a valid instruction, the address of the next
120    instruction beyond ADDR otherwise.  *PWORD1 receives the first word
121    of the instruction.*/
122
123 CORE_ADDR
124 NEXT_PROLOGUE_INSN (addr, lim, pword1)
125      CORE_ADDR addr;
126      CORE_ADDR lim;
127      char *pword1;
128 {
129   if (addr < lim + 8)
130     {
131       read_memory (addr, pword1, 1);
132       read_memory (addr, pword1 + 1, 1);
133       return 1;
134     }
135   return 0;
136 }
137
138 /* Examine the prologue of a function.  `ip' points to the first
139    instruction.  `limit' is the limit of the prologue (e.g. the addr
140    of the first linenumber, or perhaps the program counter if we're
141    stepping through).  `frame_sp' is the stack pointer value in use in
142    this frame.  `fsr' is a pointer to a frame_saved_regs structure
143    into which we put info about the registers saved by this frame.
144    `fi' is a struct frame_info pointer; we fill in various fields in
145    it to reflect the offsets of the arg pointer and the locals
146    pointer.  */
147
148 /* Return the saved PC from this frame. */
149
150 CORE_ADDR
151 frame_saved_pc (frame)
152      struct frame_info *frame;
153 {
154   return read_memory_integer (FRAME_FP (frame) + 2, PTR_SIZE);
155 }
156
157 void 
158 h8500_pop_frame ()
159 {
160   unsigned regnum;
161   struct frame_saved_regs fsr;
162   struct frame_info *frame = get_current_frame ();
163
164   get_frame_saved_regs (frame, &fsr);
165
166   for (regnum = 0; regnum < 8; regnum++)
167     {
168       if (fsr.regs[regnum])
169         write_register (regnum, read_memory_short (fsr.regs[regnum]));
170
171       flush_cached_frames ();
172     }
173 }
174
175 void
176 print_register_hook (regno)
177      int regno;
178 {
179   if (regno == CCR_REGNUM)
180     {
181       /* CCR register */
182
183       int C, Z, N, V;
184       unsigned char b[2];
185       unsigned char l;
186
187       read_relative_register_raw_bytes (regno, b);
188       l = b[1];
189       printf_unfiltered ("\t");
190       printf_unfiltered ("I-%d - ", (l & 0x80) != 0);
191       N = (l & 0x8) != 0;
192       Z = (l & 0x4) != 0;
193       V = (l & 0x2) != 0;
194       C = (l & 0x1) != 0;
195       printf_unfiltered ("N-%d ", N);
196       printf_unfiltered ("Z-%d ", Z);
197       printf_unfiltered ("V-%d ", V);
198       printf_unfiltered ("C-%d ", C);
199       if ((C | Z) == 0)
200         printf_unfiltered ("u> ");
201       if ((C | Z) == 1)
202         printf_unfiltered ("u<= ");
203       if ((C == 0))
204         printf_unfiltered ("u>= ");
205       if (C == 1)
206         printf_unfiltered ("u< ");
207       if (Z == 0)
208         printf_unfiltered ("!= ");
209       if (Z == 1)
210         printf_unfiltered ("== ");
211       if ((N ^ V) == 0)
212         printf_unfiltered (">= ");
213       if ((N ^ V) == 1)
214         printf_unfiltered ("< ");
215       if ((Z | (N ^ V)) == 0)
216         printf_unfiltered ("> ");
217       if ((Z | (N ^ V)) == 1)
218         printf_unfiltered ("<= ");
219     }
220 }
221
222 int
223 h8500_register_size (regno)
224      int regno;
225 {
226   switch (regno)
227     {
228     case SEG_C_REGNUM:
229     case SEG_D_REGNUM:
230     case SEG_E_REGNUM:
231     case SEG_T_REGNUM:
232       return 1;
233     case R0_REGNUM:
234     case R1_REGNUM:
235     case R2_REGNUM:
236     case R3_REGNUM:
237     case R4_REGNUM:
238     case R5_REGNUM:
239     case R6_REGNUM:
240     case R7_REGNUM:
241     case CCR_REGNUM:
242       return 2;
243
244     case PR0_REGNUM:
245     case PR1_REGNUM:
246     case PR2_REGNUM:
247     case PR3_REGNUM:
248     case PR4_REGNUM:
249     case PR5_REGNUM:
250     case PR6_REGNUM:
251     case PR7_REGNUM:
252     case PC_REGNUM:
253       return 4;
254     default:
255       abort ();
256     }
257 }
258
259 struct type *
260 h8500_register_virtual_type (regno)
261      int regno;
262 {
263   switch (regno)
264     {
265     case SEG_C_REGNUM:
266     case SEG_E_REGNUM:
267     case SEG_D_REGNUM:
268     case SEG_T_REGNUM:
269       return builtin_type_unsigned_char;
270     case R0_REGNUM:
271     case R1_REGNUM:
272     case R2_REGNUM:
273     case R3_REGNUM:
274     case R4_REGNUM:
275     case R5_REGNUM:
276     case R6_REGNUM:
277     case R7_REGNUM:
278     case CCR_REGNUM:
279       return builtin_type_unsigned_short;
280     case PR0_REGNUM:
281     case PR1_REGNUM:
282     case PR2_REGNUM:
283     case PR3_REGNUM:
284     case PR4_REGNUM:
285     case PR5_REGNUM:
286     case PR6_REGNUM:
287     case PR7_REGNUM:
288     case PC_REGNUM:
289       return builtin_type_unsigned_long;
290     default:
291       abort ();
292     }
293 }
294
295 /* Put here the code to store, into a struct frame_saved_regs,
296    the addresses of the saved registers of frame described by FRAME_INFO.
297    This includes special registers such as pc and fp saved in special
298    ways in the stack frame.  sp is even more special:
299    the address we return for it IS the sp for the next frame.  */
300
301 void
302 frame_find_saved_regs (frame_info, frame_saved_regs)
303      struct frame_info *frame_info;
304      struct frame_saved_regs *frame_saved_regs;
305 {
306   register int regnum;
307   register int regmask;
308   register CORE_ADDR next_addr;
309   register CORE_ADDR pc;
310   unsigned char thebyte;
311
312   memset (frame_saved_regs, '\0', sizeof *frame_saved_regs);
313
314   if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 4
315       && (frame_info)->pc <= (frame_info)->frame)
316     {
317       next_addr = (frame_info)->frame;
318       pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 4;
319     }
320   else
321     {
322       pc = get_pc_function_start ((frame_info)->pc);
323       /* Verify we have a link a6 instruction next;
324          if not we lose.  If we win, find the address above the saved
325          regs using the amount of storage from the link instruction.
326          */
327
328       thebyte = read_memory_integer (pc, 1);
329       if (0x1f == thebyte)
330         next_addr = (frame_info)->frame + read_memory_integer (pc += 1, 2), pc += 2;
331       else if (0x17 == thebyte)
332         next_addr = (frame_info)->frame + read_memory_integer (pc += 1, 1), pc += 1;
333       else
334         goto lose;
335 #if 0
336       /* FIXME steve */
337       /* If have an add:g.waddal #-n, sp next, adjust next_addr.  */
338       if ((0x0c0177777 & read_memory_integer (pc, 2)) == 0157774)
339         next_addr += read_memory_integer (pc += 2, 4), pc += 4;
340 #endif
341     }
342
343   thebyte = read_memory_integer (pc, 1);
344   if (thebyte == 0x12)
345     {
346       /* Got stm */
347       pc++;
348       regmask = read_memory_integer (pc, 1);
349       pc++;
350       for (regnum = 0; regnum < 8; regnum++, regmask >>= 1)
351         {
352           if (regmask & 1)
353             {
354               (frame_saved_regs)->regs[regnum] = (next_addr += 2) - 2;
355             }
356         }
357       thebyte = read_memory_integer (pc, 1);
358     }
359   /* Maybe got a load of pushes */
360   while (thebyte == 0xbf)
361     {
362       pc++;
363       regnum = read_memory_integer (pc, 1) & 0x7;
364       pc++;
365       (frame_saved_regs)->regs[regnum] = (next_addr += 2) - 2;
366       thebyte = read_memory_integer (pc, 1);
367     }
368
369 lose:;
370
371   /* Remember the address of the frame pointer */
372   (frame_saved_regs)->regs[FP_REGNUM] = (frame_info)->frame;
373
374   /* This is where the old sp is hidden */
375   (frame_saved_regs)->regs[SP_REGNUM] = (frame_info)->frame;
376
377   /* And the PC - remember the pushed FP is always two bytes long */
378   (frame_saved_regs)->regs[PC_REGNUM] = (frame_info)->frame + 2;
379 }
380
381 CORE_ADDR
382 saved_pc_after_call ()
383 {
384   int x;
385   int a = read_register (SP_REGNUM);
386
387   x = read_memory_integer (a, code_size);
388   if (code_size == 2)
389     {
390       /* Stick current code segement onto top */
391       x &= 0xffff;
392       x |= read_register (SEG_C_REGNUM) << 16;
393     }
394   x &= 0xffffff;
395   return x;
396 }
397
398 #if 0  /* never called */
399 /* Nonzero if instruction at PC is a return instruction.  */
400
401 int
402 about_to_return (pc)
403      CORE_ADDR pc;
404 {
405   int b1 = read_memory_integer (pc, 1);
406
407   switch (b1)
408     {
409     case 0x14:                  /* rtd #8 */
410     case 0x1c:                  /* rtd #16 */
411     case 0x19:                  /* rts */
412     case 0x1a:                  /* rte */
413       return 1;
414     case 0x11:
415       {
416         int b2 = read_memory_integer (pc + 1, 1);
417         switch (b2)
418           {
419           case 0x18:            /* prts */
420           case 0x14:            /* prtd #8 */
421           case 0x16:            /* prtd #16 */
422             return 1;
423           }
424       }
425     }
426   return 0;
427 }
428 #endif
429
430 void
431 h8500_set_pointer_size (newsize)
432      int newsize;
433 {
434   static int oldsize = 0;
435
436   if (oldsize != newsize)
437     {
438       printf_unfiltered ("pointer size set to %d bits\n", newsize);
439       oldsize = newsize;
440       if (newsize == 32)
441         {
442           minimum_mode = 0;
443         }
444       else
445         {
446           minimum_mode = 1;
447         }
448       _initialize_gdbtypes ();
449     }
450 }
451
452 static void
453 big_command ()
454 {
455   h8500_set_pointer_size (32);
456   code_size = 4;
457   data_size = 4;
458 }
459
460 static void
461 medium_command ()
462 {
463   h8500_set_pointer_size (32);
464   code_size = 4;
465   data_size = 2;
466 }
467
468 static void
469 compact_command ()
470 {
471   h8500_set_pointer_size (32);
472   code_size = 2;
473   data_size = 4;
474 }
475
476 static void
477 small_command ()
478 {
479   h8500_set_pointer_size (16);
480   code_size = 2;
481   data_size = 2;
482 }
483
484 static struct cmd_list_element *setmemorylist;
485
486 static void
487 set_memory (args, from_tty)
488      char *args;
489      int from_tty;
490 {
491   printf_unfiltered ("\"set memory\" must be followed by the name of a memory subcommand.\n");
492   help_list (setmemorylist, "set memory ", -1, gdb_stdout);
493 }
494
495 /* See if variable name is ppc or pr[0-7] */
496
497 int
498 h8500_is_trapped_internalvar (name)
499      char *name;
500 {
501   if (name[0] != 'p')
502     return 0;
503
504   if (strcmp (name + 1, "pc") == 0)
505     return 1;
506
507   if (name[1] == 'r'
508       && name[2] >= '0'
509       && name[2] <= '7'
510       && name[3] == '\000')
511     return 1;
512   else
513     return 0;
514 }
515
516 value_ptr
517 h8500_value_of_trapped_internalvar (var)
518      struct internalvar *var;
519 {
520   LONGEST regval;
521   unsigned char regbuf[4];
522   int page_regnum, regnum;
523
524   regnum = var->name[2] == 'c' ? PC_REGNUM : var->name[2] - '0';
525
526   switch (var->name[2])
527     {
528     case 'c':
529       page_regnum = SEG_C_REGNUM;
530       break;
531     case '0':
532     case '1':
533     case '2':
534     case '3':
535       page_regnum = SEG_D_REGNUM;
536       break;
537     case '4':
538     case '5':
539       page_regnum = SEG_E_REGNUM;
540       break;
541     case '6':
542     case '7':
543       page_regnum = SEG_T_REGNUM;
544       break;
545     }
546
547   get_saved_register (regbuf, NULL, NULL, selected_frame, page_regnum, NULL);
548   regval = regbuf[0] << 16;
549
550   get_saved_register (regbuf, NULL, NULL, selected_frame, regnum, NULL);
551   regval |= regbuf[0] << 8 | regbuf[1]; /* XXX host/target byte order */
552
553   free (var->value);            /* Free up old value */
554
555   var->value = value_from_longest (builtin_type_unsigned_long, regval);
556   release_value (var->value);   /* Unchain new value */
557
558   VALUE_LVAL (var->value) = lval_internalvar;
559   VALUE_INTERNALVAR (var->value) = var;
560   return var->value;
561 }
562
563 void
564 h8500_set_trapped_internalvar (var, newval, bitpos, bitsize, offset)
565      struct internalvar *var;
566      int offset, bitpos, bitsize;
567      value_ptr newval;
568 {
569   char *page_regnum, *regnum;
570   char expression[100];
571   unsigned new_regval;
572   struct type *type;
573   enum type_code newval_type_code;
574
575   type = VALUE_TYPE (newval);
576   newval_type_code = TYPE_CODE (type);
577
578   if ((newval_type_code != TYPE_CODE_INT
579        && newval_type_code != TYPE_CODE_PTR)
580       || TYPE_LENGTH (type) != sizeof (new_regval))
581     error ("Illegal type (%s) for assignment to $%s\n",
582            TYPE_NAME (type), var->name);
583
584   new_regval = *(long *) VALUE_CONTENTS_RAW (newval);
585
586   regnum = var->name + 1;
587
588   switch (var->name[2])
589     {
590     case 'c':
591       page_regnum = "cp";
592       break;
593     case '0':
594     case '1':
595     case '2':
596     case '3':
597       page_regnum = "dp";
598       break;
599     case '4':
600     case '5':
601       page_regnum = "ep";
602       break;
603     case '6':
604     case '7':
605       page_regnum = "tp";
606       break;
607     }
608
609   sprintf (expression, "$%s=%d", page_regnum, new_regval >> 16);
610   parse_and_eval (expression);
611
612   sprintf (expression, "$%s=%d", regnum, new_regval & 0xffff);
613   parse_and_eval (expression);
614 }
615
616 CORE_ADDR
617 h8500_read_sp ()
618 {
619   return read_register (PR7_REGNUM);
620 }
621
622 void
623 h8500_write_sp (v)
624      CORE_ADDR v;
625 {
626   write_register (PR7_REGNUM, v);
627 }
628
629 CORE_ADDR
630 h8500_read_pc (pid)
631      int pid;
632 {
633   return read_register (PC_REGNUM);
634 }
635
636 void
637 h8500_write_pc (v, pid)
638      CORE_ADDR v;
639      int pid;
640 {
641   write_register (PC_REGNUM, v);
642 }
643
644 CORE_ADDR
645 h8500_read_fp ()
646 {
647   return read_register (PR6_REGNUM);
648 }
649
650 void
651 h8500_write_fp (v)
652      CORE_ADDR v;
653 {
654   write_register (PR6_REGNUM, v);
655 }
656
657 void
658 _initialize_h8500_tdep ()
659 {
660   tm_print_insn = print_insn_h8500;
661
662   add_prefix_cmd ("memory", no_class, set_memory,
663                   "set the memory model", &setmemorylist, "set memory ", 0,
664                   &setlist);
665
666   add_cmd ("small", class_support, small_command,
667            "Set small memory model. (16 bit code, 16 bit data)", &setmemorylist);
668
669   add_cmd ("big", class_support, big_command,
670            "Set big memory model. (32 bit code, 32 bit data)", &setmemorylist);
671
672   add_cmd ("medium", class_support, medium_command,
673            "Set medium memory model. (32 bit code, 16 bit data)", &setmemorylist);
674
675   add_cmd ("compact", class_support, compact_command,
676            "Set compact memory model. (16 bit code, 32 bit data)", &setmemorylist);
677
678 }
This page took 0.065257 seconds and 4 git commands to generate.