sim: mcore/microblaze: clean up a bit
[deliverable/binutils-gdb.git] / sim / microblaze / interp.c
1 /* Simulator for Xilinx MicroBlaze processor
2 Copyright 2009-2015 Free Software Foundation, Inc.
3
4 This file is part of GDB, the GNU debugger.
5
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.
10
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.
15
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/>. */
18
19 #include "config.h"
20 #include <signal.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/times.h>
24 #include <sys/param.h>
25 #include <unistd.h>
26 #include "bfd.h"
27 #include "gdb/callback.h"
28 #include "libiberty.h"
29 #include "gdb/remote-sim.h"
30 #include "run-sim.h"
31 #include "sim-main.h"
32 #include "sim-utils.h"
33 #include "microblaze-dis.h"
34
35
36 #ifndef NUM_ELEM
37 #define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
38 #endif
39
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;
44
45 static unsigned long
46 microblaze_extract_unsigned_integer (unsigned char *addr, int len)
47 {
48 unsigned long retval;
49 unsigned char *p;
50 unsigned char *startaddr = (unsigned char *)addr;
51 unsigned char *endaddr = startaddr + len;
52
53 if (len > (int) sizeof (unsigned long))
54 printf ("That operation is not available on integers of more than "
55 "%zu bytes.", sizeof (unsigned long));
56
57 /* Start at the most significant end of the integer, and work towards
58 the least significant. */
59 retval = 0;
60
61 if (!target_big_endian)
62 {
63 for (p = endaddr; p > startaddr;)
64 retval = (retval << 8) | * -- p;
65 }
66 else
67 {
68 for (p = startaddr; p < endaddr;)
69 retval = (retval << 8) | * p ++;
70 }
71
72 return retval;
73 }
74
75 static void
76 microblaze_store_unsigned_integer (unsigned char *addr, int len,
77 unsigned long val)
78 {
79 unsigned char *p;
80 unsigned char *startaddr = (unsigned char *)addr;
81 unsigned char *endaddr = startaddr + len;
82
83 if (!target_big_endian)
84 {
85 for (p = startaddr; p < endaddr;)
86 {
87 *p++ = val & 0xff;
88 val >>= 8;
89 }
90 }
91 else
92 {
93 for (p = endaddr; p > startaddr;)
94 {
95 *--p = val & 0xff;
96 val >>= 8;
97 }
98 }
99 }
100
101 struct sim_state microblaze_state;
102
103 int memcycles = 1;
104
105 static SIM_OPEN_KIND sim_kind;
106 static char *myname;
107
108 static int issue_messages = 0;
109
110 static void /* INLINE */
111 wbat (word x, word v)
112 {
113 if (((uword)x) >= CPU.msize)
114 {
115 if (issue_messages)
116 fprintf (stderr, "byte write to 0x%x outside memory range\n", x);
117
118 CPU.exception = SIGSEGV;
119 }
120 else
121 {
122 unsigned char *p = CPU.memory + x;
123 p[0] = v;
124 }
125 }
126
127 static void /* INLINE */
128 wlat (word x, word v)
129 {
130 if (((uword)x) >= CPU.msize)
131 {
132 if (issue_messages)
133 fprintf (stderr, "word write to 0x%x outside memory range\n", x);
134
135 CPU.exception = SIGSEGV;
136 }
137 else
138 {
139 if ((x & 3) != 0)
140 {
141 if (issue_messages)
142 fprintf (stderr, "word write to unaligned memory address: 0x%x\n", x);
143
144 CPU.exception = SIGBUS;
145 }
146 else if (!target_big_endian)
147 {
148 unsigned char *p = CPU.memory + x;
149 p[3] = v >> 24;
150 p[2] = v >> 16;
151 p[1] = v >> 8;
152 p[0] = v;
153 }
154 else
155 {
156 unsigned char *p = CPU.memory + x;
157 p[0] = v >> 24;
158 p[1] = v >> 16;
159 p[2] = v >> 8;
160 p[3] = v;
161 }
162 }
163 }
164
165 static void /* INLINE */
166 what (word x, word v)
167 {
168 if (((uword)x) >= CPU.msize)
169 {
170 if (issue_messages)
171 fprintf (stderr, "short write to 0x%x outside memory range\n", x);
172
173 CPU.exception = SIGSEGV;
174 }
175 else
176 {
177 if ((x & 1) != 0)
178 {
179 if (issue_messages)
180 fprintf (stderr, "short write to unaligned memory address: 0x%x\n",
181 x);
182
183 CPU.exception = SIGBUS;
184 }
185 else if (!target_big_endian)
186 {
187 unsigned char *p = CPU.memory + x;
188 p[1] = v >> 8;
189 p[0] = v;
190 }
191 else
192 {
193 unsigned char *p = CPU.memory + x;
194 p[0] = v >> 8;
195 p[1] = v;
196 }
197 }
198 }
199
200 /* Read functions. */
201 static int /* INLINE */
202 rbat (word x)
203 {
204 if (((uword)x) >= CPU.msize)
205 {
206 if (issue_messages)
207 fprintf (stderr, "byte read from 0x%x outside memory range\n", x);
208
209 CPU.exception = SIGSEGV;
210 return 0;
211 }
212 else
213 {
214 unsigned char *p = CPU.memory + x;
215 return p[0];
216 }
217 }
218
219 static int /* INLINE */
220 rlat (word x)
221 {
222 if (((uword) x) >= CPU.msize)
223 {
224 if (issue_messages)
225 fprintf (stderr, "word read from 0x%x outside memory range\n", x);
226
227 CPU.exception = SIGSEGV;
228 return 0;
229 }
230 else
231 {
232 if ((x & 3) != 0)
233 {
234 if (issue_messages)
235 fprintf (stderr, "word read from unaligned address: 0x%x\n", x);
236
237 CPU.exception = SIGBUS;
238 return 0;
239 }
240 else if (! target_big_endian)
241 {
242 unsigned char *p = CPU.memory + x;
243 return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
244 }
245 else
246 {
247 unsigned char *p = CPU.memory + x;
248 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
249 }
250 }
251 }
252
253 static int /* INLINE */
254 rhat (word x)
255 {
256 if (((uword)x) >= CPU.msize)
257 {
258 if (issue_messages)
259 fprintf (stderr, "short read from 0x%x outside memory range\n", x);
260
261 CPU.exception = SIGSEGV;
262 return 0;
263 }
264 else
265 {
266 if ((x & 1) != 0)
267 {
268 if (issue_messages)
269 fprintf (stderr, "short read from unaligned address: 0x%x\n", x);
270
271 CPU.exception = SIGBUS;
272 return 0;
273 }
274 else if (!target_big_endian)
275 {
276 unsigned char *p = CPU.memory + x;
277 return (p[1] << 8) | p[0];
278 }
279 else
280 {
281 unsigned char *p = CPU.memory + x;
282 return (p[0] << 8) | p[1];
283 }
284 }
285 }
286
287 /* Default to a 8 Mbyte (== 2^23) memory space. */
288 static int sim_memory_size = 1 << 23;
289
290 #define MEM_SIZE_FLOOR 64
291 void
292 sim_size (int size)
293 {
294 sim_memory_size = size;
295 CPU.msize = sim_memory_size;
296
297 if (CPU.memory)
298 free (CPU.memory);
299
300 CPU.memory = (unsigned char *) calloc (1, CPU.msize);
301
302 if (!CPU.memory)
303 {
304 if (issue_messages)
305 fprintf (stderr,
306 "Not enough VM for simulation of %ld bytes of RAM\n",
307 CPU.msize);
308
309 CPU.msize = 1;
310 CPU.memory = (unsigned char *) calloc (1, 1);
311 }
312 }
313
314 static void
315 init_pointers (void)
316 {
317 if (CPU.msize != (sim_memory_size))
318 sim_size (sim_memory_size);
319 }
320
321 static void
322 set_initial_gprs (void)
323 {
324 int i;
325 long space;
326 unsigned long memsize;
327
328 init_pointers ();
329
330 /* Set up machine just out of reset. */
331 PC = 0;
332 MSR = 0;
333
334 memsize = CPU.msize / (1024 * 1024);
335
336 if (issue_messages > 1)
337 fprintf (stderr, "Simulated memory of %ld Mbytes (0x0 .. 0x%08lx)\n",
338 memsize, CPU.msize - 1);
339
340 /* Clean out the GPRs */
341 for (i = 0; i < 32; i++)
342 CPU.regs[i] = 0;
343 CPU.insts = 0;
344 CPU.cycles = 0;
345 CPU.imm_enable = 0;
346 }
347
348 #define WATCHFUNCTIONS 1
349 #ifdef WATCHFUNCTIONS
350
351 #define MAXWL 80
352 word WL[MAXWL];
353 char *WLstr[MAXWL];
354
355 int ENDWL=0;
356 int WLincyc;
357 int WLcyc[MAXWL];
358 int WLcnts[MAXWL];
359 int WLmax[MAXWL];
360 int WLmin[MAXWL];
361 word WLendpc;
362 int WLbcyc;
363 int WLW;
364 #endif
365
366 static int tracing = 0;
367
368 void
369 sim_resume (SIM_DESC sd, int step, int siggnal)
370 {
371 int needfetch;
372 word inst;
373 enum microblaze_instr op;
374 int memops;
375 int bonus_cycles;
376 int insts;
377 int w;
378 int cycs;
379 word WLhash;
380 ubyte carry;
381 int imm_unsigned;
382 short ra, rb, rd;
383 long immword;
384 uword oldpc, newpc;
385 short delay_slot_enable;
386 short branch_taken;
387 short num_delay_slot; /* UNUSED except as reqd parameter */
388 enum microblaze_instr_type insn_type;
389
390 CPU.exception = step ? SIGTRAP : 0;
391
392 memops = 0;
393 bonus_cycles = 0;
394 insts = 0;
395
396 do
397 {
398 /* Fetch the initial instructions that we'll decode. */
399 inst = rlat (PC & 0xFFFFFFFC);
400
401 op = get_insn_microblaze (inst, &imm_unsigned, &insn_type,
402 &num_delay_slot);
403
404 if (op == invalid_inst)
405 fprintf (stderr, "Unknown instruction 0x%04x", inst);
406
407 if (tracing)
408 fprintf (stderr, "%.4x: inst = %.4x ", PC, inst);
409
410 rd = GET_RD;
411 rb = GET_RB;
412 ra = GET_RA;
413 /* immword = IMM_W; */
414
415 oldpc = PC;
416 delay_slot_enable = 0;
417 branch_taken = 0;
418 if (op == microblaze_brk)
419 CPU.exception = SIGTRAP;
420 else if (inst == MICROBLAZE_HALT_INST)
421 {
422 CPU.exception = SIGQUIT;
423 insts += 1;
424 bonus_cycles++;
425 }
426 else
427 {
428 switch(op)
429 {
430 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
431 case NAME: \
432 ACTION; \
433 break;
434 #include "microblaze.isa"
435 #undef INSTRUCTION
436
437 default:
438 CPU.exception = SIGILL;
439 fprintf (stderr, "ERROR: Unknown opcode\n");
440 }
441 /* Make R0 consistent */
442 CPU.regs[0] = 0;
443
444 /* Check for imm instr */
445 if (op == imm)
446 IMM_ENABLE = 1;
447 else
448 IMM_ENABLE = 0;
449
450 /* Update cycle counts */
451 insts ++;
452 if (insn_type == memory_store_inst || insn_type == memory_load_inst)
453 memops++;
454 if (insn_type == mult_inst)
455 bonus_cycles++;
456 if (insn_type == barrel_shift_inst)
457 bonus_cycles++;
458 if (insn_type == anyware_inst)
459 bonus_cycles++;
460 if (insn_type == div_inst)
461 bonus_cycles += 33;
462
463 if ((insn_type == branch_inst || insn_type == return_inst)
464 && branch_taken)
465 {
466 /* Add an extra cycle for taken branches */
467 bonus_cycles++;
468 /* For branch instructions handle the instruction in the delay slot */
469 if (delay_slot_enable)
470 {
471 newpc = PC;
472 PC = oldpc + INST_SIZE;
473 inst = rlat (PC & 0xFFFFFFFC);
474 op = get_insn_microblaze (inst, &imm_unsigned, &insn_type,
475 &num_delay_slot);
476 if (op == invalid_inst)
477 fprintf (stderr, "Unknown instruction 0x%04x", inst);
478 if (tracing)
479 fprintf (stderr, "%.4x: inst = %.4x ", PC, inst);
480 rd = GET_RD;
481 rb = GET_RB;
482 ra = GET_RA;
483 /* immword = IMM_W; */
484 if (op == microblaze_brk)
485 {
486 if (issue_messages)
487 fprintf (stderr, "Breakpoint set in delay slot "
488 "(at address 0x%x) will not be honored\n", PC);
489 /* ignore the breakpoint */
490 }
491 else if (insn_type == branch_inst || insn_type == return_inst)
492 {
493 if (issue_messages)
494 fprintf (stderr, "Cannot have branch or return instructions "
495 "in delay slot (at address 0x%x)\n", PC);
496 CPU.exception = SIGILL;
497 }
498 else
499 {
500 switch(op)
501 {
502 #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
503 case NAME: \
504 ACTION; \
505 break;
506 #include "microblaze.isa"
507 #undef INSTRUCTION
508
509 default:
510 CPU.exception = SIGILL;
511 fprintf (stderr, "ERROR: Unknown opcode at 0x%x\n", PC);
512 }
513 /* Update cycle counts */
514 insts++;
515 if (insn_type == memory_store_inst
516 || insn_type == memory_load_inst)
517 memops++;
518 if (insn_type == mult_inst)
519 bonus_cycles++;
520 if (insn_type == barrel_shift_inst)
521 bonus_cycles++;
522 if (insn_type == anyware_inst)
523 bonus_cycles++;
524 if (insn_type == div_inst)
525 bonus_cycles += 33;
526 }
527 /* Restore the PC */
528 PC = newpc;
529 /* Make R0 consistent */
530 CPU.regs[0] = 0;
531 /* Check for imm instr */
532 if (op == imm)
533 IMM_ENABLE = 1;
534 else
535 IMM_ENABLE = 0;
536 }
537 else
538 /* no delay slot: increment cycle count */
539 bonus_cycles++;
540 }
541 }
542
543 if (tracing)
544 fprintf (stderr, "\n");
545 }
546 while (!CPU.exception);
547
548 /* Hide away the things we've cached while executing. */
549 /* CPU.pc = pc; */
550 CPU.insts += insts; /* instructions done ... */
551 CPU.cycles += insts; /* and each takes a cycle */
552 CPU.cycles += bonus_cycles; /* and extra cycles for branches */
553 CPU.cycles += memops; /* and memop cycle delays */
554 }
555
556
557 int
558 sim_write (SIM_DESC sd, SIM_ADDR addr, const unsigned char *buffer, int size)
559 {
560 int i;
561 init_pointers ();
562
563 memcpy (&CPU.memory[addr], buffer, size);
564
565 return size;
566 }
567
568 int
569 sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
570 {
571 int i;
572 init_pointers ();
573
574 memcpy (buffer, &CPU.memory[addr], size);
575
576 return size;
577 }
578
579
580 int
581 sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
582 {
583 init_pointers ();
584
585 if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
586 {
587 if (length == 4)
588 {
589 /* misalignment safe */
590 long ival = microblaze_extract_unsigned_integer (memory, 4);
591 if (rn < NUM_REGS)
592 CPU.regs[rn] = ival;
593 else
594 CPU.spregs[rn-NUM_REGS] = ival;
595 return 4;
596 }
597 else
598 return 0;
599 }
600 else
601 return 0;
602 }
603
604 int
605 sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
606 {
607 long ival;
608 init_pointers ();
609
610 if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
611 {
612 if (length == 4)
613 {
614 if (rn < NUM_REGS)
615 ival = CPU.regs[rn];
616 else
617 ival = CPU.spregs[rn-NUM_REGS];
618
619 /* misalignment-safe */
620 microblaze_store_unsigned_integer (memory, 4, ival);
621 return 4;
622 }
623 else
624 return 0;
625 }
626 else
627 return 0;
628 }
629
630
631 int
632 sim_trace (SIM_DESC sd)
633 {
634 tracing = 1;
635
636 sim_resume (sd, 0, 0);
637
638 tracing = 0;
639
640 return 1;
641 }
642
643 void
644 sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
645 {
646 if (CPU.exception == SIGQUIT)
647 {
648 *reason = sim_exited;
649 *sigrc = RETREG;
650 }
651 else
652 {
653 *reason = sim_stopped;
654 *sigrc = CPU.exception;
655 }
656 }
657
658
659 int
660 sim_stop (SIM_DESC sd)
661 {
662 CPU.exception = SIGINT;
663 return 1;
664 }
665
666
667 void
668 sim_info (SIM_DESC sd, int verbose)
669 {
670 #ifdef WATCHFUNCTIONS
671 int w, wcyc;
672 #endif
673
674 callback->printf_filtered (callback, "\n\n# instructions executed %10d\n",
675 CPU.insts);
676 callback->printf_filtered (callback, "# cycles %10d\n",
677 (CPU.cycles) ? CPU.cycles+2 : 0);
678
679 #ifdef WATCHFUNCTIONS
680 callback->printf_filtered (callback, "\nNumber of watched functions: %d\n",
681 ENDWL);
682
683 wcyc = 0;
684
685 for (w = 1; w <= ENDWL; w++)
686 {
687 callback->printf_filtered (callback, "WL = %s %8x\n",WLstr[w],WL[w]);
688 callback->printf_filtered (callback, " calls = %d, cycles = %d\n",
689 WLcnts[w],WLcyc[w]);
690
691 if (WLcnts[w] != 0)
692 callback->printf_filtered (callback,
693 " maxcpc = %d, mincpc = %d, avecpc = %d\n",
694 WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]);
695 wcyc += WLcyc[w];
696 }
697
698 callback->printf_filtered (callback,
699 "Total cycles for watched functions: %d\n",wcyc);
700 #endif
701 }
702
703 struct aout
704 {
705 unsigned char sa_machtype[2];
706 unsigned char sa_magic[2];
707 unsigned char sa_tsize[4];
708 unsigned char sa_dsize[4];
709 unsigned char sa_bsize[4];
710 unsigned char sa_syms[4];
711 unsigned char sa_entry[4];
712 unsigned char sa_trelo[4];
713 unsigned char sa_drelo[4];
714 } aout;
715
716 #define LONG(x) (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
717 #define SHORT(x) (((x)[0]<<8)|(x)[1])
718
719 SIM_DESC
720 sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv)
721 {
722 /* SIM_DESC sd = sim_state_alloc(kind, alloc);*/
723
724 int osize = sim_memory_size;
725 myname = argv[0];
726 callback = cb;
727
728 if (kind == SIM_OPEN_STANDALONE)
729 issue_messages = 1;
730
731 /* Discard and reacquire memory -- start with a clean slate. */
732 sim_size (1); /* small */
733 sim_size (osize); /* and back again */
734
735 set_initial_gprs (); /* Reset the GPR registers. */
736
737 return ((SIM_DESC) 1);
738 }
739
740 void
741 sim_close (SIM_DESC sd, int quitting)
742 {
743 if (CPU.memory)
744 {
745 free(CPU.memory);
746 CPU.memory = NULL;
747 CPU.msize = 0;
748 }
749 }
750
751 SIM_RC
752 sim_load (SIM_DESC sd, const char *prog, bfd *abfd, int from_tty)
753 {
754 /* Do the right thing for ELF executables; this turns out to be
755 just about the right thing for any object format that:
756 - we crack using BFD routines
757 - follows the traditional UNIX text/data/bss layout
758 - calls the bss section ".bss". */
759
760 extern bfd *sim_load_file (); /* ??? Don't know where this should live. */
761 bfd *prog_bfd;
762
763 {
764 bfd *handle;
765 asection *s;
766 int found_loadable_section = 0;
767 bfd_vma max_addr = 0;
768 handle = bfd_openr (prog, 0);
769
770 if (!handle)
771 {
772 printf("``%s'' could not be opened.\n", prog);
773 return SIM_RC_FAIL;
774 }
775
776 /* Makes sure that we have an object file, also cleans gets the
777 section headers in place. */
778 if (!bfd_check_format (handle, bfd_object))
779 {
780 /* wasn't an object file */
781 bfd_close (handle);
782 printf ("``%s'' is not appropriate object file.\n", prog);
783 return SIM_RC_FAIL;
784 }
785
786 for (s = handle->sections; s; s = s->next)
787 {
788 if (s->flags & SEC_ALLOC)
789 {
790 bfd_vma vma = 0;
791 int size = bfd_get_section_size (s);
792 if (size > 0)
793 {
794 vma = bfd_section_vma (handle, s);
795 if (vma >= max_addr)
796 {
797 max_addr = vma + size;
798 }
799 }
800 if (s->flags & SEC_LOAD)
801 found_loadable_section = 1;
802 }
803 }
804
805 if (!found_loadable_section)
806 {
807 /* No loadable sections */
808 bfd_close(handle);
809 printf("No loadable sections in file %s\n", prog);
810 return SIM_RC_FAIL;
811 }
812
813 sim_memory_size = (unsigned long) max_addr;
814
815 /* Clean up after ourselves. */
816 bfd_close (handle);
817
818 }
819
820 /* from sh -- dac */
821 prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
822 /* sim_kind == SIM_OPEN_DEBUG, */
823 1,
824 0, sim_write);
825 if (prog_bfd == NULL)
826 return SIM_RC_FAIL;
827
828 target_big_endian = bfd_big_endian (prog_bfd);
829 PC = bfd_get_start_address (prog_bfd);
830
831 if (abfd == NULL)
832 bfd_close (prog_bfd);
833
834 return SIM_RC_OK;
835 }
836
837 SIM_RC
838 sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env)
839 {
840 char **avp;
841 int nargs = 0;
842 int nenv = 0;
843 int s_length;
844 int l;
845 unsigned long strings;
846 unsigned long pointers;
847 unsigned long hi_stack;
848
849
850 /* Set the initial register set. */
851 l = issue_messages;
852 issue_messages = 0;
853 set_initial_gprs ();
854 issue_messages = l;
855
856 hi_stack = CPU.msize - 4;
857 PC = bfd_get_start_address (prog_bfd);
858
859 /* For now ignore all parameters to the program */
860
861 return SIM_RC_OK;
862 }
863
864 void
865 sim_do_command (SIM_DESC sd, const char *cmd)
866 {
867 /* Nothing there yet; it's all an error. */
868
869 if (cmd != NULL)
870 {
871 char ** simargv = buildargv (cmd);
872
873 if (strcmp (simargv[0], "watch") == 0)
874 {
875 if ((simargv[1] == NULL) || (simargv[2] == NULL))
876 {
877 fprintf (stderr, "Error: missing argument to watch cmd.\n");
878 freeargv (simargv);
879 return;
880 }
881
882 ENDWL++;
883
884 WL[ENDWL] = strtol (simargv[2], NULL, 0);
885 WLstr[ENDWL] = strdup (simargv[1]);
886 fprintf (stderr, "Added %s (%x) to watchlist, #%d\n",WLstr[ENDWL],
887 WL[ENDWL], ENDWL);
888
889 }
890 else if (strcmp (simargv[0], "dumpmem") == 0)
891 {
892 unsigned char * p;
893 FILE * dumpfile;
894
895 if (simargv[1] == NULL)
896 fprintf (stderr, "Error: missing argument to dumpmem cmd.\n");
897
898 fprintf (stderr, "Writing dumpfile %s...",simargv[1]);
899
900 dumpfile = fopen (simargv[1], "w");
901 p = CPU.memory;
902 fwrite (p, CPU.msize-1, 1, dumpfile);
903 fclose (dumpfile);
904
905 fprintf (stderr, "done.\n");
906 }
907 else if (strcmp (simargv[0], "clearstats") == 0)
908 {
909 CPU.cycles = 0;
910 CPU.insts = 0;
911 ENDWL = 0;
912 }
913 else if (strcmp (simargv[0], "verbose") == 0)
914 {
915 issue_messages = 2;
916 }
917 else
918 {
919 fprintf (stderr,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
920 cmd);
921 }
922
923 freeargv (simargv);
924 }
925 else
926 {
927 fprintf (stderr, "M.CORE sim commands: \n");
928 fprintf (stderr, " watch <funcname> <addr>\n");
929 fprintf (stderr, " dumpmem <filename>\n");
930 fprintf (stderr, " clearstats\n");
931 fprintf (stderr, " verbose\n");
932 }
933 }
934
935 void
936 sim_set_callbacks (host_callback *ptr)
937 {
938 callback = ptr;
939 }
940
941 char **
942 sim_complete_command (SIM_DESC sd, const char *text, const char *word)
943 {
944 return NULL;
945 }
This page took 0.053686 seconds and 4 git commands to generate.