1 /* Simulator for Xilinx MicroBlaze processor
2 Copyright 2009-2014 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/>. */
22 #include <sys/times.h>
23 #include <sys/param.h>
24 #include <netinet/in.h> /* for byte ordering macros */
26 #include "gdb/callback.h"
27 #include "libiberty.h"
28 #include "gdb/remote-sim.h"
30 #include "sim-utils.h"
31 #include "microblaze-dis.h"
35 #define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
38 static int target_big_endian
= 1;
39 static unsigned long heap_ptr
= 0;
40 static unsigned long stack_ptr
= 0;
41 host_callback
*callback
;
44 microblaze_extract_unsigned_integer (unsigned char *addr
, int len
)
48 unsigned char *startaddr
= (unsigned char *)addr
;
49 unsigned char *endaddr
= startaddr
+ len
;
51 if (len
> (int) sizeof (unsigned long))
52 printf ("That operation is not available on integers of more than "
53 "%d bytes.", sizeof (unsigned long));
55 /* Start at the most significant end of the integer, and work towards
56 the least significant. */
59 if (!target_big_endian
)
61 for (p
= endaddr
; p
> startaddr
;)
62 retval
= (retval
<< 8) | * -- p
;
66 for (p
= startaddr
; p
< endaddr
;)
67 retval
= (retval
<< 8) | * p
++;
74 microblaze_store_unsigned_integer (unsigned char *addr
, int len
,
78 unsigned char *startaddr
= (unsigned char *)addr
;
79 unsigned char *endaddr
= startaddr
+ len
;
81 if (!target_big_endian
)
83 for (p
= startaddr
; p
< endaddr
;)
91 for (p
= endaddr
; p
> startaddr
;)
99 struct sim_state microblaze_state
;
103 static SIM_OPEN_KIND sim_kind
;
106 static int issue_messages
= 0;
109 int_sbrk (int inc_bytes
)
115 heap_ptr
+= inc_bytes
;
117 if (issue_messages
&& heap_ptr
> SP
)
118 fprintf (stderr
, "Warning: heap_ptr overlaps stack!\n");
123 static void /* INLINE */
124 wbat (word x
, word v
)
126 if (((uword
)x
) >= CPU
.msize
)
129 fprintf (stderr
, "byte write to 0x%x outside memory range\n", x
);
131 CPU
.exception
= SIGSEGV
;
135 unsigned char *p
= CPU
.memory
+ x
;
140 static void /* INLINE */
141 wlat (word x
, word v
)
143 if (((uword
)x
) >= CPU
.msize
)
146 fprintf (stderr
, "word write to 0x%x outside memory range\n", x
);
148 CPU
.exception
= SIGSEGV
;
155 fprintf (stderr
, "word write to unaligned memory address: 0x%x\n", x
);
157 CPU
.exception
= SIGBUS
;
159 else if (!target_big_endian
)
161 unsigned char *p
= CPU
.memory
+ x
;
169 unsigned char *p
= CPU
.memory
+ x
;
178 static void /* INLINE */
179 what (word x
, word v
)
181 if (((uword
)x
) >= CPU
.msize
)
184 fprintf (stderr
, "short write to 0x%x outside memory range\n", x
);
186 CPU
.exception
= SIGSEGV
;
193 fprintf (stderr
, "short write to unaligned memory address: 0x%x\n",
196 CPU
.exception
= SIGBUS
;
198 else if (!target_big_endian
)
200 unsigned char *p
= CPU
.memory
+ x
;
206 unsigned char *p
= CPU
.memory
+ x
;
213 /* Read functions. */
214 static int /* INLINE */
217 if (((uword
)x
) >= CPU
.msize
)
220 fprintf (stderr
, "byte read from 0x%x outside memory range\n", x
);
222 CPU
.exception
= SIGSEGV
;
227 unsigned char *p
= CPU
.memory
+ x
;
232 static int /* INLINE */
235 if (((uword
) x
) >= CPU
.msize
)
238 fprintf (stderr
, "word read from 0x%x outside memory range\n", x
);
240 CPU
.exception
= SIGSEGV
;
248 fprintf (stderr
, "word read from unaligned address: 0x%x\n", x
);
250 CPU
.exception
= SIGBUS
;
253 else if (! target_big_endian
)
255 unsigned char *p
= CPU
.memory
+ x
;
256 return (p
[3] << 24) | (p
[2] << 16) | (p
[1] << 8) | p
[0];
260 unsigned char *p
= CPU
.memory
+ x
;
261 return (p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3];
266 static int /* INLINE */
269 if (((uword
)x
) >= CPU
.msize
)
272 fprintf (stderr
, "short read from 0x%x outside memory range\n", x
);
274 CPU
.exception
= SIGSEGV
;
282 fprintf (stderr
, "short read from unaligned address: 0x%x\n", x
);
284 CPU
.exception
= SIGBUS
;
287 else if (!target_big_endian
)
289 unsigned char *p
= CPU
.memory
+ x
;
290 return (p
[1] << 8) | p
[0];
294 unsigned char *p
= CPU
.memory
+ x
;
295 return (p
[0] << 8) | p
[1];
301 #define SEXTB(x) (((x & 0xff) ^ (~ 0x7f)) + 0x80)
302 #define SEXTW(y) ((int)((short)y))
305 IOMEM (int addr
, int write
, int value
)
309 /* Default to a 8 Mbyte (== 2^23) memory space. */
310 static int sim_memory_size
= 1 << 23;
312 #define MEM_SIZE_FLOOR 64
316 sim_memory_size
= size
;
317 CPU
.msize
= sim_memory_size
;
322 CPU
.memory
= (unsigned char *) calloc (1, CPU
.msize
);
328 "Not enough VM for simulation of %d bytes of RAM\n",
332 CPU
.memory
= (unsigned char *) calloc (1, 1);
339 if (CPU
.msize
!= (sim_memory_size
))
340 sim_size (sim_memory_size
);
348 unsigned long memsize
;
352 /* Set up machine just out of reset. */
356 memsize
= CPU
.msize
/ (1024 * 1024);
358 if (issue_messages
> 1)
359 fprintf (stderr
, "Simulated memory of %d Mbytes (0x0 .. 0x%08x)\n",
360 memsize
, CPU
.msize
- 1);
362 /* Clean out the GPRs */
363 for (i
= 0; i
< 32; i
++)
374 CPU
.exception
= SIGINT
;
377 /* Functions so that trapped open/close don't interfere with the
378 parent's functions. We say that we can't close the descriptors
379 that we didn't open. exit() and cleanup() get in trouble here,
380 to some extent. That's the price of emulation. */
382 unsigned char opened
[100];
387 if (fd
< 0 || fd
> NUM_ELEM (opened
))
396 if (fd
< 0 || fd
> NUM_ELEM (opened
))
405 if (fd
< 0 || fd
> NUM_ELEM (opened
))
417 process_stub (int what
)
419 /* These values should match those in libgloss/microblaze/syscalls.s. */
426 case 10: /* _unlink */
427 case 19: /* _lseek */
428 case 43: /* _times */
434 fprintf (stderr
, "Unhandled stub opcode: %d\n", what
);
445 CPU
.exception
= SIGQUIT
;
454 for (s
= (unsigned char *)a
[0], i
= 1 ; *s
&& i
< 6 ; s
++)
462 fprintf (stderr
, "WARNING: scanf unimplemented\n");
469 process_stub (CPU
.regs
[1]);
474 fprintf (stderr
, "Unhandled util code: %x\n", what
);
479 /* For figuring out whether we carried; addc/subc use this. */
481 iu_carry (unsigned long a
, unsigned long b
, int cin
)
485 x
= (a
& 0xffff) + (b
& 0xffff) + cin
;
486 x
= (x
>> 16) + (a
>> 16) + (b
>> 16);
492 #define WATCHFUNCTIONS 1
493 #ifdef WATCHFUNCTIONS
510 static int tracing
= 0;
513 sim_resume (SIM_DESC sd
, int step
, int siggnal
)
517 enum microblaze_instr op
;
530 short delay_slot_enable
;
532 short num_delay_slot
; /* UNUSED except as reqd parameter */
533 enum microblaze_instr_type insn_type
;
535 sigsave
= signal (SIGINT
, interrupt
);
536 CPU
.exception
= step
? SIGTRAP
: 0;
544 /* Fetch the initial instructions that we'll decode. */
545 inst
= rlat (PC
& 0xFFFFFFFC);
547 op
= get_insn_microblaze (inst
, &imm_unsigned
, &insn_type
,
550 if (op
== invalid_inst
)
551 fprintf (stderr
, "Unknown instruction 0x%04x", inst
);
554 fprintf (stderr
, "%.4x: inst = %.4x ", PC
, inst
);
559 /* immword = IMM_W; */
562 delay_slot_enable
= 0;
564 if (op
== microblaze_brk
)
565 CPU
.exception
= SIGTRAP
;
566 else if (inst
== MICROBLAZE_HALT_INST
)
568 CPU
.exception
= SIGQUIT
;
576 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
580 #include "microblaze.isa"
584 CPU
.exception
= SIGILL
;
585 fprintf (stderr
, "ERROR: Unknown opcode\n");
587 /* Make R0 consistent */
590 /* Check for imm instr */
596 /* Update cycle counts */
598 if (insn_type
== memory_store_inst
|| insn_type
== memory_load_inst
)
600 if (insn_type
== mult_inst
)
602 if (insn_type
== barrel_shift_inst
)
604 if (insn_type
== anyware_inst
)
606 if (insn_type
== div_inst
)
609 if ((insn_type
== branch_inst
|| insn_type
== return_inst
)
612 /* Add an extra cycle for taken branches */
614 /* For branch instructions handle the instruction in the delay slot */
615 if (delay_slot_enable
)
618 PC
= oldpc
+ INST_SIZE
;
619 inst
= rlat (PC
& 0xFFFFFFFC);
620 op
= get_insn_microblaze (inst
, &imm_unsigned
, &insn_type
,
622 if (op
== invalid_inst
)
623 fprintf (stderr
, "Unknown instruction 0x%04x", inst
);
625 fprintf (stderr
, "%.4x: inst = %.4x ", PC
, inst
);
629 /* immword = IMM_W; */
630 if (op
== microblaze_brk
)
633 fprintf (stderr
, "Breakpoint set in delay slot "
634 "(at address 0x%x) will not be honored\n", PC
);
635 /* ignore the breakpoint */
637 else if (insn_type
== branch_inst
|| insn_type
== return_inst
)
640 fprintf (stderr
, "Cannot have branch or return instructions "
641 "in delay slot (at address 0x%x)\n", PC
);
642 CPU
.exception
= SIGILL
;
648 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
652 #include "microblaze.isa"
656 CPU
.exception
= SIGILL
;
657 fprintf (stderr
, "ERROR: Unknown opcode at 0x%x\n", PC
);
659 /* Update cycle counts */
661 if (insn_type
== memory_store_inst
662 || insn_type
== memory_load_inst
)
664 if (insn_type
== mult_inst
)
666 if (insn_type
== barrel_shift_inst
)
668 if (insn_type
== anyware_inst
)
670 if (insn_type
== div_inst
)
675 /* Make R0 consistent */
677 /* Check for imm instr */
684 /* no delay slot: increment cycle count */
690 fprintf (stderr
, "\n");
692 while (!CPU
.exception
);
694 /* Hide away the things we've cached while executing. */
696 CPU
.insts
+= insts
; /* instructions done ... */
697 CPU
.cycles
+= insts
; /* and each takes a cycle */
698 CPU
.cycles
+= bonus_cycles
; /* and extra cycles for branches */
699 CPU
.cycles
+= memops
; /* and memop cycle delays */
701 signal (SIGINT
, sigsave
);
706 sim_write (SIM_DESC sd
, SIM_ADDR addr
, const unsigned char *buffer
, int size
)
711 memcpy (&CPU
.memory
[addr
], buffer
, size
);
717 sim_read (SIM_DESC sd
, SIM_ADDR addr
, unsigned char *buffer
, int size
)
722 memcpy (buffer
, &CPU
.memory
[addr
], size
);
729 sim_store_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
733 if (rn
< NUM_REGS
+ NUM_SPECIAL
&& rn
>= 0)
737 /* misalignment safe */
738 long ival
= microblaze_extract_unsigned_integer (memory
, 4);
742 CPU
.spregs
[rn
-NUM_REGS
] = ival
;
753 sim_fetch_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
758 if (rn
< NUM_REGS
+ NUM_SPECIAL
&& rn
>= 0)
765 ival
= CPU
.spregs
[rn
-NUM_REGS
];
767 /* misalignment-safe */
768 microblaze_store_unsigned_integer (memory
, 4, ival
);
780 sim_trace (SIM_DESC sd
)
784 sim_resume (sd
, 0, 0);
792 sim_stop_reason (SIM_DESC sd
, enum sim_stop
*reason
, int *sigrc
)
794 if (CPU
.exception
== SIGQUIT
)
796 *reason
= sim_exited
;
801 *reason
= sim_stopped
;
802 *sigrc
= CPU
.exception
;
808 sim_stop (SIM_DESC sd
)
810 CPU
.exception
= SIGINT
;
816 sim_info (SIM_DESC sd
, int verbose
)
818 #ifdef WATCHFUNCTIONS
822 callback
->printf_filtered (callback
, "\n\n# instructions executed %10d\n",
824 callback
->printf_filtered (callback
, "# cycles %10d\n",
825 (CPU
.cycles
) ? CPU
.cycles
+2 : 0);
827 #ifdef WATCHFUNCTIONS
828 callback
->printf_filtered (callback
, "\nNumber of watched functions: %d\n",
833 for (w
= 1; w
<= ENDWL
; w
++)
835 callback
->printf_filtered (callback
, "WL = %s %8x\n",WLstr
[w
],WL
[w
]);
836 callback
->printf_filtered (callback
, " calls = %d, cycles = %d\n",
840 callback
->printf_filtered (callback
,
841 " maxcpc = %d, mincpc = %d, avecpc = %d\n",
842 WLmax
[w
],WLmin
[w
],WLcyc
[w
]/WLcnts
[w
]);
846 callback
->printf_filtered (callback
,
847 "Total cycles for watched functions: %d\n",wcyc
);
853 unsigned char sa_machtype
[2];
854 unsigned char sa_magic
[2];
855 unsigned char sa_tsize
[4];
856 unsigned char sa_dsize
[4];
857 unsigned char sa_bsize
[4];
858 unsigned char sa_syms
[4];
859 unsigned char sa_entry
[4];
860 unsigned char sa_trelo
[4];
861 unsigned char sa_drelo
[4];
864 #define LONG(x) (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
865 #define SHORT(x) (((x)[0]<<8)|(x)[1])
868 sim_open (SIM_OPEN_KIND kind
, host_callback
*cb
, struct bfd
*abfd
, char **argv
)
870 /* SIM_DESC sd = sim_state_alloc(kind, alloc);*/
872 int osize
= sim_memory_size
;
876 if (kind
== SIM_OPEN_STANDALONE
)
879 /* Discard and reacquire memory -- start with a clean slate. */
880 sim_size (1); /* small */
881 sim_size (osize
); /* and back again */
883 set_initial_gprs (); /* Reset the GPR registers. */
885 return ((SIM_DESC
) 1);
889 sim_close (SIM_DESC sd
, int quitting
)
900 sim_load (SIM_DESC sd
, char *prog
, bfd
*abfd
, int from_tty
)
902 /* Do the right thing for ELF executables; this turns out to be
903 just about the right thing for any object format that:
904 - we crack using BFD routines
905 - follows the traditional UNIX text/data/bss layout
906 - calls the bss section ".bss". */
908 extern bfd
*sim_load_file (); /* ??? Don't know where this should live. */
914 int found_loadable_section
= 0;
915 bfd_vma max_addr
= 0;
916 handle
= bfd_openr (prog
, 0);
920 printf("``%s'' could not be opened.\n", prog
);
924 /* Makes sure that we have an object file, also cleans gets the
925 section headers in place. */
926 if (!bfd_check_format (handle
, bfd_object
))
928 /* wasn't an object file */
930 printf ("``%s'' is not appropriate object file.\n", prog
);
934 for (s
= handle
->sections
; s
; s
= s
->next
)
936 if (s
->flags
& SEC_ALLOC
)
939 int size
= bfd_get_section_size (s
);
942 vma
= bfd_section_vma (handle
, s
);
945 max_addr
= vma
+ size
;
948 if (s
->flags
& SEC_LOAD
)
949 found_loadable_section
= 1;
953 if (!found_loadable_section
)
955 /* No loadable sections */
957 printf("No loadable sections in file %s\n", prog
);
961 sim_memory_size
= (unsigned long) max_addr
;
963 /* Clean up after ourselves. */
969 prog_bfd
= sim_load_file (sd
, myname
, callback
, prog
, abfd
,
970 /* sim_kind == SIM_OPEN_DEBUG, */
973 if (prog_bfd
== NULL
)
976 target_big_endian
= bfd_big_endian (prog_bfd
);
977 PC
= bfd_get_start_address (prog_bfd
);
980 bfd_close (prog_bfd
);
986 sim_create_inferior (SIM_DESC sd
, struct bfd
*prog_bfd
, char **argv
, char **env
)
993 unsigned long strings
;
994 unsigned long pointers
;
995 unsigned long hi_stack
;
998 /* Set the initial register set. */
1001 set_initial_gprs ();
1004 hi_stack
= CPU
.msize
- 4;
1005 PC
= bfd_get_start_address (prog_bfd
);
1007 /* For now ignore all parameters to the program */
1013 sim_kill (SIM_DESC sd
)
1019 sim_do_command (SIM_DESC sd
, char * cmd
)
1021 /* Nothing there yet; it's all an error. */
1025 char ** simargv
= buildargv (cmd
);
1027 if (strcmp (simargv
[0], "watch") == 0)
1029 if ((simargv
[1] == NULL
) || (simargv
[2] == NULL
))
1031 fprintf (stderr
, "Error: missing argument to watch cmd.\n");
1037 WL
[ENDWL
] = strtol (simargv
[2], NULL
, 0);
1038 WLstr
[ENDWL
] = strdup (simargv
[1]);
1039 fprintf (stderr
, "Added %s (%x) to watchlist, #%d\n",WLstr
[ENDWL
],
1043 else if (strcmp (simargv
[0], "dumpmem") == 0)
1048 if (simargv
[1] == NULL
)
1049 fprintf (stderr
, "Error: missing argument to dumpmem cmd.\n");
1051 fprintf (stderr
, "Writing dumpfile %s...",simargv
[1]);
1053 dumpfile
= fopen (simargv
[1], "w");
1055 fwrite (p
, CPU
.msize
-1, 1, dumpfile
);
1058 fprintf (stderr
, "done.\n");
1060 else if (strcmp (simargv
[0], "clearstats") == 0)
1066 else if (strcmp (simargv
[0], "verbose") == 0)
1072 fprintf (stderr
,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
1078 fprintf (stderr
, "M.CORE sim commands: \n");
1079 fprintf (stderr
, " watch <funcname> <addr>\n");
1080 fprintf (stderr
, " dumpmem <filename>\n");
1081 fprintf (stderr
, " clearstats\n");
1082 fprintf (stderr
, " verbose\n");
1087 sim_set_callbacks (host_callback
*ptr
)
1093 sim_complete_command (SIM_DESC sd
, const char *text
, const char *word
)