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_resume (SIM_DESC sd
, int step
, int siggnal
)
115 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
118 enum microblaze_instr op
;
130 short delay_slot_enable
;
132 short num_delay_slot
; /* UNUSED except as reqd parameter */
133 enum microblaze_instr_type insn_type
;
135 CPU
.exception
= step
? SIGTRAP
: 0;
143 /* Fetch the initial instructions that we'll decode. */
144 inst
= MEM_RD_WORD (PC
& 0xFFFFFFFC);
146 op
= get_insn_microblaze (inst
, &imm_unsigned
, &insn_type
,
149 if (op
== invalid_inst
)
150 fprintf (stderr
, "Unknown instruction 0x%04x", inst
);
153 fprintf (stderr
, "%.4x: inst = %.4x ", PC
, inst
);
158 /* immword = IMM_W; */
161 delay_slot_enable
= 0;
163 if (op
== microblaze_brk
)
164 CPU
.exception
= SIGTRAP
;
165 else if (inst
== MICROBLAZE_HALT_INST
)
167 CPU
.exception
= SIGQUIT
;
175 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
179 #include "microblaze.isa"
183 CPU
.exception
= SIGILL
;
184 fprintf (stderr
, "ERROR: Unknown opcode\n");
186 /* Make R0 consistent */
189 /* Check for imm instr */
195 /* Update cycle counts */
197 if (insn_type
== memory_store_inst
|| insn_type
== memory_load_inst
)
199 if (insn_type
== mult_inst
)
201 if (insn_type
== barrel_shift_inst
)
203 if (insn_type
== anyware_inst
)
205 if (insn_type
== div_inst
)
208 if ((insn_type
== branch_inst
|| insn_type
== return_inst
)
211 /* Add an extra cycle for taken branches */
213 /* For branch instructions handle the instruction in the delay slot */
214 if (delay_slot_enable
)
217 PC
= oldpc
+ INST_SIZE
;
218 inst
= MEM_RD_WORD (PC
& 0xFFFFFFFC);
219 op
= get_insn_microblaze (inst
, &imm_unsigned
, &insn_type
,
221 if (op
== invalid_inst
)
222 fprintf (stderr
, "Unknown instruction 0x%04x", inst
);
224 fprintf (stderr
, "%.4x: inst = %.4x ", PC
, inst
);
228 /* immword = IMM_W; */
229 if (op
== microblaze_brk
)
231 if (STATE_VERBOSE_P (sd
))
232 fprintf (stderr
, "Breakpoint set in delay slot "
233 "(at address 0x%x) will not be honored\n", PC
);
234 /* ignore the breakpoint */
236 else if (insn_type
== branch_inst
|| insn_type
== return_inst
)
238 if (STATE_VERBOSE_P (sd
))
239 fprintf (stderr
, "Cannot have branch or return instructions "
240 "in delay slot (at address 0x%x)\n", PC
);
241 CPU
.exception
= SIGILL
;
247 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
251 #include "microblaze.isa"
255 CPU
.exception
= SIGILL
;
256 fprintf (stderr
, "ERROR: Unknown opcode at 0x%x\n", PC
);
258 /* Update cycle counts */
260 if (insn_type
== memory_store_inst
261 || insn_type
== memory_load_inst
)
263 if (insn_type
== mult_inst
)
265 if (insn_type
== barrel_shift_inst
)
267 if (insn_type
== anyware_inst
)
269 if (insn_type
== div_inst
)
274 /* Make R0 consistent */
276 /* Check for imm instr */
283 /* no delay slot: increment cycle count */
289 fprintf (stderr
, "\n");
291 while (!CPU
.exception
);
293 /* Hide away the things we've cached while executing. */
295 CPU
.insts
+= insts
; /* instructions done ... */
296 CPU
.cycles
+= insts
; /* and each takes a cycle */
297 CPU
.cycles
+= bonus_cycles
; /* and extra cycles for branches */
298 CPU
.cycles
+= memops
; /* and memop cycle delays */
302 sim_store_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
304 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
306 if (rn
< NUM_REGS
+ NUM_SPECIAL
&& rn
>= 0)
310 /* misalignment safe */
311 long ival
= microblaze_extract_unsigned_integer (memory
, 4);
315 CPU
.spregs
[rn
-NUM_REGS
] = ival
;
326 sim_fetch_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
328 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
331 if (rn
< NUM_REGS
+ NUM_SPECIAL
&& rn
>= 0)
338 ival
= CPU
.spregs
[rn
-NUM_REGS
];
340 /* misalignment-safe */
341 microblaze_store_unsigned_integer (memory
, 4, ival
);
352 sim_stop_reason (SIM_DESC sd
, enum sim_stop
*reason
, int *sigrc
)
354 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
356 if (CPU
.exception
== SIGQUIT
)
358 *reason
= sim_exited
;
363 *reason
= sim_stopped
;
364 *sigrc
= CPU
.exception
;
369 sim_info (SIM_DESC sd
, int verbose
)
371 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
372 host_callback
*callback
= STATE_CALLBACK (sd
);
374 callback
->printf_filtered (callback
, "\n\n# instructions executed %10d\n",
376 callback
->printf_filtered (callback
, "# cycles %10d\n",
377 (CPU
.cycles
) ? CPU
.cycles
+2 : 0);
381 microblaze_pc_get (sim_cpu
*cpu
)
383 return cpu
->microblaze_cpu
.spregs
[0];
387 microblaze_pc_set (sim_cpu
*cpu
, sim_cia pc
)
389 cpu
->microblaze_cpu
.spregs
[0] = pc
;
393 free_state (SIM_DESC sd
)
395 if (STATE_MODULES (sd
) != NULL
)
396 sim_module_uninstall (sd
);
397 sim_cpu_free_all (sd
);
402 sim_open (SIM_OPEN_KIND kind
, host_callback
*cb
, struct bfd
*abfd
, char **argv
)
405 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
406 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
408 /* The cpu data is kept in a separately allocated chunk of memory. */
409 if (sim_cpu_alloc_all (sd
, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK
)
415 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
421 /* getopt will print the error message so we just have to exit if this fails.
422 FIXME: Hmmm... in the case of gdb we need getopt to call
424 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
430 /* Check for/establish the a reference program image. */
431 if (sim_analyze_program (sd
,
432 (STATE_PROG_ARGV (sd
) != NULL
433 ? *STATE_PROG_ARGV (sd
)
434 : NULL
), abfd
) != SIM_RC_OK
)
440 /* Configure/verify the target byte order and other runtime
441 configuration options. */
442 if (sim_config (sd
) != SIM_RC_OK
)
444 sim_module_uninstall (sd
);
448 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
450 /* Uninstall the modules to avoid memory leaks,
451 file descriptor leaks, etc. */
452 sim_module_uninstall (sd
);
456 /* CPU specific initialization. */
457 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
459 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
461 CPU_PC_FETCH (cpu
) = microblaze_pc_get
;
462 CPU_PC_STORE (cpu
) = microblaze_pc_set
;
464 set_initial_gprs (cpu
);
467 /* Default to a 8 Mbyte (== 2^23) memory space. */
468 sim_do_commandf (sd
, "memory-size 0x800000");
474 sim_close (SIM_DESC sd
, int quitting
)
480 sim_create_inferior (SIM_DESC sd
, struct bfd
*prog_bfd
, char **argv
, char **env
)
482 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
484 PC
= bfd_get_start_address (prog_bfd
);