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