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
;)
92 /* TODO: Convert to common tracing framework. */
93 static int issue_messages
= 0;
95 static void /* INLINE */
96 wbat (SIM_CPU
*cpu
, word x
, word v
)
98 if (((uword
)x
) >= CPU
.msize
)
101 fprintf (stderr
, "byte write to 0x%x outside memory range\n", x
);
103 CPU
.exception
= SIGSEGV
;
107 unsigned char *p
= CPU
.memory
+ x
;
112 static void /* INLINE */
113 wlat (SIM_CPU
*cpu
, word x
, word v
)
115 if (((uword
)x
) >= CPU
.msize
)
118 fprintf (stderr
, "word write to 0x%x outside memory range\n", x
);
120 CPU
.exception
= SIGSEGV
;
127 fprintf (stderr
, "word write to unaligned memory address: 0x%x\n", x
);
129 CPU
.exception
= SIGBUS
;
131 else if (!target_big_endian
)
133 unsigned char *p
= CPU
.memory
+ x
;
141 unsigned char *p
= CPU
.memory
+ x
;
150 static void /* INLINE */
151 what (SIM_CPU
*cpu
, word x
, word v
)
153 if (((uword
)x
) >= CPU
.msize
)
156 fprintf (stderr
, "short write to 0x%x outside memory range\n", x
);
158 CPU
.exception
= SIGSEGV
;
165 fprintf (stderr
, "short write to unaligned memory address: 0x%x\n",
168 CPU
.exception
= SIGBUS
;
170 else if (!target_big_endian
)
172 unsigned char *p
= CPU
.memory
+ x
;
178 unsigned char *p
= CPU
.memory
+ x
;
185 /* Read functions. */
186 static int /* INLINE */
187 rbat (SIM_CPU
*cpu
, word x
)
189 if (((uword
)x
) >= CPU
.msize
)
192 fprintf (stderr
, "byte read from 0x%x outside memory range\n", x
);
194 CPU
.exception
= SIGSEGV
;
199 unsigned char *p
= CPU
.memory
+ x
;
204 static int /* INLINE */
205 rlat (SIM_CPU
*cpu
, word x
)
207 if (((uword
) x
) >= CPU
.msize
)
210 fprintf (stderr
, "word read from 0x%x outside memory range\n", x
);
212 CPU
.exception
= SIGSEGV
;
220 fprintf (stderr
, "word read from unaligned address: 0x%x\n", x
);
222 CPU
.exception
= SIGBUS
;
225 else if (! target_big_endian
)
227 unsigned char *p
= CPU
.memory
+ x
;
228 return (p
[3] << 24) | (p
[2] << 16) | (p
[1] << 8) | p
[0];
232 unsigned char *p
= CPU
.memory
+ x
;
233 return (p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3];
238 static int /* INLINE */
239 rhat (SIM_CPU
*cpu
, word x
)
241 if (((uword
)x
) >= CPU
.msize
)
244 fprintf (stderr
, "short read from 0x%x outside memory range\n", x
);
246 CPU
.exception
= SIGSEGV
;
254 fprintf (stderr
, "short read from unaligned address: 0x%x\n", x
);
256 CPU
.exception
= SIGBUS
;
259 else if (!target_big_endian
)
261 unsigned char *p
= CPU
.memory
+ x
;
262 return (p
[1] << 8) | p
[0];
266 unsigned char *p
= CPU
.memory
+ x
;
267 return (p
[0] << 8) | p
[1];
272 /* TODO: Delete all sim_size and use common memory functions. */
273 /* Default to a 8 Mbyte (== 2^23) memory space. */
274 static int sim_memory_size
= 1 << 23;
276 #define MEM_SIZE_FLOOR 64
278 sim_size (SIM_CPU
*cpu
, int size
)
280 sim_memory_size
= size
;
281 CPU
.msize
= sim_memory_size
;
286 CPU
.memory
= (unsigned char *) calloc (1, CPU
.msize
);
292 "Not enough VM for simulation of %ld bytes of RAM\n",
296 CPU
.memory
= (unsigned char *) calloc (1, 1);
301 init_pointers (SIM_CPU
*cpu
)
303 if (CPU
.msize
!= (sim_memory_size
))
304 sim_size (cpu
, sim_memory_size
);
308 set_initial_gprs (SIM_CPU
*cpu
)
312 unsigned long memsize
;
316 /* Set up machine just out of reset. */
320 memsize
= CPU
.msize
/ (1024 * 1024);
322 if (issue_messages
> 1)
323 fprintf (stderr
, "Simulated memory of %ld Mbytes (0x0 .. 0x%08lx)\n",
324 memsize
, CPU
.msize
- 1);
326 /* Clean out the GPRs */
327 for (i
= 0; i
< 32; i
++)
334 static int tracing
= 0;
337 sim_resume (SIM_DESC sd
, int step
, int siggnal
)
339 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
342 enum microblaze_instr op
;
354 short delay_slot_enable
;
356 short num_delay_slot
; /* UNUSED except as reqd parameter */
357 enum microblaze_instr_type insn_type
;
359 CPU
.exception
= step
? SIGTRAP
: 0;
367 /* Fetch the initial instructions that we'll decode. */
368 inst
= rlat (cpu
, PC
& 0xFFFFFFFC);
370 op
= get_insn_microblaze (inst
, &imm_unsigned
, &insn_type
,
373 if (op
== invalid_inst
)
374 fprintf (stderr
, "Unknown instruction 0x%04x", inst
);
377 fprintf (stderr
, "%.4x: inst = %.4x ", PC
, inst
);
382 /* immword = IMM_W; */
385 delay_slot_enable
= 0;
387 if (op
== microblaze_brk
)
388 CPU
.exception
= SIGTRAP
;
389 else if (inst
== MICROBLAZE_HALT_INST
)
391 CPU
.exception
= SIGQUIT
;
399 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
403 #include "microblaze.isa"
407 CPU
.exception
= SIGILL
;
408 fprintf (stderr
, "ERROR: Unknown opcode\n");
410 /* Make R0 consistent */
413 /* Check for imm instr */
419 /* Update cycle counts */
421 if (insn_type
== memory_store_inst
|| insn_type
== memory_load_inst
)
423 if (insn_type
== mult_inst
)
425 if (insn_type
== barrel_shift_inst
)
427 if (insn_type
== anyware_inst
)
429 if (insn_type
== div_inst
)
432 if ((insn_type
== branch_inst
|| insn_type
== return_inst
)
435 /* Add an extra cycle for taken branches */
437 /* For branch instructions handle the instruction in the delay slot */
438 if (delay_slot_enable
)
441 PC
= oldpc
+ INST_SIZE
;
442 inst
= rlat (cpu
, PC
& 0xFFFFFFFC);
443 op
= get_insn_microblaze (inst
, &imm_unsigned
, &insn_type
,
445 if (op
== invalid_inst
)
446 fprintf (stderr
, "Unknown instruction 0x%04x", inst
);
448 fprintf (stderr
, "%.4x: inst = %.4x ", PC
, inst
);
452 /* immword = IMM_W; */
453 if (op
== microblaze_brk
)
456 fprintf (stderr
, "Breakpoint set in delay slot "
457 "(at address 0x%x) will not be honored\n", PC
);
458 /* ignore the breakpoint */
460 else if (insn_type
== branch_inst
|| insn_type
== return_inst
)
463 fprintf (stderr
, "Cannot have branch or return instructions "
464 "in delay slot (at address 0x%x)\n", PC
);
465 CPU
.exception
= SIGILL
;
471 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
475 #include "microblaze.isa"
479 CPU
.exception
= SIGILL
;
480 fprintf (stderr
, "ERROR: Unknown opcode at 0x%x\n", PC
);
482 /* Update cycle counts */
484 if (insn_type
== memory_store_inst
485 || insn_type
== memory_load_inst
)
487 if (insn_type
== mult_inst
)
489 if (insn_type
== barrel_shift_inst
)
491 if (insn_type
== anyware_inst
)
493 if (insn_type
== div_inst
)
498 /* Make R0 consistent */
500 /* Check for imm instr */
507 /* no delay slot: increment cycle count */
513 fprintf (stderr
, "\n");
515 while (!CPU
.exception
);
517 /* Hide away the things we've cached while executing. */
519 CPU
.insts
+= insts
; /* instructions done ... */
520 CPU
.cycles
+= insts
; /* and each takes a cycle */
521 CPU
.cycles
+= bonus_cycles
; /* and extra cycles for branches */
522 CPU
.cycles
+= memops
; /* and memop cycle delays */
527 sim_write (SIM_DESC sd
, SIM_ADDR addr
, const unsigned char *buffer
, int size
)
529 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
534 memcpy (&CPU
.memory
[addr
], buffer
, size
);
540 sim_read (SIM_DESC sd
, SIM_ADDR addr
, unsigned char *buffer
, int size
)
542 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
547 memcpy (buffer
, &CPU
.memory
[addr
], size
);
554 sim_store_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
556 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
560 if (rn
< NUM_REGS
+ NUM_SPECIAL
&& rn
>= 0)
564 /* misalignment safe */
565 long ival
= microblaze_extract_unsigned_integer (memory
, 4);
569 CPU
.spregs
[rn
-NUM_REGS
] = ival
;
580 sim_fetch_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
582 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
587 if (rn
< NUM_REGS
+ NUM_SPECIAL
&& rn
>= 0)
594 ival
= CPU
.spregs
[rn
-NUM_REGS
];
596 /* misalignment-safe */
597 microblaze_store_unsigned_integer (memory
, 4, ival
);
608 sim_stop_reason (SIM_DESC sd
, enum sim_stop
*reason
, int *sigrc
)
610 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
612 if (CPU
.exception
== SIGQUIT
)
614 *reason
= sim_exited
;
619 *reason
= sim_stopped
;
620 *sigrc
= CPU
.exception
;
625 sim_info (SIM_DESC sd
, int verbose
)
627 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
628 host_callback
*callback
= STATE_CALLBACK (sd
);
630 callback
->printf_filtered (callback
, "\n\n# instructions executed %10d\n",
632 callback
->printf_filtered (callback
, "# cycles %10d\n",
633 (CPU
.cycles
) ? CPU
.cycles
+2 : 0);
637 free_state (SIM_DESC sd
)
639 if (STATE_MODULES (sd
) != NULL
)
640 sim_module_uninstall (sd
);
641 sim_cpu_free_all (sd
);
646 sim_open (SIM_OPEN_KIND kind
, host_callback
*cb
, struct bfd
*abfd
, char **argv
)
649 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
650 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
652 /* The cpu data is kept in a separately allocated chunk of memory. */
653 if (sim_cpu_alloc_all (sd
, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK
)
659 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
665 /* getopt will print the error message so we just have to exit if this fails.
666 FIXME: Hmmm... in the case of gdb we need getopt to call
668 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
674 /* Check for/establish the a reference program image. */
675 if (sim_analyze_program (sd
,
676 (STATE_PROG_ARGV (sd
) != NULL
677 ? *STATE_PROG_ARGV (sd
)
678 : NULL
), abfd
) != SIM_RC_OK
)
684 /* Configure/verify the target byte order and other runtime
685 configuration options. */
686 if (sim_config (sd
) != SIM_RC_OK
)
688 sim_module_uninstall (sd
);
692 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
694 /* Uninstall the modules to avoid memory leaks,
695 file descriptor leaks, etc. */
696 sim_module_uninstall (sd
);
700 if (kind
== SIM_OPEN_STANDALONE
)
703 /* CPU specific initialization. */
704 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
706 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
707 int osize
= sim_memory_size
;
709 set_initial_gprs (cpu
);
711 /* Discard and reacquire memory -- start with a clean slate. */
712 sim_size (cpu
, 1); /* small */
713 sim_size (cpu
, osize
); /* and back again */
720 sim_close (SIM_DESC sd
, int quitting
)
726 sim_create_inferior (SIM_DESC sd
, struct bfd
*prog_bfd
, char **argv
, char **env
)
728 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
730 PC
= bfd_get_start_address (prog_bfd
);
736 sim_do_command (SIM_DESC sd
, const char *cmd
)
738 SIM_CPU
*cpu
= STATE_CPU (sd
, 0);
740 /* Nothing there yet; it's all an error. */
744 char ** simargv
= buildargv (cmd
);
746 if (strcmp (simargv
[0], "dumpmem") == 0)
751 if (simargv
[1] == NULL
)
752 fprintf (stderr
, "Error: missing argument to dumpmem cmd.\n");
754 fprintf (stderr
, "Writing dumpfile %s...",simargv
[1]);
756 dumpfile
= fopen (simargv
[1], "w");
758 fwrite (p
, CPU
.msize
-1, 1, dumpfile
);
761 fprintf (stderr
, "done.\n");
763 else if (strcmp (simargv
[0], "clearstats") == 0)
768 else if (strcmp (simargv
[0], "verbose") == 0)
774 fprintf (stderr
,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
782 fprintf (stderr
, "M.CORE sim commands: \n");
783 fprintf (stderr
, " dumpmem <filename>\n");
784 fprintf (stderr
, " clearstats\n");
785 fprintf (stderr
, " verbose\n");