X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fmicroblaze%2Finterp.c;h=be541347495622ec45c857452034278086383bc7;hb=41792d688a5a1f158d6e9ecda2b603ae122d69a1;hp=4e64932c3bf3c842ae7deebcc41088a57a811b2b;hpb=191ec03314b005b8189ecea7296f2f6cad534d09;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/microblaze/interp.c b/sim/microblaze/interp.c index 4e64932c3b..be54134749 100644 --- a/sim/microblaze/interp.c +++ b/sim/microblaze/interp.c @@ -1,5 +1,5 @@ /* Simulator for Xilinx MicroBlaze processor - Copyright 2009-2015 Free Software Foundation, Inc. + Copyright 2009-2020 Free Software Foundation, Inc. This file is part of GDB, the GNU debugger. @@ -20,27 +20,18 @@ #include #include #include -#include -#include #include #include "bfd.h" #include "gdb/callback.h" #include "libiberty.h" #include "gdb/remote-sim.h" -#include "run-sim.h" -#include "sim-main.h" -#include "sim-utils.h" -#include "microblaze-dis.h" +#include "sim-main.h" +#include "sim-options.h" -#ifndef NUM_ELEM -#define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0]) -#endif +#include "microblaze-dis.h" -static int target_big_endian = 1; -static unsigned long heap_ptr = 0; -static unsigned long stack_ptr = 0; -host_callback *callback; +#define target_big_endian (CURRENT_TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) static unsigned long microblaze_extract_unsigned_integer (unsigned char *addr, int len) @@ -98,245 +89,16 @@ microblaze_store_unsigned_integer (unsigned char *addr, int len, } } -struct sim_state microblaze_state; - -int memcycles = 1; - -static SIM_OPEN_KIND sim_kind; -static char *myname; - -static int issue_messages = 0; - -static void /* INLINE */ -wbat (word x, word v) -{ - if (((uword)x) >= CPU.msize) - { - if (issue_messages) - fprintf (stderr, "byte write to 0x%x outside memory range\n", x); - - CPU.exception = SIGSEGV; - } - else - { - unsigned char *p = CPU.memory + x; - p[0] = v; - } -} - -static void /* INLINE */ -wlat (word x, word v) -{ - if (((uword)x) >= CPU.msize) - { - if (issue_messages) - fprintf (stderr, "word write to 0x%x outside memory range\n", x); - - CPU.exception = SIGSEGV; - } - else - { - if ((x & 3) != 0) - { - if (issue_messages) - fprintf (stderr, "word write to unaligned memory address: 0x%x\n", x); - - CPU.exception = SIGBUS; - } - else if (!target_big_endian) - { - unsigned char *p = CPU.memory + x; - p[3] = v >> 24; - p[2] = v >> 16; - p[1] = v >> 8; - p[0] = v; - } - else - { - unsigned char *p = CPU.memory + x; - p[0] = v >> 24; - p[1] = v >> 16; - p[2] = v >> 8; - p[3] = v; - } - } -} - -static void /* INLINE */ -what (word x, word v) -{ - if (((uword)x) >= CPU.msize) - { - if (issue_messages) - fprintf (stderr, "short write to 0x%x outside memory range\n", x); - - CPU.exception = SIGSEGV; - } - else - { - if ((x & 1) != 0) - { - if (issue_messages) - fprintf (stderr, "short write to unaligned memory address: 0x%x\n", - x); - - CPU.exception = SIGBUS; - } - else if (!target_big_endian) - { - unsigned char *p = CPU.memory + x; - p[1] = v >> 8; - p[0] = v; - } - else - { - unsigned char *p = CPU.memory + x; - p[0] = v >> 8; - p[1] = v; - } - } -} - -/* Read functions. */ -static int /* INLINE */ -rbat (word x) -{ - if (((uword)x) >= CPU.msize) - { - if (issue_messages) - fprintf (stderr, "byte read from 0x%x outside memory range\n", x); - - CPU.exception = SIGSEGV; - return 0; - } - else - { - unsigned char *p = CPU.memory + x; - return p[0]; - } -} - -static int /* INLINE */ -rlat (word x) -{ - if (((uword) x) >= CPU.msize) - { - if (issue_messages) - fprintf (stderr, "word read from 0x%x outside memory range\n", x); - - CPU.exception = SIGSEGV; - return 0; - } - else - { - if ((x & 3) != 0) - { - if (issue_messages) - fprintf (stderr, "word read from unaligned address: 0x%x\n", x); - - CPU.exception = SIGBUS; - return 0; - } - else if (! target_big_endian) - { - unsigned char *p = CPU.memory + x; - return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]; - } - else - { - unsigned char *p = CPU.memory + x; - return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; - } - } -} - -static int /* INLINE */ -rhat (word x) -{ - if (((uword)x) >= CPU.msize) - { - if (issue_messages) - fprintf (stderr, "short read from 0x%x outside memory range\n", x); - - CPU.exception = SIGSEGV; - return 0; - } - else - { - if ((x & 1) != 0) - { - if (issue_messages) - fprintf (stderr, "short read from unaligned address: 0x%x\n", x); - - CPU.exception = SIGBUS; - return 0; - } - else if (!target_big_endian) - { - unsigned char *p = CPU.memory + x; - return (p[1] << 8) | p[0]; - } - else - { - unsigned char *p = CPU.memory + x; - return (p[0] << 8) | p[1]; - } - } -} - -/* Default to a 8 Mbyte (== 2^23) memory space. */ -static int sim_memory_size = 1 << 23; - -#define MEM_SIZE_FLOOR 64 -void -sim_size (int size) -{ - sim_memory_size = size; - CPU.msize = sim_memory_size; - - if (CPU.memory) - free (CPU.memory); - - CPU.memory = (unsigned char *) calloc (1, CPU.msize); - - if (!CPU.memory) - { - if (issue_messages) - fprintf (stderr, - "Not enough VM for simulation of %ld bytes of RAM\n", - CPU.msize); - - CPU.msize = 1; - CPU.memory = (unsigned char *) calloc (1, 1); - } -} - -static void -init_pointers (void) -{ - if (CPU.msize != (sim_memory_size)) - sim_size (sim_memory_size); -} - static void -set_initial_gprs (void) +set_initial_gprs (SIM_CPU *cpu) { int i; long space; - unsigned long memsize; - - init_pointers (); /* Set up machine just out of reset. */ PC = 0; MSR = 0; - memsize = CPU.msize / (1024 * 1024); - - if (issue_messages > 1) - fprintf (stderr, "Simulated memory of %ld Mbytes (0x0 .. 0x%08lx)\n", - memsize, CPU.msize - 1); - /* Clean out the GPRs */ for (i = 0; i < 32; i++) CPU.regs[i] = 0; @@ -345,29 +107,15 @@ set_initial_gprs (void) CPU.imm_enable = 0; } -#define WATCHFUNCTIONS 1 -#ifdef WATCHFUNCTIONS - -#define MAXWL 80 -word WL[MAXWL]; -char *WLstr[MAXWL]; - -int ENDWL=0; -int WLincyc; -int WLcyc[MAXWL]; -int WLcnts[MAXWL]; -int WLmax[MAXWL]; -int WLmin[MAXWL]; -word WLendpc; -int WLbcyc; -int WLW; -#endif - static int tracing = 0; void -sim_resume (SIM_DESC sd, int step, int siggnal) +sim_engine_run (SIM_DESC sd, + int next_cpu_nr, /* ignore */ + int nr_cpus, /* ignore */ + int siggnal) /* ignore */ { + SIM_CPU *cpu = STATE_CPU (sd, 0); int needfetch; word inst; enum microblaze_instr op; @@ -387,16 +135,14 @@ sim_resume (SIM_DESC sd, int step, int siggnal) short num_delay_slot; /* UNUSED except as reqd parameter */ enum microblaze_instr_type insn_type; - CPU.exception = step ? SIGTRAP : 0; - memops = 0; bonus_cycles = 0; insts = 0; - do + while (1) { /* Fetch the initial instructions that we'll decode. */ - inst = rlat (PC & 0xFFFFFFFC); + inst = MEM_RD_WORD (PC & 0xFFFFFFFC); op = get_insn_microblaze (inst, &imm_unsigned, &insn_type, &num_delay_slot); @@ -416,12 +162,12 @@ sim_resume (SIM_DESC sd, int step, int siggnal) delay_slot_enable = 0; branch_taken = 0; if (op == microblaze_brk) - CPU.exception = SIGTRAP; + sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP); else if (inst == MICROBLAZE_HALT_INST) { - CPU.exception = SIGQUIT; insts += 1; bonus_cycles++; + sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_exited, RETREG); } else { @@ -435,7 +181,8 @@ sim_resume (SIM_DESC sd, int step, int siggnal) #undef INSTRUCTION default: - CPU.exception = SIGILL; + sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_signalled, + SIM_SIGILL); fprintf (stderr, "ERROR: Unknown opcode\n"); } /* Make R0 consistent */ @@ -470,7 +217,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal) { newpc = PC; PC = oldpc + INST_SIZE; - inst = rlat (PC & 0xFFFFFFFC); + inst = MEM_RD_WORD (PC & 0xFFFFFFFC); op = get_insn_microblaze (inst, &imm_unsigned, &insn_type, &num_delay_slot); if (op == invalid_inst) @@ -483,17 +230,18 @@ sim_resume (SIM_DESC sd, int step, int siggnal) /* immword = IMM_W; */ if (op == microblaze_brk) { - if (issue_messages) + if (STATE_VERBOSE_P (sd)) fprintf (stderr, "Breakpoint set in delay slot " "(at address 0x%x) will not be honored\n", PC); /* ignore the breakpoint */ } else if (insn_type == branch_inst || insn_type == return_inst) { - if (issue_messages) + if (STATE_VERBOSE_P (sd)) fprintf (stderr, "Cannot have branch or return instructions " "in delay slot (at address 0x%x)\n", PC); - CPU.exception = SIGILL; + sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_signalled, + SIM_SIGILL); } else { @@ -507,7 +255,8 @@ sim_resume (SIM_DESC sd, int step, int siggnal) #undef INSTRUCTION default: - CPU.exception = SIGILL; + sim_engine_halt (sd, NULL, NULL, NULL_CIA, + sim_signalled, SIM_SIGILL); fprintf (stderr, "ERROR: Unknown opcode at 0x%x\n", PC); } /* Update cycle counts */ @@ -542,8 +291,10 @@ sim_resume (SIM_DESC sd, int step, int siggnal) if (tracing) fprintf (stderr, "\n"); + + if (sim_events_tick (sd)) + sim_events_process (sd); } - while (!CPU.exception); /* Hide away the things we've cached while executing. */ /* CPU.pc = pc; */ @@ -553,35 +304,9 @@ sim_resume (SIM_DESC sd, int step, int siggnal) CPU.cycles += memops; /* and memop cycle delays */ } - -int -sim_write (SIM_DESC sd, SIM_ADDR addr, const unsigned char *buffer, int size) +static int +microblaze_reg_store (SIM_CPU *cpu, int rn, unsigned char *memory, int length) { - int i; - init_pointers (); - - memcpy (&CPU.memory[addr], buffer, size); - - return size; -} - -int -sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size) -{ - int i; - init_pointers (); - - memcpy (buffer, &CPU.memory[addr], size); - - return size; -} - - -int -sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length) -{ - init_pointers (); - if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0) { if (length == 4) @@ -601,11 +326,10 @@ sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length) return 0; } -int -sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length) +static int +microblaze_reg_fetch (SIM_CPU *cpu, int rn, unsigned char *memory, int length) { long ival; - init_pointers (); if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0) { @@ -627,319 +351,119 @@ sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length) return 0; } - -int -sim_trace (SIM_DESC sd) -{ - tracing = 1; - - sim_resume (sd, 0, 0); - - tracing = 0; - - return 1; -} - -void -sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc) -{ - if (CPU.exception == SIGQUIT) - { - *reason = sim_exited; - *sigrc = RETREG; - } - else - { - *reason = sim_stopped; - *sigrc = CPU.exception; - } -} - - -int -sim_stop (SIM_DESC sd) -{ - CPU.exception = SIGINT; - return 1; -} - - void sim_info (SIM_DESC sd, int verbose) { -#ifdef WATCHFUNCTIONS - int w, wcyc; -#endif + SIM_CPU *cpu = STATE_CPU (sd, 0); + host_callback *callback = STATE_CALLBACK (sd); callback->printf_filtered (callback, "\n\n# instructions executed %10d\n", CPU.insts); callback->printf_filtered (callback, "# cycles %10d\n", (CPU.cycles) ? CPU.cycles+2 : 0); - -#ifdef WATCHFUNCTIONS - callback->printf_filtered (callback, "\nNumber of watched functions: %d\n", - ENDWL); - - wcyc = 0; - - for (w = 1; w <= ENDWL; w++) - { - callback->printf_filtered (callback, "WL = %s %8x\n",WLstr[w],WL[w]); - callback->printf_filtered (callback, " calls = %d, cycles = %d\n", - WLcnts[w],WLcyc[w]); - - if (WLcnts[w] != 0) - callback->printf_filtered (callback, - " maxcpc = %d, mincpc = %d, avecpc = %d\n", - WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]); - wcyc += WLcyc[w]; - } - - callback->printf_filtered (callback, - "Total cycles for watched functions: %d\n",wcyc); -#endif } -struct aout -{ - unsigned char sa_machtype[2]; - unsigned char sa_magic[2]; - unsigned char sa_tsize[4]; - unsigned char sa_dsize[4]; - unsigned char sa_bsize[4]; - unsigned char sa_syms[4]; - unsigned char sa_entry[4]; - unsigned char sa_trelo[4]; - unsigned char sa_drelo[4]; -} aout; - -#define LONG(x) (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) -#define SHORT(x) (((x)[0]<<8)|(x)[1]) - -SIM_DESC -sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv) +static sim_cia +microblaze_pc_get (sim_cpu *cpu) { - /* SIM_DESC sd = sim_state_alloc(kind, alloc);*/ - - int osize = sim_memory_size; - myname = argv[0]; - callback = cb; - - if (kind == SIM_OPEN_STANDALONE) - issue_messages = 1; - - /* Discard and reacquire memory -- start with a clean slate. */ - sim_size (1); /* small */ - sim_size (osize); /* and back again */ - - set_initial_gprs (); /* Reset the GPR registers. */ - - return ((SIM_DESC) 1); + return cpu->microblaze_cpu.spregs[0]; } -void -sim_close (SIM_DESC sd, int quitting) +static void +microblaze_pc_set (sim_cpu *cpu, sim_cia pc) { - if (CPU.memory) - { - free(CPU.memory); - CPU.memory = NULL; - CPU.msize = 0; - } + cpu->microblaze_cpu.spregs[0] = pc; } -SIM_RC -sim_load (SIM_DESC sd, const char *prog, bfd *abfd, int from_tty) +static void +free_state (SIM_DESC sd) { - /* Do the right thing for ELF executables; this turns out to be - just about the right thing for any object format that: - - we crack using BFD routines - - follows the traditional UNIX text/data/bss layout - - calls the bss section ".bss". */ - - extern bfd *sim_load_file (); /* ??? Don't know where this should live. */ - bfd *prog_bfd; - - { - bfd *handle; - asection *s; - int found_loadable_section = 0; - bfd_vma max_addr = 0; - handle = bfd_openr (prog, 0); - - if (!handle) - { - printf("``%s'' could not be opened.\n", prog); - return SIM_RC_FAIL; - } - - /* Makes sure that we have an object file, also cleans gets the - section headers in place. */ - if (!bfd_check_format (handle, bfd_object)) - { - /* wasn't an object file */ - bfd_close (handle); - printf ("``%s'' is not appropriate object file.\n", prog); - return SIM_RC_FAIL; - } - - for (s = handle->sections; s; s = s->next) - { - if (s->flags & SEC_ALLOC) - { - bfd_vma vma = 0; - int size = bfd_get_section_size (s); - if (size > 0) - { - vma = bfd_section_vma (handle, s); - if (vma >= max_addr) - { - max_addr = vma + size; - } - } - if (s->flags & SEC_LOAD) - found_loadable_section = 1; - } - } - - if (!found_loadable_section) - { - /* No loadable sections */ - bfd_close(handle); - printf("No loadable sections in file %s\n", prog); - return SIM_RC_FAIL; - } - - sim_memory_size = (unsigned long) max_addr; - - /* Clean up after ourselves. */ - bfd_close (handle); - - } - - /* from sh -- dac */ - prog_bfd = sim_load_file (sd, myname, callback, prog, abfd, - /* sim_kind == SIM_OPEN_DEBUG, */ - 0, - 0, sim_write); - if (prog_bfd == NULL) - return SIM_RC_FAIL; - - target_big_endian = bfd_big_endian (prog_bfd); - PC = bfd_get_start_address (prog_bfd); - - if (abfd == NULL) - bfd_close (prog_bfd); - - return SIM_RC_OK; + if (STATE_MODULES (sd) != NULL) + sim_module_uninstall (sd); + sim_cpu_free_all (sd); + sim_state_free (sd); } -SIM_RC -sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env) +SIM_DESC +sim_open (SIM_OPEN_KIND kind, host_callback *cb, + struct bfd *abfd, char * const *argv) { - char **avp; - int nargs = 0; - int nenv = 0; - int s_length; - int l; - unsigned long strings; - unsigned long pointers; - unsigned long hi_stack; - - - /* Set the initial register set. */ - l = issue_messages; - issue_messages = 0; - set_initial_gprs (); - issue_messages = l; - - hi_stack = CPU.msize - 4; - PC = bfd_get_start_address (prog_bfd); - - /* For now ignore all parameters to the program */ - - return SIM_RC_OK; -} + int i; + SIM_DESC sd = sim_state_alloc (kind, cb); + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); -void -sim_do_command (SIM_DESC sd, const char *cmd) -{ - /* Nothing there yet; it's all an error. */ + /* 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; + } - if (cmd != NULL) + if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) { - char ** simargv = buildargv (cmd); + free_state (sd); + return 0; + } - if (strcmp (simargv[0], "watch") == 0) - { - if ((simargv[1] == NULL) || (simargv[2] == NULL)) - { - fprintf (stderr, "Error: missing argument to watch cmd.\n"); - freeargv (simargv); - return; - } + /* The parser will print an error message for us, so we silently return. */ + if (sim_parse_args (sd, argv) != SIM_RC_OK) + { + free_state (sd); + return 0; + } - ENDWL++; + /* 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) + { + free_state (sd); + return 0; + } - WL[ENDWL] = strtol (simargv[2], NULL, 0); - WLstr[ENDWL] = strdup (simargv[1]); - fprintf (stderr, "Added %s (%x) to watchlist, #%d\n",WLstr[ENDWL], - WL[ENDWL], ENDWL); + /* Configure/verify the target byte order and other runtime + configuration options. */ + if (sim_config (sd) != SIM_RC_OK) + { + sim_module_uninstall (sd); + return 0; + } - } - else if (strcmp (simargv[0], "dumpmem") == 0) - { - unsigned char * p; - FILE * dumpfile; + 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 (simargv[1] == NULL) - fprintf (stderr, "Error: missing argument to dumpmem cmd.\n"); + /* CPU specific initialization. */ + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + { + SIM_CPU *cpu = STATE_CPU (sd, i); - fprintf (stderr, "Writing dumpfile %s...",simargv[1]); + CPU_REG_FETCH (cpu) = microblaze_reg_fetch; + CPU_REG_STORE (cpu) = microblaze_reg_store; + CPU_PC_FETCH (cpu) = microblaze_pc_get; + CPU_PC_STORE (cpu) = microblaze_pc_set; - dumpfile = fopen (simargv[1], "w"); - p = CPU.memory; - fwrite (p, CPU.msize-1, 1, dumpfile); - fclose (dumpfile); + set_initial_gprs (cpu); + } - fprintf (stderr, "done.\n"); - } - else if (strcmp (simargv[0], "clearstats") == 0) - { - CPU.cycles = 0; - CPU.insts = 0; - ENDWL = 0; - } - else if (strcmp (simargv[0], "verbose") == 0) - { - issue_messages = 2; - } - else - { - fprintf (stderr,"Error: \"%s\" is not a valid M.CORE simulator command.\n", - cmd); - } + /* Default to a 8 Mbyte (== 2^23) memory space. */ + sim_do_commandf (sd, "memory-size 0x800000"); - freeargv (simargv); - } - else - { - fprintf (stderr, "M.CORE sim commands: \n"); - fprintf (stderr, " watch \n"); - fprintf (stderr, " dumpmem \n"); - fprintf (stderr, " clearstats\n"); - fprintf (stderr, " verbose\n"); - } + return sd; } -void -sim_set_callbacks (host_callback *ptr) +SIM_RC +sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, + char * const *argv, char * const *env) { - callback = ptr; -} + SIM_CPU *cpu = STATE_CPU (sd, 0); -char ** -sim_complete_command (SIM_DESC sd, const char *text, const char *word) -{ - return NULL; + PC = bfd_get_start_address (prog_bfd); + + return SIM_RC_OK; }