1 /* Simulator for Xilinx MicroBlaze processor
2 Copyright 2009-2015 Free Software Foundation, Inc.
4 This file is part of GDB, the GNU debugger.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>. */
25 #include "gdb/callback.h"
26 #include "libiberty.h"
27 #include "gdb/remote-sim.h"
30 #include "sim-options.h"
32 #include "microblaze-dis.h"
34 #define target_big_endian (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
37 microblaze_extract_unsigned_integer (unsigned char *addr, int len)
41 unsigned char *startaddr = (unsigned char *)addr;
42 unsigned char *endaddr = startaddr + len;
44 if (len > (int) sizeof (unsigned long))
45 printf ("That operation is not available on integers of more than "
46 "%zu bytes.", sizeof (unsigned long));
48 /* Start at the most significant end of the integer, and work towards
49 the least significant. */
52 if (!target_big_endian)
54 for (p = endaddr; p > startaddr;)
55 retval = (retval << 8) | * -- p;
59 for (p = startaddr; p < endaddr;)
60 retval = (retval << 8) | * p ++;
67 microblaze_store_unsigned_integer (unsigned char *addr, int len,
71 unsigned char *startaddr = (unsigned char *)addr;
72 unsigned char *endaddr = startaddr + len;
74 if (!target_big_endian)
76 for (p = startaddr; p < endaddr;)
84 for (p = endaddr; p > startaddr;)
93 set_initial_gprs (SIM_CPU *cpu)
98 /* Set up machine just out of reset. */
102 /* Clean out the GPRs */
103 for (i = 0; i < 32; i++)
110 static int tracing = 0;
113 sim_engine_run (SIM_DESC sd,
114 int next_cpu_nr, /* ignore */
115 int nr_cpus, /* ignore */
116 int siggnal) /* ignore */
118 SIM_CPU *cpu = STATE_CPU (sd, 0);
121 enum microblaze_instr op;
133 short delay_slot_enable;
135 short num_delay_slot; /* UNUSED except as reqd parameter */
136 enum microblaze_instr_type insn_type;
144 /* Fetch the initial instructions that we'll decode. */
145 inst = MEM_RD_WORD (PC & 0xFFFFFFFC);
147 op = get_insn_microblaze (inst, &imm_unsigned, &insn_type,
150 if (op == invalid_inst)
151 fprintf (stderr, "Unknown instruction 0x%04x", inst);
154 fprintf (stderr, "%.4x: inst = %.4x ", PC, inst);
159 /* immword = IMM_W; */
162 delay_slot_enable = 0;
164 if (op == microblaze_brk)
165 sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
166 else if (inst == MICROBLAZE_HALT_INST)
170 sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_exited, RETREG);
176 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
180 #include "microblaze.isa"
184 sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_signalled,
186 fprintf (stderr, "ERROR: Unknown opcode\n");
188 /* Make R0 consistent */
191 /* Check for imm instr */
197 /* Update cycle counts */
199 if (insn_type == memory_store_inst || insn_type == memory_load_inst)
201 if (insn_type == mult_inst)
203 if (insn_type == barrel_shift_inst)
205 if (insn_type == anyware_inst)
207 if (insn_type == div_inst)
210 if ((insn_type == branch_inst || insn_type == return_inst)
213 /* Add an extra cycle for taken branches */
215 /* For branch instructions handle the instruction in the delay slot */
216 if (delay_slot_enable)
219 PC = oldpc + INST_SIZE;
220 inst = MEM_RD_WORD (PC & 0xFFFFFFFC);
221 op = get_insn_microblaze (inst, &imm_unsigned, &insn_type,
223 if (op == invalid_inst)
224 fprintf (stderr, "Unknown instruction 0x%04x", inst);
226 fprintf (stderr, "%.4x: inst = %.4x ", PC, inst);
230 /* immword = IMM_W; */
231 if (op == microblaze_brk)
233 if (STATE_VERBOSE_P (sd))
234 fprintf (stderr, "Breakpoint set in delay slot "
235 "(at address 0x%x) will not be honored\n", PC);
236 /* ignore the breakpoint */
238 else if (insn_type == branch_inst || insn_type == return_inst)
240 if (STATE_VERBOSE_P (sd))
241 fprintf (stderr, "Cannot have branch or return instructions "
242 "in delay slot (at address 0x%x)\n", PC);
243 sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_signalled,
250 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
254 #include "microblaze.isa"
258 sim_engine_halt (sd, NULL, NULL, NULL_CIA,
259 sim_signalled, SIM_SIGILL);
260 fprintf (stderr, "ERROR: Unknown opcode at 0x%x\n", PC);
262 /* Update cycle counts */
264 if (insn_type == memory_store_inst
265 || insn_type == memory_load_inst)
267 if (insn_type == mult_inst)
269 if (insn_type == barrel_shift_inst)
271 if (insn_type == anyware_inst)
273 if (insn_type == div_inst)
278 /* Make R0 consistent */
280 /* Check for imm instr */
287 /* no delay slot: increment cycle count */
293 fprintf (stderr, "\n");
295 if (sim_events_tick (sd))
296 sim_events_process (sd);
299 /* Hide away the things we've cached while executing. */
301 CPU.insts += insts; /* instructions done ... */
302 CPU.cycles += insts; /* and each takes a cycle */
303 CPU.cycles += bonus_cycles; /* and extra cycles for branches */
304 CPU.cycles += memops; /* and memop cycle delays */
308 sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
310 SIM_CPU *cpu = STATE_CPU (sd, 0);
312 if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
316 /* misalignment safe */
317 long ival = microblaze_extract_unsigned_integer (memory, 4);
321 CPU.spregs[rn-NUM_REGS] = ival;
332 sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
334 SIM_CPU *cpu = STATE_CPU (sd, 0);
337 if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
344 ival = CPU.spregs[rn-NUM_REGS];
346 /* misalignment-safe */
347 microblaze_store_unsigned_integer (memory, 4, ival);
358 sim_info (SIM_DESC sd, int verbose)
360 SIM_CPU *cpu = STATE_CPU (sd, 0);
361 host_callback *callback = STATE_CALLBACK (sd);
363 callback->printf_filtered (callback, "\n\n# instructions executed %10d\n",
365 callback->printf_filtered (callback, "# cycles %10d\n",
366 (CPU.cycles) ? CPU.cycles+2 : 0);
370 microblaze_pc_get (sim_cpu *cpu)
372 return cpu->microblaze_cpu.spregs[0];
376 microblaze_pc_set (sim_cpu *cpu, sim_cia pc)
378 cpu->microblaze_cpu.spregs[0] = pc;
382 free_state (SIM_DESC sd)
384 if (STATE_MODULES (sd) != NULL)
385 sim_module_uninstall (sd);
386 sim_cpu_free_all (sd);
391 sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv)
394 SIM_DESC sd = sim_state_alloc (kind, cb);
395 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
397 /* The cpu data is kept in a separately allocated chunk of memory. */
398 if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
404 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
410 /* getopt will print the error message so we just have to exit if this fails.
411 FIXME: Hmmm... in the case of gdb we need getopt to call
413 if (sim_parse_args (sd, argv) != SIM_RC_OK)
419 /* Check for/establish the a reference program image. */
420 if (sim_analyze_program (sd,
421 (STATE_PROG_ARGV (sd) != NULL
422 ? *STATE_PROG_ARGV (sd)
423 : NULL), abfd) != SIM_RC_OK)
429 /* Configure/verify the target byte order and other runtime
430 configuration options. */
431 if (sim_config (sd) != SIM_RC_OK)
433 sim_module_uninstall (sd);
437 if (sim_post_argv_init (sd) != SIM_RC_OK)
439 /* Uninstall the modules to avoid memory leaks,
440 file descriptor leaks, etc. */
441 sim_module_uninstall (sd);
445 /* CPU specific initialization. */
446 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
448 SIM_CPU *cpu = STATE_CPU (sd, i);
450 CPU_PC_FETCH (cpu) = microblaze_pc_get;
451 CPU_PC_STORE (cpu) = microblaze_pc_set;
453 set_initial_gprs (cpu);
456 /* Default to a 8 Mbyte (== 2^23) memory space. */
457 sim_do_commandf (sd, "memory-size 0x800000");
463 sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env)
465 SIM_CPU *cpu = STATE_CPU (sd, 0);
467 PC = bfd_get_start_address (prog_bfd);