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, 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)