X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fm68hc11%2Finterp.c;h=ab205714306b2f36b2ed6478afac46d927076e02;hb=527aaa4a3143afedd8dd85aa70862328a9dbe627;hp=74674ce2969c856875724e8d0dc7013623b47f30;hpb=2ee563b53258d390d7446e90a67f465d504ae44c;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/m68hc11/interp.c b/sim/m68hc11/interp.c index 74674ce296..ab20571430 100644 --- a/sim/m68hc11/interp.c +++ b/sim/m68hc11/interp.c @@ -1,22 +1,21 @@ /* interp.c -- Simulator for Motorola 68HC11/68HC12 - Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1999-2016 Free Software Foundation, Inc. Written by Stephane Carrez (stcarrez@nerim.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. +the Free Software Foundation; either version 3 of the License, 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. */ +You should have received a copy of the GNU General Public License +along with this program. If not, see . */ #include "sim-main.h" #include "sim-assert.h" @@ -25,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "hw-tree.h" #include "hw-device.h" #include "hw-ports.h" +#include "elf32-m68hc1x.h" #ifndef MONITOR_BASE # define MONITOR_BASE (0x0C000) @@ -33,22 +33,6 @@ with this program; if not, write to the Free Software Foundation, Inc., 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; @@ -194,8 +178,17 @@ sim_hw_configure (SIM_DESC sd) sim_do_commandf (sd, "memory region 0x000@%d,0x8000", M6811_RAM_LEVEL); sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F"); + if (cpu->bank_start < cpu->bank_end) + { + sim_do_commandf (sd, "memory region 0x%lx@%d,0x100000", + cpu->bank_virtual, M6811_RAM_LEVEL); + sim_hw_parse (sd, "/m68hc11/use_bank 1"); + } } - + if (cpu->cpu_start_mode) + { + sim_hw_parse (sd, "/m68hc11/mode %s", cpu->cpu_start_mode); + } if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0) { sim_hw_parse (sd, "/m68hc11/m68hc11sio/reg 0x2b 0x5"); @@ -242,14 +235,16 @@ sim_hw_configure (SIM_DESC sd) { /* Allocate core external memory. */ sim_do_commandf (sd, "memory region 0x%lx@%d,0x%lx", - 0xC000, M6811_RAM_LEVEL, 0x4000); + 0x8000, M6811_RAM_LEVEL, 0x8000); sim_do_commandf (sd, "memory region 0x000@%d,0x8000", M6811_RAM_LEVEL); - sim_do_commandf (sd, "memory region 0x01000000@%d,0x100000", - M6811_RAM_LEVEL); - + if (cpu->bank_start < cpu->bank_end) + { + sim_do_commandf (sd, "memory region 0x%lx@%d,0x100000", + cpu->bank_virtual, M6811_RAM_LEVEL); + sim_hw_parse (sd, "/m68hc12/use_bank 1"); + } sim_hw_parse (sd, "/m68hc12/reg 0x0 0x3FF"); - sim_hw_parse (sd, "/m68hc12/use_bank 1"); } if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@1/reg")) @@ -294,19 +289,77 @@ sim_hw_configure (SIM_DESC sd) return 1; } +/* Get the memory bank parameters by looking at the global symbols + defined by the linker. */ static int -sim_prepare_for_program (SIM_DESC sd, struct _bfd* abfd) +sim_get_bank_parameters (SIM_DESC sd, bfd* abfd) { sim_cpu *cpu; + long symsize; + long symbol_count, i; + unsigned size; + asymbol** asymbols; + asymbol** current; cpu = STATE_CPU (sd, 0); - if (!sim_hw_configure (sd)) - return SIM_RC_FAIL; + symsize = bfd_get_symtab_upper_bound (abfd); + if (symsize < 0) + { + sim_io_eprintf (sd, "Cannot read symbols of program"); + return 0; + } + asymbols = (asymbol **) xmalloc (symsize); + symbol_count = bfd_canonicalize_symtab (abfd, asymbols); + if (symbol_count < 0) + { + sim_io_eprintf (sd, "Cannot read symbols of program"); + return 0; + } + + size = 0; + for (i = 0, current = asymbols; i < symbol_count; i++, current++) + { + const char* name = bfd_asymbol_name (*current); + + if (strcmp (name, BFD_M68HC11_BANK_START_NAME) == 0) + { + cpu->bank_start = bfd_asymbol_value (*current); + } + else if (strcmp (name, BFD_M68HC11_BANK_SIZE_NAME) == 0) + { + size = bfd_asymbol_value (*current); + } + else if (strcmp (name, BFD_M68HC11_BANK_VIRTUAL_NAME) == 0) + { + cpu->bank_virtual = bfd_asymbol_value (*current); + } + } + free (asymbols); + + cpu->bank_end = cpu->bank_start + size; + cpu->bank_shift = 0; + for (; size > 1; size >>= 1) + cpu->bank_shift++; + + return 0; +} + +static int +sim_prepare_for_program (SIM_DESC sd, bfd* abfd) +{ + sim_cpu *cpu; + int elf_flags = 0; + + cpu = STATE_CPU (sd, 0); if (abfd != NULL) { asection *s; + + if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) + elf_flags = elf_elfheader (abfd)->e_flags; + cpu->cpu_elf_start = bfd_get_start_address (abfd); /* See if any section sets the reset address */ cpu->cpu_use_elf_start = 1; @@ -316,7 +369,7 @@ sim_prepare_for_program (SIM_DESC sd, struct _bfd* abfd) { bfd_size_type size; - size = bfd_get_section_size_before_reloc (s); + size = bfd_get_section_size (s); if (size > 0) { bfd_vma lma; @@ -331,29 +384,58 @@ sim_prepare_for_program (SIM_DESC sd, struct _bfd* abfd) } } } + + if (elf_flags & E_M68HC12_BANKS) + { + if (sim_get_bank_parameters (sd, abfd) != 0) + sim_io_eprintf (sd, "Memory bank parameters are not initialized\n"); + } } + if (!sim_hw_configure (sd)) + return SIM_RC_FAIL; + /* reset all state information */ sim_board_reset (sd); return SIM_RC_OK; } +static sim_cia +m68hc11_pc_get (sim_cpu *cpu) +{ + return cpu_get_pc (cpu); +} + +static void +m68hc11_pc_set (sim_cpu *cpu, sim_cia pc) +{ + cpu_set_pc (cpu, pc); +} + +static int m68hc11_reg_fetch (SIM_CPU *, int, unsigned char *, int); +static int m68hc11_reg_store (SIM_CPU *, int, unsigned char *, int); + SIM_DESC sim_open (SIM_OPEN_KIND kind, host_callback *callback, - struct _bfd *abfd, char **argv) + bfd *abfd, char * const *argv) { + int i; SIM_DESC sd; sim_cpu *cpu; 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; + /* The cpu data is kept in a separately allocated chunk of memory. */ + if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK) + { + free_state (sd); + return 0; + } + + cpu = STATE_CPU (sd, 0); cpu_initialize (sd, cpu); @@ -363,9 +445,7 @@ sim_open (SIM_OPEN_KIND kind, host_callback *callback, 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. */ + /* The parser will print an error message for us, so we silently return. */ if (sim_parse_args (sd, argv) != SIM_RC_OK) { /* Uninstall the modules to avoid memory leaks, @@ -398,37 +478,24 @@ sim_open (SIM_OPEN_KIND kind, host_callback *callback, free_state (sd); return 0; } + if (sim_prepare_for_program (sd, abfd) != SIM_RC_OK) + { + free_state (sd); + return 0; + } - sim_hw_configure (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 */ - sim_state_free (sd); - return; -} + /* CPU specific initialization. */ + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + { + SIM_CPU *cpu = STATE_CPU (sd, i); -void -sim_set_profile (int n) -{ -} + CPU_REG_FETCH (cpu) = m68hc11_reg_fetch; + CPU_REG_STORE (cpu) = m68hc11_reg_store; + CPU_PC_FETCH (cpu) = m68hc11_pc_get; + CPU_PC_STORE (cpu) = m68hc11_pc_set; + } -void -sim_set_profile_size (int n) -{ + return sd; } /* Generic implementation of sim_engine_run that works within the @@ -456,13 +523,6 @@ sim_engine_run (SIM_DESC sd, } } -int -sim_trace (SIM_DESC sd) -{ - sim_resume (sd, 0, 0); - return 1; -} - void sim_info (SIM_DESC sd, int verbose) { @@ -486,28 +546,18 @@ sim_info (SIM_DESC sd, int verbose) } SIM_RC -sim_create_inferior (SIM_DESC sd, struct _bfd *abfd, - char **argv, char **env) +sim_create_inferior (SIM_DESC sd, struct bfd *abfd, + char * const *argv, char * const *env) { return sim_prepare_for_program (sd, abfd); } - -void -sim_set_callbacks (host_callback *p) -{ - /* m6811_callback = p; */ -} - - -int -sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length) +static int +m68hc11_reg_fetch (SIM_CPU *cpu, int rn, unsigned char *memory, int length) { - sim_cpu *cpu; uint16 val; int size = 2; - cpu = STATE_CPU (sd, 0); switch (rn) { case A_REGNUM: @@ -554,18 +604,22 @@ sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length) val = 0; break; } - memory[0] = val >> 8; - memory[1] = val & 0x0FF; + if (size == 1) + { + memory[0] = val; + } + else + { + memory[0] = val >> 8; + memory[1] = val & 0x0FF; + } return size; } -int -sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length) +static int +m68hc11_reg_store (SIM_CPU *cpu, int rn, unsigned char *memory, int length) { uint16 val; - sim_cpu *cpu; - - cpu = STATE_CPU (sd, 0); val = *memory++; if (length == 2) @@ -615,112 +669,3 @@ sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length) 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"; - sim_cpu *cpu; - - cpu = STATE_CPU (sd, 0); - /* 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, 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); - } - - /* If the architecture changed, re-configure. */ - if (STATE_ARCHITECTURE (sd) != cpu->cpu_configured_arch) - sim_hw_configure (sd); -} - -/* Halt the simulator after just one instruction */ - -static void -has_stepped (SIM_DESC sd, - void *data) -{ - ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); - sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP); -} - - -/* Generic resume - assumes the existance of sim_engine_run */ - -void -sim_resume (SIM_DESC sd, - int step, - int siggnal) -{ - sim_engine *engine = STATE_ENGINE (sd); - jmp_buf buf; - int jmpval; - - ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); - - /* we only want to be single stepping the simulator once */ - if (engine->stepper != NULL) - { - sim_events_deschedule (sd, engine->stepper); - engine->stepper = NULL; - } - sim_module_resume (sd); - - /* run/resume the simulator */ - engine->jmpbuf = &buf; - jmpval = setjmp (buf); - if (jmpval == sim_engine_start_jmpval - || jmpval == sim_engine_restart_jmpval) - { - int last_cpu_nr = sim_engine_last_cpu_nr (sd); - int next_cpu_nr = sim_engine_next_cpu_nr (sd); - int nr_cpus = sim_engine_nr_cpus (sd); - - sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus); - if (next_cpu_nr >= nr_cpus) - next_cpu_nr = 0; - - /* Only deliver the siggnal ]sic] the first time through - don't - re-deliver any siggnal during a restart. */ - if (jmpval == sim_engine_restart_jmpval) - siggnal = 0; - - /* Install the stepping event after having processed some - pending events. This is necessary for HC11/HC12 simulator - because the tick counter is incremented by the number of cycles - the instruction took. Some pending ticks to process can still - be recorded internally by the simulator and sim_events_preprocess - will handle them. If the stepping event is inserted before, - these pending ticks will raise the event and the simulator will - stop without having executed any instruction. */ - if (step) - engine->stepper = sim_events_schedule (sd, 0, has_stepped, sd); - -#ifdef SIM_CPU_EXCEPTION_RESUME - { - sim_cpu* cpu = STATE_CPU (sd, next_cpu_nr); - SIM_CPU_EXCEPTION_RESUME(sd, cpu, siggnal); - } -#endif - - sim_engine_run (sd, next_cpu_nr, nr_cpus, siggnal); - } - engine->jmpbuf = NULL; - - sim_module_suspend (sd); -}