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
++)
371 /* Functions so that trapped open/close don't interfere with the
372 parent's functions. We say that we can't close the descriptors
373 that we didn't open. exit() and cleanup() get in trouble here,
374 to some extent. That's the price of emulation. */
376 unsigned char opened
[100];
381 if (fd
< 0 || fd
> NUM_ELEM (opened
))
390 if (fd
< 0 || fd
> NUM_ELEM (opened
))
399 if (fd
< 0 || fd
> NUM_ELEM (opened
))
411 process_stub (int what
)
413 /* These values should match those in libgloss/microblaze/syscalls.s. */
420 case 10: /* _unlink */
421 case 19: /* _lseek */
422 case 43: /* _times */
428 fprintf (stderr
, "Unhandled stub opcode: %d\n", what
);
439 CPU
.exception
= SIGQUIT
;
448 for (s
= (unsigned char *)a
[0], i
= 1 ; *s
&& i
< 6 ; s
++)
456 fprintf (stderr
, "WARNING: scanf unimplemented\n");
463 process_stub (CPU
.regs
[1]);
468 fprintf (stderr
, "Unhandled util code: %x\n", what
);
473 /* For figuring out whether we carried; addc/subc use this. */
475 iu_carry (unsigned long a
, unsigned long b
, int cin
)
479 x
= (a
& 0xffff) + (b
& 0xffff) + cin
;
480 x
= (x
>> 16) + (a
>> 16) + (b
>> 16);
486 #define WATCHFUNCTIONS 1
487 #ifdef WATCHFUNCTIONS
504 static int tracing
= 0;
507 sim_resume (SIM_DESC sd
, int step
, int siggnal
)
511 enum microblaze_instr op
;
523 short delay_slot_enable
;
525 short num_delay_slot
; /* UNUSED except as reqd parameter */
526 enum microblaze_instr_type insn_type
;
528 CPU
.exception
= step
? SIGTRAP
: 0;
536 /* Fetch the initial instructions that we'll decode. */
537 inst
= rlat (PC
& 0xFFFFFFFC);
539 op
= get_insn_microblaze (inst
, &imm_unsigned
, &insn_type
,
542 if (op
== invalid_inst
)
543 fprintf (stderr
, "Unknown instruction 0x%04x", inst
);
546 fprintf (stderr
, "%.4x: inst = %.4x ", PC
, inst
);
551 /* immword = IMM_W; */
554 delay_slot_enable
= 0;
556 if (op
== microblaze_brk
)
557 CPU
.exception
= SIGTRAP
;
558 else if (inst
== MICROBLAZE_HALT_INST
)
560 CPU
.exception
= SIGQUIT
;
568 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
572 #include "microblaze.isa"
576 CPU
.exception
= SIGILL
;
577 fprintf (stderr
, "ERROR: Unknown opcode\n");
579 /* Make R0 consistent */
582 /* Check for imm instr */
588 /* Update cycle counts */
590 if (insn_type
== memory_store_inst
|| insn_type
== memory_load_inst
)
592 if (insn_type
== mult_inst
)
594 if (insn_type
== barrel_shift_inst
)
596 if (insn_type
== anyware_inst
)
598 if (insn_type
== div_inst
)
601 if ((insn_type
== branch_inst
|| insn_type
== return_inst
)
604 /* Add an extra cycle for taken branches */
606 /* For branch instructions handle the instruction in the delay slot */
607 if (delay_slot_enable
)
610 PC
= oldpc
+ INST_SIZE
;
611 inst
= rlat (PC
& 0xFFFFFFFC);
612 op
= get_insn_microblaze (inst
, &imm_unsigned
, &insn_type
,
614 if (op
== invalid_inst
)
615 fprintf (stderr
, "Unknown instruction 0x%04x", inst
);
617 fprintf (stderr
, "%.4x: inst = %.4x ", PC
, inst
);
621 /* immword = IMM_W; */
622 if (op
== microblaze_brk
)
625 fprintf (stderr
, "Breakpoint set in delay slot "
626 "(at address 0x%x) will not be honored\n", PC
);
627 /* ignore the breakpoint */
629 else if (insn_type
== branch_inst
|| insn_type
== return_inst
)
632 fprintf (stderr
, "Cannot have branch or return instructions "
633 "in delay slot (at address 0x%x)\n", PC
);
634 CPU
.exception
= SIGILL
;
640 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
644 #include "microblaze.isa"
648 CPU
.exception
= SIGILL
;
649 fprintf (stderr
, "ERROR: Unknown opcode at 0x%x\n", PC
);
651 /* Update cycle counts */
653 if (insn_type
== memory_store_inst
654 || insn_type
== memory_load_inst
)
656 if (insn_type
== mult_inst
)
658 if (insn_type
== barrel_shift_inst
)
660 if (insn_type
== anyware_inst
)
662 if (insn_type
== div_inst
)
667 /* Make R0 consistent */
669 /* Check for imm instr */
676 /* no delay slot: increment cycle count */
682 fprintf (stderr
, "\n");
684 while (!CPU
.exception
);
686 /* Hide away the things we've cached while executing. */
688 CPU
.insts
+= insts
; /* instructions done ... */
689 CPU
.cycles
+= insts
; /* and each takes a cycle */
690 CPU
.cycles
+= bonus_cycles
; /* and extra cycles for branches */
691 CPU
.cycles
+= memops
; /* and memop cycle delays */
696 sim_write (SIM_DESC sd
, SIM_ADDR addr
, const unsigned char *buffer
, int size
)
701 memcpy (&CPU
.memory
[addr
], buffer
, size
);
707 sim_read (SIM_DESC sd
, SIM_ADDR addr
, unsigned char *buffer
, int size
)
712 memcpy (buffer
, &CPU
.memory
[addr
], size
);
719 sim_store_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
723 if (rn
< NUM_REGS
+ NUM_SPECIAL
&& rn
>= 0)
727 /* misalignment safe */
728 long ival
= microblaze_extract_unsigned_integer (memory
, 4);
732 CPU
.spregs
[rn
-NUM_REGS
] = ival
;
743 sim_fetch_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
748 if (rn
< NUM_REGS
+ NUM_SPECIAL
&& rn
>= 0)
755 ival
= CPU
.spregs
[rn
-NUM_REGS
];
757 /* misalignment-safe */
758 microblaze_store_unsigned_integer (memory
, 4, ival
);
770 sim_trace (SIM_DESC sd
)
774 sim_resume (sd
, 0, 0);
782 sim_stop_reason (SIM_DESC sd
, enum sim_stop
*reason
, int *sigrc
)
784 if (CPU
.exception
== SIGQUIT
)
786 *reason
= sim_exited
;
791 *reason
= sim_stopped
;
792 *sigrc
= CPU
.exception
;
798 sim_stop (SIM_DESC sd
)
800 CPU
.exception
= SIGINT
;
806 sim_info (SIM_DESC sd
, int verbose
)
808 #ifdef WATCHFUNCTIONS
812 callback
->printf_filtered (callback
, "\n\n# instructions executed %10d\n",
814 callback
->printf_filtered (callback
, "# cycles %10d\n",
815 (CPU
.cycles
) ? CPU
.cycles
+2 : 0);
817 #ifdef WATCHFUNCTIONS
818 callback
->printf_filtered (callback
, "\nNumber of watched functions: %d\n",
823 for (w
= 1; w
<= ENDWL
; w
++)
825 callback
->printf_filtered (callback
, "WL = %s %8x\n",WLstr
[w
],WL
[w
]);
826 callback
->printf_filtered (callback
, " calls = %d, cycles = %d\n",
830 callback
->printf_filtered (callback
,
831 " maxcpc = %d, mincpc = %d, avecpc = %d\n",
832 WLmax
[w
],WLmin
[w
],WLcyc
[w
]/WLcnts
[w
]);
836 callback
->printf_filtered (callback
,
837 "Total cycles for watched functions: %d\n",wcyc
);
843 unsigned char sa_machtype
[2];
844 unsigned char sa_magic
[2];
845 unsigned char sa_tsize
[4];
846 unsigned char sa_dsize
[4];
847 unsigned char sa_bsize
[4];
848 unsigned char sa_syms
[4];
849 unsigned char sa_entry
[4];
850 unsigned char sa_trelo
[4];
851 unsigned char sa_drelo
[4];
854 #define LONG(x) (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
855 #define SHORT(x) (((x)[0]<<8)|(x)[1])
858 sim_open (SIM_OPEN_KIND kind
, host_callback
*cb
, struct bfd
*abfd
, char **argv
)
860 /* SIM_DESC sd = sim_state_alloc(kind, alloc);*/
862 int osize
= sim_memory_size
;
866 if (kind
== SIM_OPEN_STANDALONE
)
869 /* Discard and reacquire memory -- start with a clean slate. */
870 sim_size (1); /* small */
871 sim_size (osize
); /* and back again */
873 set_initial_gprs (); /* Reset the GPR registers. */
875 return ((SIM_DESC
) 1);
879 sim_close (SIM_DESC sd
, int quitting
)
890 sim_load (SIM_DESC sd
, const char *prog
, bfd
*abfd
, int from_tty
)
892 /* Do the right thing for ELF executables; this turns out to be
893 just about the right thing for any object format that:
894 - we crack using BFD routines
895 - follows the traditional UNIX text/data/bss layout
896 - calls the bss section ".bss". */
898 extern bfd
*sim_load_file (); /* ??? Don't know where this should live. */
904 int found_loadable_section
= 0;
905 bfd_vma max_addr
= 0;
906 handle
= bfd_openr (prog
, 0);
910 printf("``%s'' could not be opened.\n", prog
);
914 /* Makes sure that we have an object file, also cleans gets the
915 section headers in place. */
916 if (!bfd_check_format (handle
, bfd_object
))
918 /* wasn't an object file */
920 printf ("``%s'' is not appropriate object file.\n", prog
);
924 for (s
= handle
->sections
; s
; s
= s
->next
)
926 if (s
->flags
& SEC_ALLOC
)
929 int size
= bfd_get_section_size (s
);
932 vma
= bfd_section_vma (handle
, s
);
935 max_addr
= vma
+ size
;
938 if (s
->flags
& SEC_LOAD
)
939 found_loadable_section
= 1;
943 if (!found_loadable_section
)
945 /* No loadable sections */
947 printf("No loadable sections in file %s\n", prog
);
951 sim_memory_size
= (unsigned long) max_addr
;
953 /* Clean up after ourselves. */
959 prog_bfd
= sim_load_file (sd
, myname
, callback
, prog
, abfd
,
960 /* sim_kind == SIM_OPEN_DEBUG, */
963 if (prog_bfd
== NULL
)
966 target_big_endian
= bfd_big_endian (prog_bfd
);
967 PC
= bfd_get_start_address (prog_bfd
);
970 bfd_close (prog_bfd
);
976 sim_create_inferior (SIM_DESC sd
, struct bfd
*prog_bfd
, char **argv
, char **env
)
983 unsigned long strings
;
984 unsigned long pointers
;
985 unsigned long hi_stack
;
988 /* Set the initial register set. */
994 hi_stack
= CPU
.msize
- 4;
995 PC
= bfd_get_start_address (prog_bfd
);
997 /* For now ignore all parameters to the program */
1003 sim_kill (SIM_DESC sd
)
1009 sim_do_command (SIM_DESC sd
, char * cmd
)
1011 /* Nothing there yet; it's all an error. */
1015 char ** simargv
= buildargv (cmd
);
1017 if (strcmp (simargv
[0], "watch") == 0)
1019 if ((simargv
[1] == NULL
) || (simargv
[2] == NULL
))
1021 fprintf (stderr
, "Error: missing argument to watch cmd.\n");
1027 WL
[ENDWL
] = strtol (simargv
[2], NULL
, 0);
1028 WLstr
[ENDWL
] = strdup (simargv
[1]);
1029 fprintf (stderr
, "Added %s (%x) to watchlist, #%d\n",WLstr
[ENDWL
],
1033 else if (strcmp (simargv
[0], "dumpmem") == 0)
1038 if (simargv
[1] == NULL
)
1039 fprintf (stderr
, "Error: missing argument to dumpmem cmd.\n");
1041 fprintf (stderr
, "Writing dumpfile %s...",simargv
[1]);
1043 dumpfile
= fopen (simargv
[1], "w");
1045 fwrite (p
, CPU
.msize
-1, 1, dumpfile
);
1048 fprintf (stderr
, "done.\n");
1050 else if (strcmp (simargv
[0], "clearstats") == 0)
1056 else if (strcmp (simargv
[0], "verbose") == 0)
1062 fprintf (stderr
,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
1068 fprintf (stderr
, "M.CORE sim commands: \n");
1069 fprintf (stderr
, " watch <funcname> <addr>\n");
1070 fprintf (stderr
, " dumpmem <filename>\n");
1071 fprintf (stderr
, " clearstats\n");
1072 fprintf (stderr
, " verbose\n");
1077 sim_set_callbacks (host_callback
*ptr
)
1083 sim_complete_command (SIM_DESC sd
, const char *text
, const char *word
)