/* Simulator for Xilinx MicroBlaze processor
- Copyright 2009-2015 Free Software Foundation, Inc.
+ Copyright 2009-2021 Free Software Foundation, Inc.
This file is part of GDB, the GNU debugger.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>. */
-#include "config.h"
+/* This must come before any other includes. */
+#include "defs.h"
+
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "bfd.h"
-#include "gdb/callback.h"
+#include "sim/callback.h"
#include "libiberty.h"
-#include "gdb/remote-sim.h"
+#include "sim/sim.h"
#include "sim-main.h"
#include "sim-options.h"
+#include "sim-signal.h"
+#include "sim-syscall.h"
#include "microblaze-dis.h"
-#define target_big_endian (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
+#define target_big_endian (CURRENT_TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
static unsigned long
microblaze_extract_unsigned_integer (unsigned char *addr, int len)
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;
int cycs;
word WLhash;
ubyte carry;
- int imm_unsigned;
+ bool imm_unsigned;
short ra, rb, rd;
long immword;
uword oldpc, newpc;
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 = MEM_RD_WORD (PC & 0xFFFFFFFC);
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++;
+ TRACE_INSN (cpu, "HALT (%i)", RETREG);
+ sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_exited, RETREG);
}
else
{
{
#define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
case NAME: \
+ TRACE_INSN (cpu, #NAME); \
ACTION; \
break;
#include "microblaze.isa"
#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 */
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
{
#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 */
IMM_ENABLE = 0;
}
else
- /* no delay slot: increment cycle count */
- bonus_cycles++;
+ {
+ if (op == brki && IMM == 8)
+ {
+ RETREG = sim_syscall (cpu, CPU.regs[12], CPU.regs[5],
+ CPU.regs[6], CPU.regs[7],
+ CPU.regs[8]);
+ PC = RD + INST_SIZE;
+ }
+
+ /* no delay slot: increment cycle count */
+ bonus_cycles++;
+ }
}
}
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; */
CPU.cycles += memops; /* and memop cycle delays */
}
-int
-sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
+static int
+microblaze_reg_store (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
{
- SIM_CPU *cpu = STATE_CPU (sd, 0);
-
if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
{
if (length == 4)
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)
{
- SIM_CPU *cpu = STATE_CPU (sd, 0);
long ival;
if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
return 0;
}
-void
-sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
-{
- SIM_CPU *cpu = STATE_CPU (sd, 0);
-
- if (CPU.exception == SIGQUIT)
- {
- *reason = sim_exited;
- *sigrc = RETREG;
- }
- else
- {
- *reason = sim_stopped;
- *sigrc = CPU.exception;
- }
-}
-
void
sim_info (SIM_DESC sd, int verbose)
{
}
SIM_DESC
-sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv)
+sim_open (SIM_OPEN_KIND kind, host_callback *cb,
+ struct bfd *abfd, char * const *argv)
{
int i;
SIM_DESC sd = sim_state_alloc (kind, cb);
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
/* 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)
+ if (sim_cpu_alloc_all (sd, 1) != SIM_RC_OK)
{
free_state (sd);
return 0;
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)
{
free_state (sd);
{
SIM_CPU *cpu = STATE_CPU (sd, i);
+ 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;
return sd;
}
-void
-sim_close (SIM_DESC sd, int quitting)
-{
- /* Do nothing. */
-}
-
SIM_RC
-sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env)
+sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
+ char * const *argv, char * const *env)
{
SIM_CPU *cpu = STATE_CPU (sd, 0);