1 /* Simulator for Xilinx MicroBlaze processor
2 Copyright 2009-2012 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
24 #include <sys/times.h>
25 #include <sys/param.h>
26 #include <netinet/in.h> /* for byte ordering macros */
28 #include "gdb/callback.h"
29 #include "libiberty.h"
30 #include "gdb/remote-sim.h"
32 #include "sim-utils.h"
33 #include "microblaze-dis.h"
37 #define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
40 static int target_big_endian
= 1;
41 static unsigned long heap_ptr
= 0;
42 static unsigned long stack_ptr
= 0;
43 host_callback
*callback
;
46 microblaze_extract_unsigned_integer (unsigned char *addr
, int len
)
50 unsigned char *startaddr
= (unsigned char *)addr
;
51 unsigned char *endaddr
= startaddr
+ len
;
53 if (len
> (int) sizeof (unsigned long))
54 printf ("That operation is not available on integers of more than "
55 "%d bytes.", sizeof (unsigned long));
57 /* Start at the most significant end of the integer, and work towards
58 the least significant. */
61 if (!target_big_endian
)
63 for (p
= endaddr
; p
> startaddr
;)
64 retval
= (retval
<< 8) | * -- p
;
68 for (p
= startaddr
; p
< endaddr
;)
69 retval
= (retval
<< 8) | * p
++;
76 microblaze_store_unsigned_integer (unsigned char *addr
, int len
,
80 unsigned char *startaddr
= (unsigned char *)addr
;
81 unsigned char *endaddr
= startaddr
+ len
;
83 if (!target_big_endian
)
85 for (p
= startaddr
; p
< endaddr
;)
93 for (p
= endaddr
; p
> startaddr
;)
101 struct sim_state microblaze_state
;
105 static SIM_OPEN_KIND sim_kind
;
108 static int issue_messages
= 0;
111 int_sbrk (int inc_bytes
)
117 heap_ptr
+= inc_bytes
;
119 if (issue_messages
&& heap_ptr
> SP
)
120 fprintf (stderr
, "Warning: heap_ptr overlaps stack!\n");
125 static void /* INLINE */
126 wbat (word x
, word v
)
128 if (((uword
)x
) >= CPU
.msize
)
131 fprintf (stderr
, "byte write to 0x%x outside memory range\n", x
);
133 CPU
.exception
= SIGSEGV
;
137 unsigned char *p
= CPU
.memory
+ x
;
142 static void /* INLINE */
143 wlat (word x
, word v
)
145 if (((uword
)x
) >= CPU
.msize
)
148 fprintf (stderr
, "word write to 0x%x outside memory range\n", x
);
150 CPU
.exception
= SIGSEGV
;
157 fprintf (stderr
, "word write to unaligned memory address: 0x%x\n", x
);
159 CPU
.exception
= SIGBUS
;
161 else if (!target_big_endian
)
163 unsigned char *p
= CPU
.memory
+ x
;
171 unsigned char *p
= CPU
.memory
+ x
;
180 static void /* INLINE */
181 what (word x
, word v
)
183 if (((uword
)x
) >= CPU
.msize
)
186 fprintf (stderr
, "short write to 0x%x outside memory range\n", x
);
188 CPU
.exception
= SIGSEGV
;
195 fprintf (stderr
, "short write to unaligned memory address: 0x%x\n",
198 CPU
.exception
= SIGBUS
;
200 else if (!target_big_endian
)
202 unsigned char *p
= CPU
.memory
+ x
;
208 unsigned char *p
= CPU
.memory
+ x
;
215 /* Read functions. */
216 static int /* INLINE */
219 if (((uword
)x
) >= CPU
.msize
)
222 fprintf (stderr
, "byte read from 0x%x outside memory range\n", x
);
224 CPU
.exception
= SIGSEGV
;
229 unsigned char *p
= CPU
.memory
+ x
;
234 static int /* INLINE */
237 if (((uword
) x
) >= CPU
.msize
)
240 fprintf (stderr
, "word read from 0x%x outside memory range\n", x
);
242 CPU
.exception
= SIGSEGV
;
250 fprintf (stderr
, "word read from unaligned address: 0x%x\n", x
);
252 CPU
.exception
= SIGBUS
;
255 else if (! target_big_endian
)
257 unsigned char *p
= CPU
.memory
+ x
;
258 return (p
[3] << 24) | (p
[2] << 16) | (p
[1] << 8) | p
[0];
262 unsigned char *p
= CPU
.memory
+ x
;
263 return (p
[0] << 24) | (p
[1] << 16) | (p
[2] << 8) | p
[3];
268 static int /* INLINE */
271 if (((uword
)x
) >= CPU
.msize
)
274 fprintf (stderr
, "short read from 0x%x outside memory range\n", x
);
276 CPU
.exception
= SIGSEGV
;
284 fprintf (stderr
, "short read from unaligned address: 0x%x\n", x
);
286 CPU
.exception
= SIGBUS
;
289 else if (!target_big_endian
)
291 unsigned char *p
= CPU
.memory
+ x
;
292 return (p
[1] << 8) | p
[0];
296 unsigned char *p
= CPU
.memory
+ x
;
297 return (p
[0] << 8) | p
[1];
303 #define SEXTB(x) (((x & 0xff) ^ (~ 0x7f)) + 0x80)
304 #define SEXTW(y) ((int)((short)y))
307 IOMEM (int addr
, int write
, int value
)
311 /* Default to a 8 Mbyte (== 2^23) memory space. */
312 static int sim_memory_size
= 1 << 23;
314 #define MEM_SIZE_FLOOR 64
318 sim_memory_size
= size
;
319 CPU
.msize
= sim_memory_size
;
324 CPU
.memory
= (unsigned char *) calloc (1, CPU
.msize
);
330 "Not enough VM for simulation of %d bytes of RAM\n",
334 CPU
.memory
= (unsigned char *) calloc (1, 1);
341 if (CPU
.msize
!= (sim_memory_size
))
342 sim_size (sim_memory_size
);
350 unsigned long memsize
;
354 /* Set up machine just out of reset. */
358 memsize
= CPU
.msize
/ (1024 * 1024);
360 if (issue_messages
> 1)
361 fprintf (stderr
, "Simulated memory of %d Mbytes (0x0 .. 0x%08x)\n",
362 memsize
, CPU
.msize
- 1);
364 /* Clean out the GPRs */
365 for (i
= 0; i
< 32; i
++)
376 CPU
.exception
= SIGINT
;
379 /* Functions so that trapped open/close don't interfere with the
380 parent's functions. We say that we can't close the descriptors
381 that we didn't open. exit() and cleanup() get in trouble here,
382 to some extent. That's the price of emulation. */
384 unsigned char opened
[100];
389 if (fd
< 0 || fd
> NUM_ELEM (opened
))
398 if (fd
< 0 || fd
> NUM_ELEM (opened
))
407 if (fd
< 0 || fd
> NUM_ELEM (opened
))
419 process_stub (int what
)
421 /* These values should match those in libgloss/microblaze/syscalls.s. */
428 case 10: /* _unlink */
429 case 19: /* _lseek */
430 case 43: /* _times */
436 fprintf (stderr
, "Unhandled stub opcode: %d\n", what
);
447 CPU
.exception
= SIGQUIT
;
456 for (s
= (unsigned char *)a
[0], i
= 1 ; *s
&& i
< 6 ; s
++)
464 fprintf (stderr
, "WARNING: scanf unimplemented\n");
471 process_stub (CPU
.regs
[1]);
476 fprintf (stderr
, "Unhandled util code: %x\n", what
);
481 /* For figuring out whether we carried; addc/subc use this. */
483 iu_carry (unsigned long a
, unsigned long b
, int cin
)
487 x
= (a
& 0xffff) + (b
& 0xffff) + cin
;
488 x
= (x
>> 16) + (a
>> 16) + (b
>> 16);
494 #define WATCHFUNCTIONS 1
495 #ifdef WATCHFUNCTIONS
512 static int tracing
= 0;
515 sim_resume (SIM_DESC sd
, int step
, int siggnal
)
519 enum microblaze_instr op
;
532 short delay_slot_enable
;
534 short num_delay_slot
; /* UNUSED except as reqd parameter */
535 enum microblaze_instr_type insn_type
;
537 sigsave
= signal (SIGINT
, interrupt
);
538 CPU
.exception
= step
? SIGTRAP
: 0;
546 /* Fetch the initial instructions that we'll decode. */
547 inst
= rlat (PC
& 0xFFFFFFFC);
549 op
= get_insn_microblaze (inst
, &imm_unsigned
, &insn_type
,
552 if (op
== invalid_inst
)
553 fprintf (stderr
, "Unknown instruction 0x%04x", inst
);
556 fprintf (stderr
, "%.4x: inst = %.4x ", PC
, inst
);
561 /* immword = IMM_W; */
564 delay_slot_enable
= 0;
566 if (op
== microblaze_brk
)
567 CPU
.exception
= SIGTRAP
;
568 else if (inst
== MICROBLAZE_HALT_INST
)
570 CPU
.exception
= SIGQUIT
;
578 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
582 #include "microblaze.isa"
586 CPU
.exception
= SIGILL
;
587 fprintf (stderr
, "ERROR: Unknown opcode\n");
589 /* Make R0 consistent */
592 /* Check for imm instr */
598 /* Update cycle counts */
600 if (insn_type
== memory_store_inst
|| insn_type
== memory_load_inst
)
602 if (insn_type
== mult_inst
)
604 if (insn_type
== barrel_shift_inst
)
606 if (insn_type
== anyware_inst
)
608 if (insn_type
== div_inst
)
611 if ((insn_type
== branch_inst
|| insn_type
== return_inst
)
614 /* Add an extra cycle for taken branches */
616 /* For branch instructions handle the instruction in the delay slot */
617 if (delay_slot_enable
)
620 PC
= oldpc
+ INST_SIZE
;
621 inst
= rlat (PC
& 0xFFFFFFFC);
622 op
= get_insn_microblaze (inst
, &imm_unsigned
, &insn_type
,
624 if (op
== invalid_inst
)
625 fprintf (stderr
, "Unknown instruction 0x%04x", inst
);
627 fprintf (stderr
, "%.4x: inst = %.4x ", PC
, inst
);
631 /* immword = IMM_W; */
632 if (op
== microblaze_brk
)
635 fprintf (stderr
, "Breakpoint set in delay slot "
636 "(at address 0x%x) will not be honored\n", PC
);
637 /* ignore the breakpoint */
639 else if (insn_type
== branch_inst
|| insn_type
== return_inst
)
642 fprintf (stderr
, "Cannot have branch or return instructions "
643 "in delay slot (at address 0x%x)\n", PC
);
644 CPU
.exception
= SIGILL
;
650 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
654 #include "microblaze.isa"
658 CPU
.exception
= SIGILL
;
659 fprintf (stderr
, "ERROR: Unknown opcode at 0x%x\n", PC
);
661 /* Update cycle counts */
663 if (insn_type
== memory_store_inst
664 || insn_type
== memory_load_inst
)
666 if (insn_type
== mult_inst
)
668 if (insn_type
== barrel_shift_inst
)
670 if (insn_type
== anyware_inst
)
672 if (insn_type
== div_inst
)
677 /* Make R0 consistent */
679 /* Check for imm instr */
686 /* no delay slot: increment cycle count */
692 fprintf (stderr
, "\n");
694 while (!CPU
.exception
);
696 /* Hide away the things we've cached while executing. */
698 CPU
.insts
+= insts
; /* instructions done ... */
699 CPU
.cycles
+= insts
; /* and each takes a cycle */
700 CPU
.cycles
+= bonus_cycles
; /* and extra cycles for branches */
701 CPU
.cycles
+= memops
; /* and memop cycle delays */
703 signal (SIGINT
, sigsave
);
708 sim_write (SIM_DESC sd
, SIM_ADDR addr
, const unsigned char *buffer
, int size
)
713 memcpy (&CPU
.memory
[addr
], buffer
, size
);
719 sim_read (SIM_DESC sd
, SIM_ADDR addr
, unsigned char *buffer
, int size
)
724 memcpy (buffer
, &CPU
.memory
[addr
], size
);
731 sim_store_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
735 if (rn
< NUM_REGS
+ NUM_SPECIAL
&& rn
>= 0)
739 /* misalignment safe */
740 long ival
= microblaze_extract_unsigned_integer (memory
, 4);
744 CPU
.spregs
[rn
-NUM_REGS
] = ival
;
755 sim_fetch_register (SIM_DESC sd
, int rn
, unsigned char *memory
, int length
)
760 if (rn
< NUM_REGS
+ NUM_SPECIAL
&& rn
>= 0)
767 ival
= CPU
.spregs
[rn
-NUM_REGS
];
769 /* misalignment-safe */
770 microblaze_store_unsigned_integer (memory
, 4, ival
);
782 sim_trace (SIM_DESC sd
)
786 sim_resume (sd
, 0, 0);
794 sim_stop_reason (SIM_DESC sd
, enum sim_stop
*reason
, int *sigrc
)
796 if (CPU
.exception
== SIGQUIT
)
798 *reason
= sim_exited
;
803 *reason
= sim_stopped
;
804 *sigrc
= CPU
.exception
;
810 sim_stop (SIM_DESC sd
)
812 CPU
.exception
= SIGINT
;
818 sim_info (SIM_DESC sd
, int verbose
)
820 #ifdef WATCHFUNCTIONS
824 callback
->printf_filtered (callback
, "\n\n# instructions executed %10d\n",
826 callback
->printf_filtered (callback
, "# cycles %10d\n",
827 (CPU
.cycles
) ? CPU
.cycles
+2 : 0);
829 #ifdef WATCHFUNCTIONS
830 callback
->printf_filtered (callback
, "\nNumber of watched functions: %d\n",
835 for (w
= 1; w
<= ENDWL
; w
++)
837 callback
->printf_filtered (callback
, "WL = %s %8x\n",WLstr
[w
],WL
[w
]);
838 callback
->printf_filtered (callback
, " calls = %d, cycles = %d\n",
842 callback
->printf_filtered (callback
,
843 " maxcpc = %d, mincpc = %d, avecpc = %d\n",
844 WLmax
[w
],WLmin
[w
],WLcyc
[w
]/WLcnts
[w
]);
848 callback
->printf_filtered (callback
,
849 "Total cycles for watched functions: %d\n",wcyc
);
855 unsigned char sa_machtype
[2];
856 unsigned char sa_magic
[2];
857 unsigned char sa_tsize
[4];
858 unsigned char sa_dsize
[4];
859 unsigned char sa_bsize
[4];
860 unsigned char sa_syms
[4];
861 unsigned char sa_entry
[4];
862 unsigned char sa_trelo
[4];
863 unsigned char sa_drelo
[4];
866 #define LONG(x) (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
867 #define SHORT(x) (((x)[0]<<8)|(x)[1])
870 sim_open (SIM_OPEN_KIND kind
, host_callback
*cb
, struct bfd
*abfd
, char **argv
)
872 /* SIM_DESC sd = sim_state_alloc(kind, alloc);*/
874 int osize
= sim_memory_size
;
878 if (kind
== SIM_OPEN_STANDALONE
)
881 /* Discard and reacquire memory -- start with a clean slate. */
882 sim_size (1); /* small */
883 sim_size (osize
); /* and back again */
885 set_initial_gprs (); /* Reset the GPR registers. */
887 return ((SIM_DESC
) 1);
891 sim_close (SIM_DESC sd
, int quitting
)
902 sim_load (SIM_DESC sd
, char *prog
, bfd
*abfd
, int from_tty
)
904 /* Do the right thing for ELF executables; this turns out to be
905 just about the right thing for any object format that:
906 - we crack using BFD routines
907 - follows the traditional UNIX text/data/bss layout
908 - calls the bss section ".bss". */
910 extern bfd
*sim_load_file (); /* ??? Don't know where this should live. */
916 int found_loadable_section
= 0;
917 bfd_vma max_addr
= 0;
918 handle
= bfd_openr (prog
, 0);
922 printf("``%s'' could not be opened.\n", prog
);
926 /* Makes sure that we have an object file, also cleans gets the
927 section headers in place. */
928 if (!bfd_check_format (handle
, bfd_object
))
930 /* wasn't an object file */
932 printf ("``%s'' is not appropriate object file.\n", prog
);
936 for (s
= handle
->sections
; s
; s
= s
->next
)
938 if (s
->flags
& SEC_ALLOC
)
941 int size
= bfd_get_section_size (s
);
944 vma
= bfd_section_vma (handle
, s
);
947 max_addr
= vma
+ size
;
950 if (s
->flags
& SEC_LOAD
)
951 found_loadable_section
= 1;
955 if (!found_loadable_section
)
957 /* No loadable sections */
959 printf("No loadable sections in file %s\n", prog
);
963 sim_memory_size
= (unsigned long) max_addr
;
965 /* Clean up after ourselves. */
971 prog_bfd
= sim_load_file (sd
, myname
, callback
, prog
, abfd
,
972 /* sim_kind == SIM_OPEN_DEBUG, */
975 if (prog_bfd
== NULL
)
978 target_big_endian
= bfd_big_endian (prog_bfd
);
979 PC
= bfd_get_start_address (prog_bfd
);
982 bfd_close (prog_bfd
);
988 sim_create_inferior (SIM_DESC sd
, struct bfd
*prog_bfd
, char **argv
, char **env
)
995 unsigned long strings
;
996 unsigned long pointers
;
997 unsigned long hi_stack
;
1000 /* Set the initial register set. */
1003 set_initial_gprs ();
1006 hi_stack
= CPU
.msize
- 4;
1007 PC
= bfd_get_start_address (prog_bfd
);
1009 /* For now ignore all parameters to the program */
1015 sim_kill (SIM_DESC sd
)
1021 sim_do_command (SIM_DESC sd
, char * cmd
)
1023 /* Nothing there yet; it's all an error. */
1027 char ** simargv
= buildargv (cmd
);
1029 if (strcmp (simargv
[0], "watch") == 0)
1031 if ((simargv
[1] == NULL
) || (simargv
[2] == NULL
))
1033 fprintf (stderr
, "Error: missing argument to watch cmd.\n");
1039 WL
[ENDWL
] = strtol (simargv
[2], NULL
, 0);
1040 WLstr
[ENDWL
] = strdup (simargv
[1]);
1041 fprintf (stderr
, "Added %s (%x) to watchlist, #%d\n",WLstr
[ENDWL
],
1045 else if (strcmp (simargv
[0], "dumpmem") == 0)
1050 if (simargv
[1] == NULL
)
1051 fprintf (stderr
, "Error: missing argument to dumpmem cmd.\n");
1053 fprintf (stderr
, "Writing dumpfile %s...",simargv
[1]);
1055 dumpfile
= fopen (simargv
[1], "w");
1057 fwrite (p
, CPU
.msize
-1, 1, dumpfile
);
1060 fprintf (stderr
, "done.\n");
1062 else if (strcmp (simargv
[0], "clearstats") == 0)
1068 else if (strcmp (simargv
[0], "verbose") == 0)
1074 fprintf (stderr
,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
1080 fprintf (stderr
, "M.CORE sim commands: \n");
1081 fprintf (stderr
, " watch <funcname> <addr>\n");
1082 fprintf (stderr
, " dumpmem <filename>\n");
1083 fprintf (stderr
, " clearstats\n");
1084 fprintf (stderr
, " verbose\n");
1089 sim_set_callbacks (host_callback
*ptr
)
1095 sim_complete_command (SIM_DESC sd
, char *text
, char *word
)