]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/m68hc11/interp.c
*** empty log message ***
[thirdparty/binutils-gdb.git] / sim / m68hc11 / interp.c
CommitLineData
e0709f50 1/* interp.c -- Simulator for Motorola 68HC11
81e09ed8 2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
e0709f50
AC
3 Written by Stephane Carrez (stcarrez@worldnet.fr)
4
5This file is part of GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License along
18with this program; if not, write to the Free Software Foundation, Inc.,
1959 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21#include "sim-main.h"
22#include "sim-assert.h"
23#include "sim-hw.h"
24#include "sim-options.h"
25#include "hw-tree.h"
26#include "hw-device.h"
27#include "hw-ports.h"
28
29#ifndef MONITOR_BASE
30# define MONITOR_BASE (0x0C000)
31# define MONITOR_SIZE (0x04000)
32#endif
33
34static void sim_get_info (SIM_DESC sd, char *cmd);
35
36
37char *interrupt_names[] = {
38 "reset",
39 "nmi",
40 "int",
41 NULL
42};
43
44#ifndef INLINE
45#if defined(__GNUC__) && defined(__OPTIMIZE__)
46#define INLINE __inline__
47#else
48#define INLINE
49#endif
50#endif
51
52struct sim_info_list
53{
54 const char *name;
55 const char *device;
56};
57
81e09ed8 58struct sim_info_list dev_list_68hc11[] = {
e0709f50
AC
59 {"cpu", "/m68hc11"},
60 {"timer", "/m68hc11/m68hc11tim"},
61 {"sio", "/m68hc11/m68hc11sio"},
62 {"spi", "/m68hc11/m68hc11spi"},
63 {"eeprom", "/m68hc11/m68hc11eepr"},
64 {0, 0}
65};
66
81e09ed8
SC
67struct sim_info_list dev_list_68hc12[] = {
68 {"cpu", "/m68hc12"},
69 {"timer", "/m68hc12/m68hc12tim"},
70 {"sio", "/m68hc12/m68hc12sio"},
71 {"spi", "/m68hc12/m68hc12spi"},
72 {"eeprom", "/m68hc12/m68hc12eepr"},
73 {0, 0}
74};
75
76/* Cover function of sim_state_free to free the cpu buffers as well. */
77
78static void
79free_state (SIM_DESC sd)
80{
81 if (STATE_MODULES (sd) != NULL)
82 sim_module_uninstall (sd);
83
84 sim_state_free (sd);
85}
86
e0709f50
AC
87/* Give some information about the simulator. */
88static void
89sim_get_info (SIM_DESC sd, char *cmd)
90{
91 sim_cpu *cpu;
92
81e09ed8 93 cpu = STATE_CPU (sd, 0);
e0709f50
AC
94 if (cmd != 0 && (cmd[0] == ' ' || cmd[0] == '-'))
95 {
96 int i;
97 struct hw *hw_dev;
81e09ed8
SC
98 struct sim_info_list *dev_list;
99 const struct bfd_arch_info *arch;
100
101 arch = STATE_ARCHITECTURE (sd);
e0709f50
AC
102 cmd++;
103
81e09ed8
SC
104 if (arch->arch == bfd_arch_m68hc11)
105 dev_list = dev_list_68hc11;
106 else
107 dev_list = dev_list_68hc12;
108
e0709f50
AC
109 for (i = 0; dev_list[i].name; i++)
110 if (strcmp (cmd, dev_list[i].name) == 0)
111 break;
112
113 if (dev_list[i].name == 0)
114 {
115 sim_io_eprintf (sd, "Device '%s' not found.\n", cmd);
116 sim_io_eprintf (sd, "Valid devices: cpu timer sio eeprom\n");
117 return;
118 }
119 hw_dev = sim_hw_parse (sd, dev_list[i].device);
120 if (hw_dev == 0)
121 {
122 sim_io_eprintf (sd, "Device '%s' not found\n", dev_list[i].device);
123 return;
124 }
125 hw_ioctl (hw_dev, 23, 0);
126 return;
127 }
128
e0709f50
AC
129 cpu_info (sd, cpu);
130 interrupts_info (sd, &cpu->cpu_interrupts);
131}
132
133
134void
135sim_board_reset (SIM_DESC sd)
136{
137 struct hw *hw_cpu;
138 sim_cpu *cpu;
81e09ed8
SC
139 const struct bfd_arch_info *arch;
140 const char *cpu_type;
e0709f50
AC
141
142 cpu = STATE_CPU (sd, 0);
81e09ed8
SC
143 arch = STATE_ARCHITECTURE (sd);
144
e0709f50 145 /* hw_cpu = sim_hw_parse (sd, "/"); */
81e09ed8
SC
146 if (arch->arch == bfd_arch_m68hc11)
147 {
148 cpu->cpu_type = CPU_M6811;
149 cpu_type = "/m68hc11";
150 }
151 else
152 {
153 cpu->cpu_type = CPU_M6812;
154 cpu_type = "/m68hc12";
155 }
156
157 hw_cpu = sim_hw_parse (sd, cpu_type);
e0709f50
AC
158 if (hw_cpu == 0)
159 {
81e09ed8 160 sim_io_eprintf (sd, "%s cpu not found in device tree.", cpu_type);
e0709f50
AC
161 return;
162 }
163
164 cpu_reset (cpu);
165 hw_port_event (hw_cpu, 3, 0);
166 cpu_restart (cpu);
167}
168
81e09ed8
SC
169int
170sim_hw_configure (SIM_DESC sd)
171{
172 const struct bfd_arch_info *arch;
173 struct hw *device_tree;
174 int m6811_mode;
175 sim_cpu *cpu;
176
177 arch = STATE_ARCHITECTURE (sd);
178 if (arch == 0)
179 return 0;
180
181 cpu = STATE_CPU (sd, 0);
182 cpu->cpu_configured_arch = arch;
183 device_tree = sim_hw_parse (sd, "/");
184 if (arch->arch == bfd_arch_m68hc11)
185 {
186 cpu->cpu_interpretor = cpu_interp_m6811;
187 if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0)
188 {
189 /* Allocate core managed memory */
190
191 /* the monitor */
192 sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx",
193 /* MONITOR_BASE, MONITOR_SIZE */
194 0x8000, M6811_RAM_LEVEL, 0x8000);
195 sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
196 M6811_RAM_LEVEL);
197 sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F");
198 }
199
200 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0)
201 {
202 sim_hw_parse (sd, "/m68hc11/m68hc11sio/reg 0x2b 0x5");
203 sim_hw_parse (sd, "/m68hc11/m68hc11sio/backend stdio");
204 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11sio");
205 }
206 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11tim/reg") == 0)
207 {
208 /* M68hc11 Timer configuration. */
209 sim_hw_parse (sd, "/m68hc11/m68hc11tim/reg 0x1b 0x5");
210 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11tim");
211 }
212
213 /* Create the SPI device. */
214 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11spi/reg") == 0)
215 {
216 sim_hw_parse (sd, "/m68hc11/m68hc11spi/reg 0x28 0x3");
217 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi");
218 }
219 if (hw_tree_find_property (device_tree, "/m68hc11/nvram/reg") == 0)
220 {
221 /* M68hc11 persistent ram configuration. */
222 sim_hw_parse (sd, "/m68hc11/nvram/reg 0x0 256");
223 sim_hw_parse (sd, "/m68hc11/nvram/file m68hc11.ram");
224 sim_hw_parse (sd, "/m68hc11/nvram/mode save-modified");
225 /*sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/pram"); */
226 }
227 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11eepr/reg") == 0)
228 {
229 sim_hw_parse (sd, "/m68hc11/m68hc11eepr/reg 0xb000 512");
230 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr");
231 }
232 }
233 else
234 {
235 cpu->cpu_interpretor = cpu_interp_m6812;
236 if (hw_tree_find_property (device_tree, "/m68hc12/reg") == 0)
237 {
238 /* Allocate core external memory. */
239 sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx",
240 0x8000, M6811_RAM_LEVEL, 0x8000);
241 sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
242 M6811_RAM_LEVEL);
243
244 sim_hw_parse (sd, "/m68hc12/reg 0x0 0x3FF");
245 }
246
247 if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@1/reg"))
248 {
249 sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/reg 0xC0 0x8");
250 sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/backend stdio");
251 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@1");
252 }
253 if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@2/reg"))
254 {
255 sim_hw_parse (sd, "/m68hc12/m68hc12sio@2/reg 0xC8 0x8");
256 sim_hw_parse (sd, "/m68hc12/m68hc12sio@2/backend tcp");
257 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@2");
258 }
259 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12tim/reg") == 0)
260 {
261 /* M68hc11 Timer configuration. */
262 sim_hw_parse (sd, "/m68hc12/m68hc12tim/reg 0x1b 0x5");
263 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12tim");
264 }
265
266 /* Create the SPI device. */
267 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12spi/reg") == 0)
268 {
269 sim_hw_parse (sd, "/m68hc12/m68hc12spi/reg 0x28 0x3");
270 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12spi");
271 }
272 if (hw_tree_find_property (device_tree, "/m68hc12/nvram/reg") == 0)
273 {
274 /* M68hc11 persistent ram configuration. */
275 sim_hw_parse (sd, "/m68hc12/nvram/reg 0x2000 8192");
276 sim_hw_parse (sd, "/m68hc12/nvram/file m68hc12.ram");
277 sim_hw_parse (sd, "/m68hc12/nvram/mode save-modified");
278 }
279 if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12eepr/reg") == 0)
280 {
281 sim_hw_parse (sd, "/m68hc12/m68hc12eepr/reg 0x0800 2048");
282 sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12eepr");
283 }
284 }
285 return 0;
286}
287
288static int
289sim_prepare_for_program (SIM_DESC sd, struct _bfd* abfd)
290{
291 sim_cpu *cpu;
292
293 cpu = STATE_CPU (sd, 0);
294
295 sim_hw_configure (sd);
296 if (abfd != NULL)
297 {
298 cpu->cpu_elf_start = bfd_get_start_address (abfd);
299 }
300
301 /* reset all state information */
302 sim_board_reset (sd);
303
304 return SIM_RC_OK;
305}
306
e0709f50
AC
307SIM_DESC
308sim_open (SIM_OPEN_KIND kind, host_callback *callback,
309 struct _bfd *abfd, char **argv)
310{
311 char **p;
312 SIM_DESC sd;
313 sim_cpu *cpu;
314 struct hw *device_tree;
315
316 sd = sim_state_alloc (kind, callback);
317 cpu = STATE_CPU (sd, 0);
318
319 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
320
321 /* for compatibility */
322 current_alignment = NONSTRICT_ALIGNMENT;
323 current_target_byte_order = BIG_ENDIAN;
324
325 cpu_initialize (sd, cpu);
326
327 cpu->cpu_use_elf_start = 1;
328 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
81e09ed8
SC
329 {
330 free_state (sd);
331 return 0;
332 }
e0709f50
AC
333
334 /* getopt will print the error message so we just have to exit if this fails.
335 FIXME: Hmmm... in the case of gdb we need getopt to call
336 print_filtered. */
337 if (sim_parse_args (sd, argv) != SIM_RC_OK)
338 {
339 /* Uninstall the modules to avoid memory leaks,
340 file descriptor leaks, etc. */
81e09ed8 341 free_state (sd);
e0709f50
AC
342 return 0;
343 }
344
e0709f50
AC
345 /* Check for/establish the a reference program image. */
346 if (sim_analyze_program (sd,
347 (STATE_PROG_ARGV (sd) != NULL
348 ? *STATE_PROG_ARGV (sd)
349 : NULL), abfd) != SIM_RC_OK)
350 {
81e09ed8 351 free_state (sd);
e0709f50
AC
352 return 0;
353 }
354
355 /* Establish any remaining configuration options. */
356 if (sim_config (sd) != SIM_RC_OK)
357 {
81e09ed8 358 free_state (sd);
e0709f50
AC
359 return 0;
360 }
361
362 if (sim_post_argv_init (sd) != SIM_RC_OK)
363 {
364 /* Uninstall the modules to avoid memory leaks,
365 file descriptor leaks, etc. */
81e09ed8 366 free_state (sd);
e0709f50
AC
367 return 0;
368 }
369
81e09ed8 370 sim_hw_configure (sd);
e0709f50
AC
371
372 /* Fudge our descriptor. */
373 return sd;
374}
375
376
377void
378sim_close (SIM_DESC sd, int quitting)
379{
380 /* shut down modules */
381 sim_module_uninstall (sd);
382
383 /* Ensure that any resources allocated through the callback
384 mechanism are released: */
385 sim_io_shutdown (sd);
386
387 /* FIXME - free SD */
81e09ed8 388 sim_state_free (sd);
e0709f50
AC
389 return;
390}
391
392void
393sim_set_profile (int n)
394{
395}
396
397void
398sim_set_profile_size (int n)
399{
400}
401
402/* Generic implementation of sim_engine_run that works within the
403 sim_engine setjmp/longjmp framework. */
404
405void
406sim_engine_run (SIM_DESC sd,
407 int next_cpu_nr, /* ignore */
408 int nr_cpus, /* ignore */
409 int siggnal) /* ignore */
410{
411 sim_cpu *cpu;
412
413 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
414 cpu = STATE_CPU (sd, 0);
415 while (1)
416 {
417 cpu_single_step (cpu);
418
419 /* process any events */
420 if (sim_events_tickn (sd, cpu->cpu_current_cycle))
421 {
422 sim_events_process (sd);
423 }
424 }
425}
426
427int
428sim_trace (SIM_DESC sd)
429{
430 sim_resume (sd, 0, 0);
431 return 1;
432}
433
434void
435sim_info (SIM_DESC sd, int verbose)
436{
81e09ed8
SC
437 const char *cpu_type;
438 const struct bfd_arch_info *arch;
439
440 arch = STATE_ARCHITECTURE (sd);
441 if (arch->arch == bfd_arch_m68hc11)
442 cpu_type = "68HC11";
443 else
444 cpu_type = "68HC12";
445
e0709f50 446 sim_io_eprintf (sd, "Simulator info:\n");
81e09ed8 447 sim_io_eprintf (sd, " CPU Motorola %s\n", cpu_type);
e0709f50
AC
448 sim_get_info (sd, 0);
449 sim_module_info (sd, verbose || STATE_VERBOSE_P (sd));
450}
451
452SIM_RC
453sim_create_inferior (SIM_DESC sd, struct _bfd *abfd,
454 char **argv, char **env)
455{
81e09ed8 456 return sim_prepare_for_program (sd, abfd);
e0709f50
AC
457}
458
459
460void
461sim_set_callbacks (host_callback *p)
462{
463 /* m6811_callback = p; */
464}
465
466
467int
468sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
469{
470 sim_cpu *cpu;
471 uint16 val;
472
473 cpu = STATE_CPU (sd, 0);
474 switch (rn)
475 {
476 case A_REGNUM:
477 val = cpu_get_a (cpu);
478 break;
479
480 case B_REGNUM:
481 val = cpu_get_b (cpu);
482 break;
483
484 case D_REGNUM:
485 val = cpu_get_d (cpu);
486 break;
487
488 case X_REGNUM:
489 val = cpu_get_x (cpu);
490 break;
491
492 case Y_REGNUM:
493 val = cpu_get_y (cpu);
494 break;
495
496 case SP_REGNUM:
497 val = cpu_get_sp (cpu);
498 break;
499
500 case PC_REGNUM:
501 val = cpu_get_pc (cpu);
502 break;
503
504 case PSW_REGNUM:
505 val = cpu_get_ccr (cpu);
506 break;
507
e0709f50 508 default:
9830501b 509 val = 0;
e0709f50
AC
510 break;
511 }
512 memory[0] = val >> 8;
513 memory[1] = val & 0x0FF;
514 return 2;
515}
516
517int
518sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
519{
520 uint16 val;
521 sim_cpu *cpu;
522
523 cpu = STATE_CPU (sd, 0);
524
525 val = *memory++;
526 if (length == 2)
527 val = (val << 8) | *memory;
528
529 switch (rn)
530 {
531 case D_REGNUM:
532 cpu_set_d (cpu, val);
533 break;
534
535 case A_REGNUM:
536 cpu_set_a (cpu, val);
537 break;
538
539 case B_REGNUM:
540 cpu_set_b (cpu, val);
541 break;
542
543 case X_REGNUM:
544 cpu_set_x (cpu, val);
545 break;
546
547 case Y_REGNUM:
548 cpu_set_y (cpu, val);
549 break;
550
551 case SP_REGNUM:
552 cpu_set_sp (cpu, val);
553 break;
554
555 case PC_REGNUM:
556 cpu_set_pc (cpu, val);
557 break;
558
559 case PSW_REGNUM:
560 cpu_set_ccr (cpu, val);
561 break;
562
e0709f50 563 default:
e0709f50
AC
564 break;
565 }
566
567 return 2;
568}
569
570void
571sim_size (int s)
572{
573 ;
574}
575
576void
577sim_do_command (SIM_DESC sd, char *cmd)
578{
579 char *mm_cmd = "memory-map";
580 char *int_cmd = "interrupt";
81e09ed8 581 sim_cpu *cpu;
e0709f50 582
81e09ed8 583 cpu = STATE_CPU (sd, 0);
e0709f50
AC
584 /* Commands available from GDB: */
585 if (sim_args_command (sd, cmd) != SIM_RC_OK)
586 {
587 if (strncmp (cmd, "info", sizeof ("info") - 1) == 0)
588 sim_get_info (sd, &cmd[4]);
589 else if (strncmp (cmd, "frame", sizeof ("frame") - 1) == 0)
590 cpu_print_frame (sd, STATE_CPU (sd, 0));
591 else if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0))
592 sim_io_eprintf (sd,
593 "`memory-map' command replaced by `sim memory'\n");
594 else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0)
595 sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n");
596 else
597 sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
598 }
81e09ed8
SC
599
600 /* If the architecture changed, re-configure. */
601 if (STATE_ARCHITECTURE (sd) != cpu->cpu_configured_arch)
602 sim_hw_configure (sd);
e0709f50 603}