1 /* Simulator for Xilinx MicroBlaze processor
2 Copyright 2009, 2010 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 2 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, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
23 #include <sys/times.h>
24 #include <sys/param.h>
25 #include <netinet/in.h> /* for byte ordering macros */
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 "%d 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 %d 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 %d Mbytes (0x0 .. 0x%08x)\n",
361 memsize
, CPU
.msize
- 1);
363 /* Clean out the GPRs */
364 for (i
= 0; i
< 32; i
++)
375 CPU
.exception
= SIGINT
;
378 /* Functions so that trapped open/close don't interfere with the
379 parent's functions. We say that we can't close the descriptors
380 that we didn't open. exit() and cleanup() get in trouble here,
381 to some extent. That's the price of emulation. */
383 unsigned char opened
[100];
388 if (fd
< 0 || fd
> NUM_ELEM (opened
))
397 if (fd
< 0 || fd
> NUM_ELEM (opened
))
406 if (fd
< 0 || fd
> NUM_ELEM (opened
))
418 process_stub (int what
)
420 /* These values should match those in libgloss/microblaze/syscalls.s. */
427 case 10: /* _unlink */
428 case 19: /* _lseek */
429 case 43: /* _times */
435 fprintf (stderr
, "Unhandled stub opcode: %d\n", what
);
446 CPU
.exception
= SIGQUIT
;
455 for (s
= (unsigned char *)a
[0], i
= 1 ; *s
&& i
< 6 ; s
++)
463 fprintf (stderr
, "WARNING: scanf unimplemented\n");
470 process_stub (CPU
.regs
[1]);
475 fprintf (stderr
, "Unhandled util code: %x\n", what
);
480 /* For figuring out whether we carried; addc/subc use this. */
482 iu_carry (unsigned long a
, unsigned long b
, int cin
)
486 x
= (a
& 0xffff) + (b
& 0xffff) + cin
;
487 x
= (x
>> 16) + (a
>> 16) + (b
>> 16);
493 #define WATCHFUNCTIONS 1
494 #ifdef WATCHFUNCTIONS
511 static int tracing
= 0;
514 sim_resume (SIM_DESC sd
, int step
, int siggnal
)
518 enum microblaze_instr op
;
531 short delay_slot_enable
;
533 short num_delay_slot
; /* UNUSED except as reqd parameter */
534 enum microblaze_instr_type insn_type
;
536 sigsave
= signal (SIGINT
, interrupt
);
537 CPU
.exception
= step
? SIGTRAP
: 0;
545 /* Fetch the initial instructions that we'll decode. */
546 inst
= rlat (PC
& 0xFFFFFFFC);
548 op
= get_insn_microblaze (inst
, &imm_unsigned
, &insn_type
,
551 if (op
== invalid_inst
)
552 fprintf (stderr
, "Unknown instruction 0x%04x", inst
);
555 fprintf (stderr
, "%.4x: inst = %.4x ", PC
, inst
);
560 /* immword = IMM_W; */
563 delay_slot_enable
= 0;
565 if (op
== microblaze_brk
)
566 CPU
.exception
= SIGTRAP
;
567 else if (inst
== MICROBLAZE_HALT_INST
)
569 CPU
.exception
= SIGQUIT
;
577 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
581 #include "microblaze.isa"
585 CPU
.exception
= SIGILL
;
586 fprintf (stderr
, "ERROR: Unknown opcode\n");
588 /* Make R0 consistent */
591 /* Check for imm instr */
597 /* Update cycle counts */
599 if (insn_type
== memory_store_inst
|| insn_type
== memory_load_inst
)
601 if (insn_type
== mult_inst
)
603 if (insn_type
== barrel_shift_inst
)
605 if (insn_type
== anyware_inst
)
607 if (insn_type
== div_inst
)
610 if ((insn_type
== branch_inst
|| insn_type
== return_inst
)
613 /* Add an extra cycle for taken branches */
615 /* For branch instructions handle the instruction in the delay slot */
616 if (delay_slot_enable
)
619 PC
= oldpc
+ INST_SIZE
;
620 inst
= rlat (PC
& 0xFFFFFFFC);
621 op
= get_insn_microblaze (inst
, &imm_unsigned
, &insn_type
,
623 if (op
== invalid_inst
)
624 fprintf (stderr
, "Unknown instruction 0x%04x", inst
);
626 fprintf (stderr
, "%.4x: inst = %.4x ", PC
, inst
);
630 /* immword = IMM_W; */
631 if (op
== microblaze_brk
)
634 fprintf (stderr
, "Breakpoint set in delay slot "
635 "(at address 0x%x) will not be honored\n", PC
);
636 /* ignore the breakpoint */
638 else if (insn_type
== branch_inst
|| insn_type
== return_inst
)
641 fprintf (stderr
, "Cannot have branch or return instructions "
642 "in delay slot (at address 0x%x)\n", PC
);
643 CPU
.exception
= SIGILL
;
649 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
653 #include "microblaze.isa"
657 CPU
.exception
= SIGILL
;
658 fprintf (stderr
, "ERROR: Unknown opcode at 0x%x\n", PC
);
660 /* Update cycle counts */
662 if (insn_type
== memory_store_inst
663 || insn_type
== memory_load_inst
)
665 if (insn_type
== mult_inst
)
667 if (insn_type
== barrel_shift_inst
)
669 if (insn_type
== anyware_inst
)
671 if (insn_type
== div_inst
)
676 /* Make R0 consistent */
678 /* Check for imm instr */
685 /* no delay slot: increment cycle count */
691 fprintf (stderr
, "\n");
693 while (!CPU
.exception
);
695 /* Hide away the things we've cached while executing. */
697 CPU
.insts
+= insts
; /* instructions done ... */
698 CPU
.cycles
+= insts
; /* and each takes a cycle */
699 CPU
.cycles
+= bonus_cycles
; /* and extra cycles for branches */
700 CPU
.cycles
+= memops
; /* and memop cycle delays */
702 signal (SIGINT
, sigsave
);
707 sim_write (SIM_DESC sd
, SIM_ADDR addr
, const unsigned char *buffer
, int size
)
712 memcpy (&CPU
.memory
[addr
], buffer
, size
);
718 sim_read (SIM_DESC sd
, SIM_ADDR addr
, unsigned char *buffer
, int size
)
723 memcpy (buffer
, &CPU
.memory
[addr
], size
);
730 sim_store_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
734 if (rn
< NUM_REGS
+ NUM_SPECIAL
&& rn
>= 0)
738 /* misalignment safe */
739 long ival
= microblaze_extract_unsigned_integer (memory
, 4);
743 CPU
.spregs
[rn
-NUM_REGS
] = ival
;
754 sim_fetch_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
759 if (rn
< NUM_REGS
+ NUM_SPECIAL
&& rn
>= 0)
766 ival
= CPU
.spregs
[rn
-NUM_REGS
];
768 /* misalignment-safe */
769 microblaze_store_unsigned_integer (memory
, 4, ival
);
781 sim_trace (SIM_DESC sd
)
785 sim_resume (sd
, 0, 0);
793 sim_stop_reason (SIM_DESC sd
, enum sim_stop
*reason
, int *sigrc
)
795 if (CPU
.exception
== SIGQUIT
)
797 *reason
= sim_exited
;
802 *reason
= sim_stopped
;
803 *sigrc
= CPU
.exception
;
809 sim_stop (SIM_DESC sd
)
811 CPU
.exception
= SIGINT
;
817 sim_info (SIM_DESC sd
, int verbose
)
819 #ifdef WATCHFUNCTIONS
823 callback
->printf_filtered (callback
, "\n\n# instructions executed %10d\n",
825 callback
->printf_filtered (callback
, "# cycles %10d\n",
826 (CPU
.cycles
) ? CPU
.cycles
+2 : 0);
828 #ifdef WATCHFUNCTIONS
829 callback
->printf_filtered (callback
, "\nNumber of watched functions: %d\n",
834 for (w
= 1; w
<= ENDWL
; w
++)
836 callback
->printf_filtered (callback
, "WL = %s %8x\n",WLstr
[w
],WL
[w
]);
837 callback
->printf_filtered (callback
, " calls = %d, cycles = %d\n",
841 callback
->printf_filtered (callback
,
842 " maxcpc = %d, mincpc = %d, avecpc = %d\n",
843 WLmax
[w
],WLmin
[w
],WLcyc
[w
]/WLcnts
[w
]);
847 callback
->printf_filtered (callback
,
848 "Total cycles for watched functions: %d\n",wcyc
);
854 unsigned char sa_machtype
[2];
855 unsigned char sa_magic
[2];
856 unsigned char sa_tsize
[4];
857 unsigned char sa_dsize
[4];
858 unsigned char sa_bsize
[4];
859 unsigned char sa_syms
[4];
860 unsigned char sa_entry
[4];
861 unsigned char sa_trelo
[4];
862 unsigned char sa_drelo
[4];
865 #define LONG(x) (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
866 #define SHORT(x) (((x)[0]<<8)|(x)[1])
869 sim_open (SIM_OPEN_KIND kind
, host_callback
*cb
, struct bfd
*abfd
, char **argv
)
871 /* SIM_DESC sd = sim_state_alloc(kind, alloc);*/
873 int osize
= sim_memory_size
;
877 if (kind
== SIM_OPEN_STANDALONE
)
880 /* Discard and reacquire memory -- start with a clean slate. */
881 sim_size (1); /* small */
882 sim_size (osize
); /* and back again */
884 set_initial_gprs (); /* Reset the GPR registers. */
886 return ((SIM_DESC
) 1);
890 sim_close (SIM_DESC sd
, int quitting
)
901 sim_load (SIM_DESC sd
, char *prog
, bfd
*abfd
, int from_tty
)
903 /* Do the right thing for ELF executables; this turns out to be
904 just about the right thing for any object format that:
905 - we crack using BFD routines
906 - follows the traditional UNIX text/data/bss layout
907 - calls the bss section ".bss". */
909 extern bfd
*sim_load_file (); /* ??? Don't know where this should live. */
915 int found_loadable_section
= 0;
916 bfd_vma max_addr
= 0;
917 handle
= bfd_openr (prog
, 0);
921 printf("``%s'' could not be opened.\n", prog
);
925 /* Makes sure that we have an object file, also cleans gets the
926 section headers in place. */
927 if (!bfd_check_format (handle
, bfd_object
))
929 /* wasn't an object file */
931 printf ("``%s'' is not appropriate object file.\n", prog
);
935 for (s
= handle
->sections
; s
; s
= s
->next
)
937 if (s
->flags
& SEC_ALLOC
)
940 int size
= bfd_get_section_size (s
);
943 vma
= bfd_section_vma (handle
, s
);
946 max_addr
= vma
+ size
;
949 if (s
->flags
& SEC_LOAD
)
950 found_loadable_section
= 1;
954 if (!found_loadable_section
)
956 /* No loadable sections */
958 printf("No loadable sections in file %s\n", prog
);
962 sim_memory_size
= (unsigned long) max_addr
;
964 /* Clean up after ourselves. */
970 prog_bfd
= sim_load_file (sd
, myname
, callback
, prog
, abfd
,
971 /* sim_kind == SIM_OPEN_DEBUG, */
974 if (prog_bfd
== NULL
)
977 target_big_endian
= bfd_big_endian (prog_bfd
);
978 PC
= bfd_get_start_address (prog_bfd
);
981 bfd_close (prog_bfd
);
987 sim_create_inferior (SIM_DESC sd
, struct bfd
*prog_bfd
, char **argv
, char **env
)
994 unsigned long strings
;
995 unsigned long pointers
;
996 unsigned long hi_stack
;
999 /* Set the initial register set. */
1002 set_initial_gprs ();
1005 hi_stack
= CPU
.msize
- 4;
1006 PC
= bfd_get_start_address (prog_bfd
);
1008 /* For now ignore all parameters to the program */
1014 sim_kill (SIM_DESC sd
)
1020 sim_do_command (SIM_DESC sd
, char * cmd
)
1022 /* Nothing there yet; it's all an error. */
1026 char ** simargv
= buildargv (cmd
);
1028 if (strcmp (simargv
[0], "watch") == 0)
1030 if ((simargv
[1] == NULL
) || (simargv
[2] == NULL
))
1032 fprintf (stderr
, "Error: missing argument to watch cmd.\n");
1038 WL
[ENDWL
] = strtol (simargv
[2], NULL
, 0);
1039 WLstr
[ENDWL
] = strdup (simargv
[1]);
1040 fprintf (stderr
, "Added %s (%x) to watchlist, #%d\n",WLstr
[ENDWL
],
1044 else if (strcmp (simargv
[0], "dumpmem") == 0)
1049 if (simargv
[1] == NULL
)
1050 fprintf (stderr
, "Error: missing argument to dumpmem cmd.\n");
1052 fprintf (stderr
, "Writing dumpfile %s...",simargv
[1]);
1054 dumpfile
= fopen (simargv
[1], "w");
1056 fwrite (p
, CPU
.msize
-1, 1, dumpfile
);
1059 fprintf (stderr
, "done.\n");
1061 else if (strcmp (simargv
[0], "clearstats") == 0)
1067 else if (strcmp (simargv
[0], "verbose") == 0)
1073 fprintf (stderr
,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
1079 fprintf (stderr
, "M.CORE sim commands: \n");
1080 fprintf (stderr
, " watch <funcname> <addr>\n");
1081 fprintf (stderr
, " dumpmem <filename>\n");
1082 fprintf (stderr
, " clearstats\n");
1083 fprintf (stderr
, " verbose\n");
1088 sim_set_callbacks (host_callback
*ptr
)