diff options
author | Andrew Cagney <cagney@redhat.com> | 2000-07-27 11:23:39 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2000-07-27 11:23:39 +0000 |
commit | e0709f5044a0e824475defef03f86346ed9a292e (patch) | |
tree | e06389fffbbc598f7e212d1eedd4688720a72ca9 /sim/m68hc11/interp.c | |
parent | 3c765a54971db6d8dbeafdf5230ad692cad271b3 (diff) | |
download | binutils-gdb-e0709f5044a0e824475defef03f86346ed9a292e.tar.gz |
New simulator.
Diffstat (limited to 'sim/m68hc11/interp.c')
-rw-r--r-- | sim/m68hc11/interp.c | 517 |
1 files changed, 517 insertions, 0 deletions
diff --git a/sim/m68hc11/interp.c b/sim/m68hc11/interp.c new file mode 100644 index 00000000000..c05f1b847a5 --- /dev/null +++ b/sim/m68hc11/interp.c @@ -0,0 +1,517 @@ +/* interp.c -- Simulator for Motorola 68HC11 + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + Written by Stephane Carrez (stcarrez@worldnet.fr) + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "sim-assert.h" +#include "sim-hw.h" +#include "sim-options.h" +#include "hw-tree.h" +#include "hw-device.h" +#include "hw-ports.h" + +#ifndef MONITOR_BASE +# define MONITOR_BASE (0x0C000) +# define MONITOR_SIZE (0x04000) +#endif + +static void sim_get_info (SIM_DESC sd, char *cmd); + + +char *interrupt_names[] = { + "reset", + "nmi", + "int", + NULL +}; + +#ifndef INLINE +#if defined(__GNUC__) && defined(__OPTIMIZE__) +#define INLINE __inline__ +#else +#define INLINE +#endif +#endif + +struct sim_info_list +{ + const char *name; + const char *device; +}; + +struct sim_info_list dev_list[] = { + {"cpu", "/m68hc11"}, + {"timer", "/m68hc11/m68hc11tim"}, + {"sio", "/m68hc11/m68hc11sio"}, + {"spi", "/m68hc11/m68hc11spi"}, + {"eeprom", "/m68hc11/m68hc11eepr"}, + {0, 0} +}; + +/* Give some information about the simulator. */ +static void +sim_get_info (SIM_DESC sd, char *cmd) +{ + sim_cpu *cpu; + + if (cmd != 0 && (cmd[0] == ' ' || cmd[0] == '-')) + { + int i; + struct hw *hw_dev; + cmd++; + + for (i = 0; dev_list[i].name; i++) + if (strcmp (cmd, dev_list[i].name) == 0) + break; + + if (dev_list[i].name == 0) + { + sim_io_eprintf (sd, "Device '%s' not found.\n", cmd); + sim_io_eprintf (sd, "Valid devices: cpu timer sio eeprom\n"); + return; + } + hw_dev = sim_hw_parse (sd, dev_list[i].device); + if (hw_dev == 0) + { + sim_io_eprintf (sd, "Device '%s' not found\n", dev_list[i].device); + return; + } + hw_ioctl (hw_dev, 23, 0); + return; + } + + cpu = STATE_CPU (sd, 0); + cpu_info (sd, cpu); + interrupts_info (sd, &cpu->cpu_interrupts); +} + + +void +sim_board_reset (SIM_DESC sd) +{ + struct hw *hw_cpu; + sim_cpu *cpu; + + cpu = STATE_CPU (sd, 0); + /* hw_cpu = sim_hw_parse (sd, "/"); */ + hw_cpu = sim_hw_parse (sd, "/m68hc11"); + if (hw_cpu == 0) + { + sim_io_eprintf (sd, "m68hc11 cpu not found in device tree."); + return; + } + + cpu_reset (cpu); + hw_port_event (hw_cpu, 3, 0); + cpu_restart (cpu); +} + +SIM_DESC +sim_open (SIM_OPEN_KIND kind, host_callback *callback, + struct _bfd *abfd, char **argv) +{ + char **p; + SIM_DESC sd; + sim_cpu *cpu; + struct hw *device_tree; + + sd = sim_state_alloc (kind, callback); + cpu = STATE_CPU (sd, 0); + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + + /* for compatibility */ + current_alignment = NONSTRICT_ALIGNMENT; + current_target_byte_order = BIG_ENDIAN; + + cpu_initialize (sd, cpu); + + cpu->cpu_use_elf_start = 1; + if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) + return 0; + + /* getopt will print the error message so we just have to exit if this fails. + FIXME: Hmmm... in the case of gdb we need getopt to call + print_filtered. */ + if (sim_parse_args (sd, argv) != SIM_RC_OK) + { + /* Uninstall the modules to avoid memory leaks, + file descriptor leaks, etc. */ + sim_module_uninstall (sd); + return 0; + } + + device_tree = sim_hw_parse (sd, "/"); + if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0) + { + /* Allocate core managed memory */ + + /* the monitor */ + sim_do_commandf (sd, "memory region 0x%lx,0x%lx", + /* MONITOR_BASE, MONITOR_SIZE */ + 0x8000, 0x8000); + sim_do_command (sd, " memory region 0x000,0x8000"); + sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F"); + } + + if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0) + { + sim_hw_parse (sd, "/m68hc11/m68hc11sio/reg 0x2b 0x5"); + sim_hw_parse (sd, "/m68hc11/m68hc11sio/backend stdio"); + sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11sio"); + } + if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11tim/reg") == 0) + { + /* M68hc11 Timer configuration. */ + sim_hw_parse (sd, "/m68hc11/m68hc11tim/reg 0x1b 0x5"); + sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11tim"); + } + + /* Create the SPI device. */ + if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11spi/reg") == 0) + { + sim_hw_parse (sd, "/m68hc11/m68hc11spi/reg 0x28 0x3"); + sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi"); + } + if (hw_tree_find_property (device_tree, "/m68hc11/pram/reg") == 0) + { + /* M68hc11 persistent ram configuration. */ + sim_hw_parse (sd, "/m68hc11/nvram/reg 0x0 256"); + sim_hw_parse (sd, "/m68hc11/nvram/file m68hc11.ram"); + sim_hw_parse (sd, "/m68hc11/nvram/mode save-modified"); + sim_hw_parse (sd, "/m68hc11/nvram/overlap? true"); + /*sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/pram"); */ + } + if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11eepr/reg") == 0) + { + sim_hw_parse (sd, "/m68hc11/m68hc11eepr/reg 0xb000 512"); + /* Connect the CPU reset to all devices. */ + sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr"); + } + + /* Check for/establish the a reference program image. */ + if (sim_analyze_program (sd, + (STATE_PROG_ARGV (sd) != NULL + ? *STATE_PROG_ARGV (sd) + : NULL), abfd) != SIM_RC_OK) + { + sim_module_uninstall (sd); + return 0; + } + + /* Establish any remaining configuration options. */ + if (sim_config (sd) != SIM_RC_OK) + { + sim_module_uninstall (sd); + return 0; + } + + if (sim_post_argv_init (sd) != SIM_RC_OK) + { + /* Uninstall the modules to avoid memory leaks, + file descriptor leaks, etc. */ + sim_module_uninstall (sd); + return 0; + } + + if (abfd != NULL) + { + cpu->cpu_elf_start = bfd_get_start_address (abfd); + } + + sim_board_reset (sd); + + /* Fudge our descriptor. */ + return sd; +} + + +void +sim_close (SIM_DESC sd, int quitting) +{ + /* shut down modules */ + sim_module_uninstall (sd); + + /* Ensure that any resources allocated through the callback + mechanism are released: */ + sim_io_shutdown (sd); + + /* FIXME - free SD */ + + return; +} + +void +sim_set_profile (int n) +{ +} + +void +sim_set_profile_size (int n) +{ +} + +/* Generic implementation of sim_engine_run that works within the + sim_engine setjmp/longjmp framework. */ + +void +sim_engine_run (SIM_DESC sd, + int next_cpu_nr, /* ignore */ + int nr_cpus, /* ignore */ + int siggnal) /* ignore */ +{ + sim_cpu *cpu; + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + cpu = STATE_CPU (sd, 0); + while (1) + { + cpu_single_step (cpu); + + /* process any events */ + if (sim_events_tickn (sd, cpu->cpu_current_cycle)) + { + sim_events_process (sd); + } + } +} + +int +sim_trace (SIM_DESC sd) +{ + sim_resume (sd, 0, 0); + return 1; +} + +void +sim_info (SIM_DESC sd, int verbose) +{ + sim_io_eprintf (sd, "Simulator info:\n"); + sim_io_eprintf (sd, " CPU Motorola 68HC11\n"); + sim_get_info (sd, 0); + sim_module_info (sd, verbose || STATE_VERBOSE_P (sd)); +} + +SIM_RC +sim_create_inferior (SIM_DESC sd, struct _bfd *abfd, + char **argv, char **env) +{ + sim_cpu *cpu; + int i; + + cpu = STATE_CPU (sd, 0); + + if (abfd != NULL) + { + cpu->cpu_elf_start = bfd_get_start_address (abfd); + } + + /* reset all state information */ + sim_board_reset (sd); + + /* Get information about the number of pseudo registers. */ + for (i = FIRST_SOFT_REGNUM; i <= ZD32_REGNUM; i++) + { + switch (i) + { + case TMP_REGNUM: + cpu->cpu_page0_reg[i - FIRST_SOFT_REGNUM] = 0; + break; + case Z_REGNUM: + case ZS_REGNUM: + cpu->cpu_page0_reg[i - FIRST_SOFT_REGNUM] = 2; + break; + case XY_REGNUM: + cpu->cpu_page0_reg[i - FIRST_SOFT_REGNUM] = 4; + break; + case FP_REGNUM: + cpu->cpu_page0_reg[i - FIRST_SOFT_REGNUM] = 6; + break; + default: + cpu->cpu_page0_reg[i - FIRST_SOFT_REGNUM] + = ((i - FIRST_SOFT_REGNUM) * 2) - 2; + break; + } + } + cpu->cpu_nb_pseudo_regs = 8; + + return SIM_RC_OK; +} + + +void +sim_set_callbacks (host_callback *p) +{ + /* m6811_callback = p; */ +} + + +int +sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length) +{ + sim_cpu *cpu; + uint16 val; + + cpu = STATE_CPU (sd, 0); + switch (rn) + { + case A_REGNUM: + val = cpu_get_a (cpu); + break; + + case B_REGNUM: + val = cpu_get_b (cpu); + break; + + case D_REGNUM: + val = cpu_get_d (cpu); + break; + + case X_REGNUM: + val = cpu_get_x (cpu); + break; + + case Y_REGNUM: + val = cpu_get_y (cpu); + break; + + case SP_REGNUM: + val = cpu_get_sp (cpu); + break; + + case PC_REGNUM: + val = cpu_get_pc (cpu); + break; + + case PSW_REGNUM: + val = cpu_get_ccr (cpu); + break; + + + /* Read a pseudo register. Pseudo registers are located at + beginning of page 0. Each of them is 2 bytes. */ + default: + if (rn < FIRST_SOFT_REGNUM || rn >= ZD32_REGNUM) + { + val = 0; + } + else + { + uint16 addr; + + addr = cpu->cpu_page0_reg[rn - FIRST_SOFT_REGNUM]; + val = memory_read16 (cpu, addr); + } + break; + } + memory[0] = val >> 8; + memory[1] = val & 0x0FF; + return 2; +} + +int +sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length) +{ + uint16 val; + sim_cpu *cpu; + + cpu = STATE_CPU (sd, 0); + + val = *memory++; + if (length == 2) + val = (val << 8) | *memory; + + switch (rn) + { + case D_REGNUM: + cpu_set_d (cpu, val); + break; + + case A_REGNUM: + cpu_set_a (cpu, val); + break; + + case B_REGNUM: + cpu_set_b (cpu, val); + break; + + case X_REGNUM: + cpu_set_x (cpu, val); + break; + + case Y_REGNUM: + cpu_set_y (cpu, val); + break; + + case SP_REGNUM: + cpu_set_sp (cpu, val); + break; + + case PC_REGNUM: + cpu_set_pc (cpu, val); + break; + + case PSW_REGNUM: + cpu_set_ccr (cpu, val); + break; + + /* Write a pseudo register. Pseudo registers are located at + beginning of page 0. Each of them is 2 bytes. */ + default: + if (rn >= FIRST_SOFT_REGNUM && rn <= ZD32_REGNUM) + { + uint16 addr; + + addr = cpu->cpu_page0_reg[rn - FIRST_SOFT_REGNUM]; + memory_write16 (cpu, addr, val); + } + break; + } + + return 2; +} + +void +sim_size (int s) +{ + ; +} + +void +sim_do_command (SIM_DESC sd, char *cmd) +{ + char *mm_cmd = "memory-map"; + char *int_cmd = "interrupt"; + + /* Commands available from GDB: */ + if (sim_args_command (sd, cmd) != SIM_RC_OK) + { + if (strncmp (cmd, "info", sizeof ("info") - 1) == 0) + sim_get_info (sd, &cmd[4]); + else if (strncmp (cmd, "frame", sizeof ("frame") - 1) == 0) + cpu_print_frame (sd, STATE_CPU (sd, 0)); + else if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0)) + sim_io_eprintf (sd, + "`memory-map' command replaced by `sim memory'\n"); + else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0) + sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n"); + else + sim_io_eprintf (sd, "Unknown command `%s'\n", cmd); + } +} |