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/>. */
23 #include <sys/times.h>
24 #include <sys/param.h>
27 #include "gdb/callback.h"
28 #include "libiberty.h"
29 #include "gdb/remote-sim.h"
31 #include "sim-utils.h"
32 #include "microblaze-dis.h"
36 #define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
39 static int target_big_endian
= 1;
40 static unsigned long heap_ptr
= 0;
41 static unsigned long stack_ptr
= 0;
42 host_callback
*callback
;
45 microblaze_extract_unsigned_integer (unsigned char *addr
, int len
)
49 unsigned char *startaddr
= (unsigned char *)addr
;
50 unsigned char *endaddr
= startaddr
+ len
;
52 if (len
> (int) sizeof (unsigned long))
53 printf ("That operation is not available on integers of more than "
54 "%zu bytes.", sizeof (unsigned long));
56 /* Start at the most significant end of the integer, and work towards
57 the least significant. */
60 if (!target_big_endian
)
62 for (p
= endaddr
; p
> startaddr
;)
63 retval
= (retval
<< 8) | * -- p
;
67 for (p
= startaddr
; p
< endaddr
;)
68 retval
= (retval
<< 8) | * p
++;
75 microblaze_store_unsigned_integer (unsigned char *addr
, int len
,
79 unsigned char *startaddr
= (unsigned char *)addr
;
80 unsigned char *endaddr
= startaddr
+ len
;
82 if (!target_big_endian
)
84 for (p
= startaddr
; p
< endaddr
;)
92 for (p
= endaddr
; p
> startaddr
;)
100 struct sim_state microblaze_state
;
104 static SIM_OPEN_KIND sim_kind
;
107 static int issue_messages
= 0;
110 int_sbrk (int inc_bytes
)
116 heap_ptr
+= inc_bytes
;
118 if (issue_messages
&& heap_ptr
> SP
)
119 fprintf (stderr
, "Warning: heap_ptr overlaps stack!\n");
124 static void /* INLINE */
125 wbat (word x
, word v
)
127 if (((uword
)x
) >= CPU
.msize
)
130 fprintf (stderr
, "byte write to 0x%x outside memory range\n", x
);
132 CPU
.exception
= SIGSEGV
;
136 unsigned char *p
= CPU
.memory
+ x
;
141 static void /* INLINE */
142 wlat (word x
, word v
)
144 if (((uword
)x
) >= CPU
.msize
)
147 fprintf (stderr
, "word write to 0x%x outside memory range\n", x
);
149 CPU
.exception
= SIGSEGV
;
156 fprintf (stderr
, "word write to unaligned memory address: 0x%x\n", x
);
158 CPU
.exception
= SIGBUS
;
160 else if (!target_big_endian
)
162 unsigned char *p
= CPU
.memory
+ x
;
170 unsigned char *p
= CPU
.memory
+ x
;
179 static void /* INLINE */
180 what (word x
, word v
)
182 if (((uword
)x
) >= CPU
.msize
)
185 fprintf (stderr
, "short write to 0x%x outside memory range\n", x
);
187 CPU
.exception
= SIGSEGV
;
194 fprintf (stderr
, "short write to unaligned memory address: 0x%x\n",
197 CPU
.exception
= SIGBUS
;
199 else if (!target_big_endian
)
201 unsigned char *p
= CPU
.memory
+ x
;
207 unsigned char *p
= CPU
.memory
+ x
;
214 /* Read functions. */
215 static int /* INLINE */
218 if (((uword
)x
) >= CPU
.msize
)
221 fprintf (stderr
, "byte read from 0x%x outside memory range\n", x
);
223 CPU
.exception
= SIGSEGV
;
228 unsigned char *p
= CPU
.memory
+ x
;
233 static int /* INLINE */
236 if (((uword
) x
) >= CPU
.msize
)
239 fprintf (stderr
, "word read from 0x%x outside memory range\n", x
);
241 CPU
.exception
= SIGSEGV
;
249 fprintf (stderr
, "word read from unaligned address: 0x%x\n", x
);
251 CPU
.exception
= SIGBUS
;
254 else if (! target_big_endian
)
256 unsigned char *p
= CPU
.memory
+ x
;
257 return (p
[3] << 24) | (p
[2] << 16) | (p
[1] << 8) | p
[0];
261 unsigned char *p
= CPU
.memory
+ x
;
262 return (p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3];
267 static int /* INLINE */
270 if (((uword
)x
) >= CPU
.msize
)
273 fprintf (stderr
, "short read from 0x%x outside memory range\n", x
);
275 CPU
.exception
= SIGSEGV
;
283 fprintf (stderr
, "short read from unaligned address: 0x%x\n", x
);
285 CPU
.exception
= SIGBUS
;
288 else if (!target_big_endian
)
290 unsigned char *p
= CPU
.memory
+ x
;
291 return (p
[1] << 8) | p
[0];
295 unsigned char *p
= CPU
.memory
+ x
;
296 return (p
[0] << 8) | p
[1];
302 #define SEXTB(x) (((x & 0xff) ^ (~ 0x7f)) + 0x80)
303 #define SEXTW(y) ((int)((short)y))
306 IOMEM (int addr
, int write
, int value
)
310 /* Default to a 8 Mbyte (== 2^23) memory space. */
311 static int sim_memory_size
= 1 << 23;
313 #define MEM_SIZE_FLOOR 64
317 sim_memory_size
= size
;
318 CPU
.msize
= sim_memory_size
;
323 CPU
.memory
= (unsigned char *) calloc (1, CPU
.msize
);
329 "Not enough VM for simulation of %ld bytes of RAM\n",
333 CPU
.memory
= (unsigned char *) calloc (1, 1);
340 if (CPU
.msize
!= (sim_memory_size
))
341 sim_size (sim_memory_size
);
349 unsigned long memsize
;
353 /* Set up machine just out of reset. */
357 memsize
= CPU
.msize
/ (1024 * 1024);
359 if (issue_messages
> 1)
360 fprintf (stderr
, "Simulated memory of %ld Mbytes (0x0 .. 0x%08lx)\n",
361 memsize
, CPU
.msize
- 1);
363 /* Clean out the GPRs */
364 for (i
= 0; i
< 32; i
++)
372 /* Functions so that trapped open/close don't interfere with the
373 parent's functions. We say that we can't close the descriptors
374 that we didn't open. exit() and cleanup() get in trouble here,
375 to some extent. That's the price of emulation. */
377 unsigned char opened
[100];
382 if (fd
< 0 || fd
> NUM_ELEM (opened
))
391 if (fd
< 0 || fd
> NUM_ELEM (opened
))
400 if (fd
< 0 || fd
> NUM_ELEM (opened
))
412 process_stub (int what
)
414 /* These values should match those in libgloss/microblaze/syscalls.s. */
421 case 10: /* _unlink */
422 case 19: /* _lseek */
423 case 43: /* _times */
429 fprintf (stderr
, "Unhandled stub opcode: %d\n", what
);
440 CPU
.exception
= SIGQUIT
;
449 for (s
= (unsigned char *)a
[0], i
= 1 ; *s
&& i
< 6 ; s
++)
457 fprintf (stderr
, "WARNING: scanf unimplemented\n");
464 process_stub (CPU
.regs
[1]);
469 fprintf (stderr
, "Unhandled util code: %x\n", what
);
474 /* For figuring out whether we carried; addc/subc use this. */
476 iu_carry (unsigned long a
, unsigned long b
, int cin
)
480 x
= (a
& 0xffff) + (b
& 0xffff) + cin
;
481 x
= (x
>> 16) + (a
>> 16) + (b
>> 16);
487 #define WATCHFUNCTIONS 1
488 #ifdef WATCHFUNCTIONS
505 static int tracing
= 0;
508 sim_resume (SIM_DESC sd
, int step
, int siggnal
)
512 enum microblaze_instr op
;
524 short delay_slot_enable
;
526 short num_delay_slot
; /* UNUSED except as reqd parameter */
527 enum microblaze_instr_type insn_type
;
529 CPU
.exception
= step
? SIGTRAP
: 0;
537 /* Fetch the initial instructions that we'll decode. */
538 inst
= rlat (PC
& 0xFFFFFFFC);
540 op
= get_insn_microblaze (inst
, &imm_unsigned
, &insn_type
,
543 if (op
== invalid_inst
)
544 fprintf (stderr
, "Unknown instruction 0x%04x", inst
);
547 fprintf (stderr
, "%.4x: inst = %.4x ", PC
, inst
);
552 /* immword = IMM_W; */
555 delay_slot_enable
= 0;
557 if (op
== microblaze_brk
)
558 CPU
.exception
= SIGTRAP
;
559 else if (inst
== MICROBLAZE_HALT_INST
)
561 CPU
.exception
= SIGQUIT
;
569 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
573 #include "microblaze.isa"
577 CPU
.exception
= SIGILL
;
578 fprintf (stderr
, "ERROR: Unknown opcode\n");
580 /* Make R0 consistent */
583 /* Check for imm instr */
589 /* Update cycle counts */
591 if (insn_type
== memory_store_inst
|| insn_type
== memory_load_inst
)
593 if (insn_type
== mult_inst
)
595 if (insn_type
== barrel_shift_inst
)
597 if (insn_type
== anyware_inst
)
599 if (insn_type
== div_inst
)
602 if ((insn_type
== branch_inst
|| insn_type
== return_inst
)
605 /* Add an extra cycle for taken branches */
607 /* For branch instructions handle the instruction in the delay slot */
608 if (delay_slot_enable
)
611 PC
= oldpc
+ INST_SIZE
;
612 inst
= rlat (PC
& 0xFFFFFFFC);
613 op
= get_insn_microblaze (inst
, &imm_unsigned
, &insn_type
,
615 if (op
== invalid_inst
)
616 fprintf (stderr
, "Unknown instruction 0x%04x", inst
);
618 fprintf (stderr
, "%.4x: inst = %.4x ", PC
, inst
);
622 /* immword = IMM_W; */
623 if (op
== microblaze_brk
)
626 fprintf (stderr
, "Breakpoint set in delay slot "
627 "(at address 0x%x) will not be honored\n", PC
);
628 /* ignore the breakpoint */
630 else if (insn_type
== branch_inst
|| insn_type
== return_inst
)
633 fprintf (stderr
, "Cannot have branch or return instructions "
634 "in delay slot (at address 0x%x)\n", PC
);
635 CPU
.exception
= SIGILL
;
641 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
645 #include "microblaze.isa"
649 CPU
.exception
= SIGILL
;
650 fprintf (stderr
, "ERROR: Unknown opcode at 0x%x\n", PC
);
652 /* Update cycle counts */
654 if (insn_type
== memory_store_inst
655 || insn_type
== memory_load_inst
)
657 if (insn_type
== mult_inst
)
659 if (insn_type
== barrel_shift_inst
)
661 if (insn_type
== anyware_inst
)
663 if (insn_type
== div_inst
)
668 /* Make R0 consistent */
670 /* Check for imm instr */
677 /* no delay slot: increment cycle count */
683 fprintf (stderr
, "\n");
685 while (!CPU
.exception
);
687 /* Hide away the things we've cached while executing. */
689 CPU
.insts
+= insts
; /* instructions done ... */
690 CPU
.cycles
+= insts
; /* and each takes a cycle */
691 CPU
.cycles
+= bonus_cycles
; /* and extra cycles for branches */
692 CPU
.cycles
+= memops
; /* and memop cycle delays */
697 sim_write (SIM_DESC sd
, SIM_ADDR addr
, const unsigned char *buffer
, int size
)
702 memcpy (&CPU
.memory
[addr
], buffer
, size
);
708 sim_read (SIM_DESC sd
, SIM_ADDR addr
, unsigned char *buffer
, int size
)
713 memcpy (buffer
, &CPU
.memory
[addr
], size
);
720 sim_store_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
724 if (rn
< NUM_REGS
+ NUM_SPECIAL
&& rn
>= 0)
728 /* misalignment safe */
729 long ival
= microblaze_extract_unsigned_integer (memory
, 4);
733 CPU
.spregs
[rn
-NUM_REGS
] = ival
;
744 sim_fetch_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
749 if (rn
< NUM_REGS
+ NUM_SPECIAL
&& rn
>= 0)
756 ival
= CPU
.spregs
[rn
-NUM_REGS
];
758 /* misalignment-safe */
759 microblaze_store_unsigned_integer (memory
, 4, ival
);
771 sim_trace (SIM_DESC sd
)
775 sim_resume (sd
, 0, 0);
783 sim_stop_reason (SIM_DESC sd
, enum sim_stop
*reason
, int *sigrc
)
785 if (CPU
.exception
== SIGQUIT
)
787 *reason
= sim_exited
;
792 *reason
= sim_stopped
;
793 *sigrc
= CPU
.exception
;
799 sim_stop (SIM_DESC sd
)
801 CPU
.exception
= SIGINT
;
807 sim_info (SIM_DESC sd
, int verbose
)
809 #ifdef WATCHFUNCTIONS
813 callback
->printf_filtered (callback
, "\n\n# instructions executed %10d\n",
815 callback
->printf_filtered (callback
, "# cycles %10d\n",
816 (CPU
.cycles
) ? CPU
.cycles
+2 : 0);
818 #ifdef WATCHFUNCTIONS
819 callback
->printf_filtered (callback
, "\nNumber of watched functions: %d\n",
824 for (w
= 1; w
<= ENDWL
; w
++)
826 callback
->printf_filtered (callback
, "WL = %s %8x\n",WLstr
[w
],WL
[w
]);
827 callback
->printf_filtered (callback
, " calls = %d, cycles = %d\n",
831 callback
->printf_filtered (callback
,
832 " maxcpc = %d, mincpc = %d, avecpc = %d\n",
833 WLmax
[w
],WLmin
[w
],WLcyc
[w
]/WLcnts
[w
]);
837 callback
->printf_filtered (callback
,
838 "Total cycles for watched functions: %d\n",wcyc
);
844 unsigned char sa_machtype
[2];
845 unsigned char sa_magic
[2];
846 unsigned char sa_tsize
[4];
847 unsigned char sa_dsize
[4];
848 unsigned char sa_bsize
[4];
849 unsigned char sa_syms
[4];
850 unsigned char sa_entry
[4];
851 unsigned char sa_trelo
[4];
852 unsigned char sa_drelo
[4];
855 #define LONG(x) (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
856 #define SHORT(x) (((x)[0]<<8)|(x)[1])
859 sim_open (SIM_OPEN_KIND kind
, host_callback
*cb
, struct bfd
*abfd
, char **argv
)
861 /* SIM_DESC sd = sim_state_alloc(kind, alloc);*/
863 int osize
= sim_memory_size
;
867 if (kind
== SIM_OPEN_STANDALONE
)
870 /* Discard and reacquire memory -- start with a clean slate. */
871 sim_size (1); /* small */
872 sim_size (osize
); /* and back again */
874 set_initial_gprs (); /* Reset the GPR registers. */
876 return ((SIM_DESC
) 1);
880 sim_close (SIM_DESC sd
, int quitting
)
891 sim_load (SIM_DESC sd
, const char *prog
, bfd
*abfd
, int from_tty
)
893 /* Do the right thing for ELF executables; this turns out to be
894 just about the right thing for any object format that:
895 - we crack using BFD routines
896 - follows the traditional UNIX text/data/bss layout
897 - calls the bss section ".bss". */
899 extern bfd
*sim_load_file (); /* ??? Don't know where this should live. */
905 int found_loadable_section
= 0;
906 bfd_vma max_addr
= 0;
907 handle
= bfd_openr (prog
, 0);
911 printf("``%s'' could not be opened.\n", prog
);
915 /* Makes sure that we have an object file, also cleans gets the
916 section headers in place. */
917 if (!bfd_check_format (handle
, bfd_object
))
919 /* wasn't an object file */
921 printf ("``%s'' is not appropriate object file.\n", prog
);
925 for (s
= handle
->sections
; s
; s
= s
->next
)
927 if (s
->flags
& SEC_ALLOC
)
930 int size
= bfd_get_section_size (s
);
933 vma
= bfd_section_vma (handle
, s
);
936 max_addr
= vma
+ size
;
939 if (s
->flags
& SEC_LOAD
)
940 found_loadable_section
= 1;
944 if (!found_loadable_section
)
946 /* No loadable sections */
948 printf("No loadable sections in file %s\n", prog
);
952 sim_memory_size
= (unsigned long) max_addr
;
954 /* Clean up after ourselves. */
960 prog_bfd
= sim_load_file (sd
, myname
, callback
, prog
, abfd
,
961 /* sim_kind == SIM_OPEN_DEBUG, */
964 if (prog_bfd
== NULL
)
967 target_big_endian
= bfd_big_endian (prog_bfd
);
968 PC
= bfd_get_start_address (prog_bfd
);
971 bfd_close (prog_bfd
);
977 sim_create_inferior (SIM_DESC sd
, struct bfd
*prog_bfd
, char **argv
, char **env
)
984 unsigned long strings
;
985 unsigned long pointers
;
986 unsigned long hi_stack
;
989 /* Set the initial register set. */
995 hi_stack
= CPU
.msize
- 4;
996 PC
= bfd_get_start_address (prog_bfd
);
998 /* For now ignore all parameters to the program */
1004 sim_do_command (SIM_DESC sd
, const char *cmd
)
1006 /* Nothing there yet; it's all an error. */
1010 char ** simargv
= buildargv (cmd
);
1012 if (strcmp (simargv
[0], "watch") == 0)
1014 if ((simargv
[1] == NULL
) || (simargv
[2] == NULL
))
1016 fprintf (stderr
, "Error: missing argument to watch cmd.\n");
1023 WL
[ENDWL
] = strtol (simargv
[2], NULL
, 0);
1024 WLstr
[ENDWL
] = strdup (simargv
[1]);
1025 fprintf (stderr
, "Added %s (%x) to watchlist, #%d\n",WLstr
[ENDWL
],
1029 else if (strcmp (simargv
[0], "dumpmem") == 0)
1034 if (simargv
[1] == NULL
)
1035 fprintf (stderr
, "Error: missing argument to dumpmem cmd.\n");
1037 fprintf (stderr
, "Writing dumpfile %s...",simargv
[1]);
1039 dumpfile
= fopen (simargv
[1], "w");
1041 fwrite (p
, CPU
.msize
-1, 1, dumpfile
);
1044 fprintf (stderr
, "done.\n");
1046 else if (strcmp (simargv
[0], "clearstats") == 0)
1052 else if (strcmp (simargv
[0], "verbose") == 0)
1058 fprintf (stderr
,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
1066 fprintf (stderr
, "M.CORE sim commands: \n");
1067 fprintf (stderr
, " watch <funcname> <addr>\n");
1068 fprintf (stderr
, " dumpmem <filename>\n");
1069 fprintf (stderr
, " clearstats\n");
1070 fprintf (stderr
, " verbose\n");
1075 sim_set_callbacks (host_callback
*ptr
)
1081 sim_complete_command (SIM_DESC sd
, const char *text
, const char *word
)