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