* configure.in (AC_PREREQ): autoconf 2.5 or higher.
[deliverable/binutils-gdb.git] / gdb / h8300-tdep.c
CommitLineData
1f46923f
SC
1/* Target-machine dependent code for Hitachi H8/300, for GDB.
2 Copyright (C) 1988, 1990, 1991 Free Software Foundation, Inc.
3
4This file is part of GDB.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
6c9638b4 18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
1f46923f 19
ec25d19b 20/*
1f46923f 21 Contributed by Steve Chamberlain
ec25d19b 22 sac@cygnus.com
1f46923f
SC
23 */
24
400943fb 25#include "defs.h"
1f46923f
SC
26#include "frame.h"
27#include "obstack.h"
28#include "symtab.h"
7f4c8595 29#include "dis-asm.h"
a3059251
SC
30#include "gdbcmd.h"
31#include "gdbtypes.h"
f9fedc48
MA
32#include "gdbcore.h"
33#include "gdb_string.h"
34#include "value.h"
35
a3059251 36
256b4f37
SC
37#undef NUM_REGS
38#define NUM_REGS 11
39
1f46923f 40#define UNSIGNED_SHORT(X) ((X) & 0xffff)
400943fb
SC
41
42/* an easy to debug H8 stack frame looks like:
ec25d19b
SC
430x6df6 push r6
440x0d76 mov.w r7,r6
450x6dfn push reg
460x7905 nnnn mov.w #n,r5 or 0x1b87 subs #2,sp
470x1957 sub.w r5,sp
400943fb
SC
48
49 */
1f46923f 50
31778db0 51#define IS_PUSH(x) ((x & 0xfff0)==0x6df0)
ec25d19b 52#define IS_PUSH_FP(x) (x == 0x6df6)
31778db0
JL
53#define IS_MOVE_FP(x) (x == 0x0d76 || x == 0x0ff6)
54#define IS_MOV_SP_FP(x) (x == 0x0d76 || x == 0x0ff6)
1f46923f 55#define IS_SUB2_SP(x) (x==0x1b87)
31778db0
JL
56#define IS_SUB4_SP(x) (x==0x1b97)
57#define IS_SUBL_SP(x) (x==0x7a37)
1f46923f 58#define IS_MOVK_R5(x) (x==0x7905)
ec25d19b 59#define IS_SUB_R5SP(x) (x==0x1957)
1ca9e7c9 60
f9fedc48
MA
61/* Local function declarations. */
62
1ca9e7c9 63static CORE_ADDR examine_prologue ();
f9fedc48 64static void set_machine_hook PARAMS ((char *filename));
1f46923f 65
ec25d19b
SC
66void frame_find_saved_regs ();
67CORE_ADDR
68h8300_skip_prologue (start_pc)
69 CORE_ADDR start_pc;
0a8f9d31 70{
ec25d19b 71 short int w;
31778db0 72 int adjust = 0;
1f46923f 73
df14b38b 74 w = read_memory_unsigned_integer (start_pc, 2);
31778db0
JL
75 if (w == 0x0100)
76 {
77 w = read_memory_unsigned_integer (start_pc + 2, 2);
78 adjust = 2;
79 }
80
400943fb 81 /* Skip past all push insns */
ec25d19b
SC
82 while (IS_PUSH_FP (w))
83 {
31778db0 84 start_pc += 2 + adjust;
df14b38b 85 w = read_memory_unsigned_integer (start_pc, 2);
ec25d19b 86 }
0a8f9d31 87
1f46923f 88 /* Skip past a move to FP */
ec25d19b
SC
89 if (IS_MOVE_FP (w))
90 {
91 start_pc += 2;
df14b38b 92 w = read_memory_unsigned_integer (start_pc, 2);
1f46923f
SC
93 }
94
ec25d19b 95 /* Skip the stack adjust */
0a8f9d31 96
ec25d19b
SC
97 if (IS_MOVK_R5 (w))
98 {
99 start_pc += 2;
df14b38b 100 w = read_memory_unsigned_integer (start_pc, 2);
ec25d19b
SC
101 }
102 if (IS_SUB_R5SP (w))
103 {
104 start_pc += 2;
df14b38b 105 w = read_memory_unsigned_integer (start_pc, 2);
ec25d19b 106 }
31778db0 107 while (IS_SUB2_SP (w) || IS_SUB4_SP (w))
ec25d19b
SC
108 {
109 start_pc += 2;
df14b38b 110 w = read_memory_unsigned_integer (start_pc, 2);
ec25d19b
SC
111 }
112
31778db0
JL
113 if (IS_SUBL_SP (w))
114 start_pc += 6;
115
ec25d19b 116 return start_pc;
ec25d19b 117}
1f46923f 118
400943fb 119int
18b46e7c
SS
120gdb_print_insn_h8300 (memaddr, info)
121 bfd_vma memaddr;
122 disassemble_info *info;
0a8f9d31 123{
d15396df
JL
124/* start-sanitize-h8s */
125 if (h8300smode)
126 return print_insn_h8300s (memaddr, info);
127 else
128/* end-sanitize-h8s */
129 if (h8300hmode)
5076ecd0 130 return print_insn_h8300h (memaddr, info);
d0414a11 131 else
5076ecd0 132 return print_insn_h8300 (memaddr, info);
0a8f9d31 133}
ec25d19b 134
1f46923f
SC
135/* Given a GDB frame, determine the address of the calling function's frame.
136 This will be used to create a new GDB frame struct, and then
137 INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
138
139 For us, the frame address is its stack pointer value, so we look up
140 the function prologue to determine the caller's sp value, and return it. */
141
669caa9c
SS
142CORE_ADDR
143h8300_frame_chain (thisframe)
144 struct frame_info *thisframe;
1f46923f 145{
1f46923f 146 frame_find_saved_regs (thisframe, (struct frame_saved_regs *) 0);
ec25d19b 147 return thisframe->fsr->regs[SP_REGNUM];
1f46923f
SC
148}
149
1f46923f
SC
150/* Put here the code to store, into a struct frame_saved_regs,
151 the addresses of the saved registers of frame described by FRAME_INFO.
152 This includes special registers such as pc and fp saved in special
153 ways in the stack frame. sp is even more special:
154 the address we return for it IS the sp for the next frame.
155
156 We cache the result of doing this in the frame_cache_obstack, since
157 it is fairly expensive. */
158
159void
160frame_find_saved_regs (fi, fsr)
161 struct frame_info *fi;
162 struct frame_saved_regs *fsr;
163{
1f46923f
SC
164 register struct frame_saved_regs *cache_fsr;
165 extern struct obstack frame_cache_obstack;
166 CORE_ADDR ip;
167 struct symtab_and_line sal;
168 CORE_ADDR limit;
169
170 if (!fi->fsr)
171 {
172 cache_fsr = (struct frame_saved_regs *)
ec25d19b
SC
173 obstack_alloc (&frame_cache_obstack,
174 sizeof (struct frame_saved_regs));
4ed97c9a 175 memset (cache_fsr, '\0', sizeof (struct frame_saved_regs));
ec25d19b 176
1f46923f
SC
177 fi->fsr = cache_fsr;
178
179 /* Find the start and end of the function prologue. If the PC
180 is in the function prologue, we only consider the part that
181 has executed already. */
ec25d19b 182
1f46923f
SC
183 ip = get_pc_function_start (fi->pc);
184 sal = find_pc_line (ip, 0);
ec25d19b 185 limit = (sal.end && sal.end < fi->pc) ? sal.end : fi->pc;
1f46923f
SC
186
187 /* This will fill in fields in *fi as well as in cache_fsr. */
188 examine_prologue (ip, limit, fi->frame, cache_fsr, fi);
189 }
190
191 if (fsr)
192 *fsr = *fi->fsr;
193}
1f46923f
SC
194
195/* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
196 is not the address of a valid instruction, the address of the next
197 instruction beyond ADDR otherwise. *PWORD1 receives the first word
198 of the instruction.*/
199
1f46923f 200CORE_ADDR
ec25d19b
SC
201NEXT_PROLOGUE_INSN (addr, lim, pword1)
202 CORE_ADDR addr;
203 CORE_ADDR lim;
58e49e21 204 INSN_WORD *pword1;
1f46923f 205{
34df79fc 206 char buf[2];
ec25d19b
SC
207 if (addr < lim + 8)
208 {
34df79fc
JK
209 read_memory (addr, buf, 2);
210 *pword1 = extract_signed_integer (buf, 2);
1f46923f 211
ec25d19b
SC
212 return addr + 2;
213 }
1f46923f 214 return 0;
1f46923f
SC
215}
216
217/* Examine the prologue of a function. `ip' points to the first instruction.
ec25d19b 218 `limit' is the limit of the prologue (e.g. the addr of the first
1f46923f 219 linenumber, or perhaps the program counter if we're stepping through).
ec25d19b 220 `frame_sp' is the stack pointer value in use in this frame.
1f46923f 221 `fsr' is a pointer to a frame_saved_regs structure into which we put
ec25d19b 222 info about the registers saved by this frame.
1f46923f
SC
223 `fi' is a struct frame_info pointer; we fill in various fields in it
224 to reflect the offsets of the arg pointer and the locals pointer. */
225
1f46923f
SC
226static CORE_ADDR
227examine_prologue (ip, limit, after_prolog_fp, fsr, fi)
228 register CORE_ADDR ip;
229 register CORE_ADDR limit;
669caa9c 230 CORE_ADDR after_prolog_fp;
1f46923f
SC
231 struct frame_saved_regs *fsr;
232 struct frame_info *fi;
233{
234 register CORE_ADDR next_ip;
235 int r;
1f46923f 236 int have_fp = 0;
1f46923f 237 INSN_WORD insn_word;
d0414a11
DE
238 /* Number of things pushed onto stack, starts at 2/4, 'cause the
239 PC is already there */
a3059251 240 unsigned int reg_save_depth = h8300hmode ? 4 : 2;
1f46923f
SC
241
242 unsigned int auto_depth = 0; /* Number of bytes of autos */
1f46923f 243
ddf30c37 244 char in_frame[11]; /* One for each reg */
1f46923f 245
31778db0
JL
246 int adjust = 0;
247
ddf30c37 248 memset (in_frame, 1, 11);
256b4f37 249 for (r = 0; r < 8; r++)
ec25d19b
SC
250 {
251 fsr->regs[r] = 0;
252 }
253 if (after_prolog_fp == 0)
254 {
255 after_prolog_fp = read_register (SP_REGNUM);
256 }
31778db0 257 if (ip == 0 || ip & (h8300hmode ? ~0xffffff : ~0xffff))
ec25d19b 258 return 0;
1f46923f 259
ec25d19b 260 next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
1f46923f 261
31778db0
JL
262 if (insn_word == 0x0100)
263 {
264 insn_word = read_memory_unsigned_integer (ip + 2, 2);
265 adjust = 2;
266 }
267
ec25d19b
SC
268 /* Skip over any fp push instructions */
269 fsr->regs[6] = after_prolog_fp;
270 while (next_ip && IS_PUSH_FP (insn_word))
271 {
31778db0 272 ip = next_ip + adjust;
1f46923f 273
ec25d19b
SC
274 in_frame[insn_word & 0x7] = reg_save_depth;
275 next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
31778db0 276 reg_save_depth += 2 + adjust;
ec25d19b 277 }
1f46923f
SC
278
279 /* Is this a move into the fp */
ec25d19b
SC
280 if (next_ip && IS_MOV_SP_FP (insn_word))
281 {
282 ip = next_ip;
283 next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
284 have_fp = 1;
285 }
1f46923f
SC
286
287 /* Skip over any stack adjustment, happens either with a number of
288 sub#2,sp or a mov #x,r5 sub r5,sp */
289
31778db0 290 if (next_ip && (IS_SUB2_SP (insn_word) || IS_SUB4_SP (insn_word)))
1f46923f 291 {
31778db0 292 while (next_ip && (IS_SUB2_SP (insn_word) || IS_SUB4_SP (insn_word)))
ec25d19b 293 {
31778db0 294 auto_depth += IS_SUB2_SP (insn_word) ? 2 : 4;
ec25d19b
SC
295 ip = next_ip;
296 next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
297 }
1f46923f 298 }
ec25d19b
SC
299 else
300 {
301 if (next_ip && IS_MOVK_R5 (insn_word))
302 {
303 ip = next_ip;
304 next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
305 auto_depth += insn_word;
306
307 next_ip = NEXT_PROLOGUE_INSN (next_ip, limit, &insn_word);
308 auto_depth += insn_word;
ec25d19b 309 }
31778db0
JL
310 if (next_ip && IS_SUBL_SP (insn_word))
311 {
312 ip = next_ip;
313 auto_depth += read_memory_unsigned_integer (ip, 4);
314 ip += 4;
315
316 next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
317 }
ec25d19b 318 }
31778db0 319
ec25d19b
SC
320 /* Work out which regs are stored where */
321 while (next_ip && IS_PUSH (insn_word))
1f46923f
SC
322 {
323 ip = next_ip;
ec25d19b
SC
324 next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn_word);
325 fsr->regs[r] = after_prolog_fp + auto_depth;
326 auto_depth += 2;
1f46923f 327 }
1f46923f 328
1f46923f 329 /* The args are always reffed based from the stack pointer */
ec25d19b 330 fi->args_pointer = after_prolog_fp;
1f46923f 331 /* Locals are always reffed based from the fp */
ec25d19b 332 fi->locals_pointer = after_prolog_fp;
1f46923f 333 /* The PC is at a known place */
31778db0 334 fi->from_pc = read_memory_unsigned_integer (after_prolog_fp + BINWORD, BINWORD);
1f46923f
SC
335
336 /* Rememeber any others too */
1f46923f 337 in_frame[PC_REGNUM] = 0;
ec25d19b
SC
338
339 if (have_fp)
340 /* We keep the old FP in the SP spot */
b1d0b161 341 fsr->regs[SP_REGNUM] = read_memory_unsigned_integer (fsr->regs[6], BINWORD);
ec25d19b
SC
342 else
343 fsr->regs[SP_REGNUM] = after_prolog_fp + auto_depth;
344
1f46923f
SC
345 return (ip);
346}
347
348void
349init_extra_frame_info (fromleaf, fi)
350 int fromleaf;
351 struct frame_info *fi;
352{
353 fi->fsr = 0; /* Not yet allocated */
354 fi->args_pointer = 0; /* Unknown */
355 fi->locals_pointer = 0; /* Unknown */
356 fi->from_pc = 0;
1f46923f 357}
ec25d19b 358
1f46923f
SC
359/* Return the saved PC from this frame.
360
361 If the frame has a memory copy of SRP_REGNUM, use that. If not,
362 just use the register SRP_REGNUM itself. */
363
364CORE_ADDR
365frame_saved_pc (frame)
669caa9c 366 struct frame_info *frame;
1f46923f
SC
367{
368 return frame->from_pc;
369}
370
1f46923f
SC
371CORE_ADDR
372frame_locals_address (fi)
373 struct frame_info *fi;
374{
ec25d19b
SC
375 if (!fi->locals_pointer)
376 {
377 struct frame_saved_regs ignore;
378
379 get_frame_saved_regs (fi, &ignore);
1f46923f 380
ec25d19b 381 }
1f46923f
SC
382 return fi->locals_pointer;
383}
384
385/* Return the address of the argument block for the frame
386 described by FI. Returns 0 if the address is unknown. */
387
388CORE_ADDR
389frame_args_address (fi)
390 struct frame_info *fi;
391{
ec25d19b
SC
392 if (!fi->args_pointer)
393 {
394 struct frame_saved_regs ignore;
395
396 get_frame_saved_regs (fi, &ignore);
397
398 }
1f46923f 399
1f46923f
SC
400 return fi->args_pointer;
401}
402
ec25d19b
SC
403void
404h8300_pop_frame ()
1f46923f
SC
405{
406 unsigned regnum;
407 struct frame_saved_regs fsr;
669caa9c 408 struct frame_info *frame = get_current_frame ();
1f46923f 409
669caa9c 410 get_frame_saved_regs (frame, &fsr);
ec25d19b 411
256b4f37 412 for (regnum = 0; regnum < 8; regnum++)
1f46923f 413 {
6bafbdfb
JL
414 /* Don't forget SP_REGNUM is a frame_saved_regs struct is the
415 actual value we want, not the address of the value we want. */
416 if (fsr.regs[regnum] && regnum != SP_REGNUM)
f9fedc48 417 write_register (regnum, read_memory_integer(fsr.regs[regnum], BINWORD));
6bafbdfb
JL
418 else if (fsr.regs[regnum] && regnum == SP_REGNUM)
419 write_register (regnum, fsr.regs[regnum]);
1f46923f 420 }
6bafbdfb
JL
421
422 /* Don't forget the update the PC too! */
423 write_pc (frame->from_pc);
424 flush_cached_frames ();
1f46923f 425}
ec25d19b 426
a3059251
SC
427
428struct cmd_list_element *setmemorylist;
429
430static void
431h8300_command(args, from_tty)
432{
433 extern int h8300hmode;
434 h8300hmode = 0;
d15396df
JL
435/* start-sanitize-h8s */
436 h8300smode = 0;
437/* end-sanitize-h8s */
a3059251
SC
438}
439
440static void
441h8300h_command(args, from_tty)
442{
443 extern int h8300hmode;
444 h8300hmode = 1;
d15396df
JL
445/* start-sanitize-h8s */
446 h8300smode = 0;
447/* end-sanitize-h8s */
448}
449/* start-sanitize-h8s */
450static void
451h8300s_command(args, from_tty)
452{
453 extern int h8300smode;
454 extern int h8300hmode;
455 h8300smode = 1;
456 h8300hmode = 1;
a3059251 457}
d15396df
JL
458/* end-santiize-h8s */
459
a3059251
SC
460
461static void
462set_machine (args, from_tty)
463 char *args;
464 int from_tty;
465{
d15396df
JL
466 printf_unfiltered ("\"set machine\" must be followed by h8300, h8300h");
467/* start-sanitize-h8s */
468 printf_unfiltered ("or h8300s");
469/* end-sanitize-h8s */
199b2450 470 help_list (setmemorylist, "set memory ", -1, gdb_stdout);
a3059251
SC
471}
472
f9fedc48
MA
473/* set_machine_hook is called as the exec file is being opened, but
474 before the symbol file is opened. This allows us to set the
475 h8300hmode flag based on the machine type specified in the exec
476 file. This in turn will cause subsequently defined pointer types
477 to be 16 or 32 bits as appropriate for the machine. */
478
479static void
480set_machine_hook (filename)
481 char *filename;
482{
d15396df
JL
483/* start-sanitize-h8s */
484 if (bfd_get_mach (exec_bfd) == bfd_mach_h8300s)
485 {
486 h8300smode = 1;
487 h8300hmode = 1;
488 }
489 else
490/* end-sanitize-h8s */
491 if (bfd_get_mach (exec_bfd) == bfd_mach_h8300h)
492 {
493/* start-sanitize-h8s */
494 h8300smode = 0;
495/* end-sanitize-h8s */
496 h8300hmode = 1;
497 }
498 else
499 {
500/* start-sanitize-h8s */
501 h8300smode = 0;
502/* end-sanitize-h8s */
503 h8300hmode = 0;
504 }
f9fedc48
MA
505}
506
a3059251
SC
507void
508_initialize_h8300m ()
509{
510 add_prefix_cmd ("machine", no_class, set_machine,
511 "set the machine type", &setmemorylist, "set machine ", 0,
512 &setlist);
513
514 add_cmd ("h8300", class_support, h8300_command,
515 "Set machine to be H8/300.", &setmemorylist);
516
517 add_cmd ("h8300h", class_support, h8300h_command,
518 "Set machine to be H8/300H.", &setmemorylist);
f9fedc48 519
d15396df
JL
520/* start-sanitize-h8s */
521 add_cmd ("h8300s", class_support, h8300s_command,
522 "Set machine to be H8/300S.", &setmemorylist);
523/* end-sanitize-h8s */
524
f9fedc48
MA
525 /* Add a hook to set the machine type when we're loading a file. */
526
527 specify_exec_file_hook(set_machine_hook);
a3059251
SC
528}
529
530
531
ec25d19b
SC
532void
533print_register_hook (regno)
534{
535 if (regno == 8)
536 {
537 /* CCR register */
ec25d19b 538 int C, Z, N, V;
08c0d7b8 539 unsigned char b[4];
ec25d19b 540 unsigned char l;
ec25d19b 541 read_relative_register_raw_bytes (regno, b);
08c0d7b8 542 l = b[REGISTER_VIRTUAL_SIZE(8) -1];
199b2450
TL
543 printf_unfiltered ("\t");
544 printf_unfiltered ("I-%d - ", (l & 0x80) != 0);
545 printf_unfiltered ("H-%d - ", (l & 0x20) != 0);
ec25d19b
SC
546 N = (l & 0x8) != 0;
547 Z = (l & 0x4) != 0;
548 V = (l & 0x2) != 0;
549 C = (l & 0x1) != 0;
199b2450
TL
550 printf_unfiltered ("N-%d ", N);
551 printf_unfiltered ("Z-%d ", Z);
552 printf_unfiltered ("V-%d ", V);
553 printf_unfiltered ("C-%d ", C);
ec25d19b 554 if ((C | Z) == 0)
199b2450 555 printf_unfiltered ("u> ");
ec25d19b 556 if ((C | Z) == 1)
199b2450 557 printf_unfiltered ("u<= ");
ec25d19b 558 if ((C == 0))
199b2450 559 printf_unfiltered ("u>= ");
ec25d19b 560 if (C == 1)
199b2450 561 printf_unfiltered ("u< ");
ec25d19b 562 if (Z == 0)
199b2450 563 printf_unfiltered ("!= ");
ec25d19b 564 if (Z == 1)
199b2450 565 printf_unfiltered ("== ");
ec25d19b 566 if ((N ^ V) == 0)
199b2450 567 printf_unfiltered (">= ");
ec25d19b 568 if ((N ^ V) == 1)
199b2450 569 printf_unfiltered ("< ");
ec25d19b 570 if ((Z | (N ^ V)) == 0)
199b2450 571 printf_unfiltered ("> ");
ec25d19b 572 if ((Z | (N ^ V)) == 1)
199b2450 573 printf_unfiltered ("<= ");
ec25d19b
SC
574 }
575}
a3059251 576
18b46e7c
SS
577void
578_initialize_h8300_tdep ()
579{
580 tm_print_insn = gdb_print_insn_h8300;
581}
This page took 0.2324 seconds and 4 git commands to generate.