gdb/
[deliverable/binutils-gdb.git] / sim / microblaze / interp.c
CommitLineData
bd30e45a 1/* Simulator for Xilinx MicroBlaze processor
c5a57081 2 Copyright 2009-2012 Free Software Foundation, Inc.
bd30e45a
ME
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 2 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, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19 02110-1301, USA. */
20
8fe6640e 21#include "config.h"
bd30e45a
ME
22#include <signal.h>
23#include "sysdep.h"
24#include <sys/times.h>
25#include <sys/param.h>
26#include <netinet/in.h> /* for byte ordering macros */
27#include "bfd.h"
28#include "gdb/callback.h"
29#include "libiberty.h"
30#include "gdb/remote-sim.h"
31#include "sim-main.h"
32#include "sim-utils.h"
419c2fda 33#include "microblaze-dis.h"
bd30e45a
ME
34
35
36#ifndef NUM_ELEM
37#define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
38#endif
39
40static int target_big_endian = 1;
41static unsigned long heap_ptr = 0;
42static unsigned long stack_ptr = 0;
43host_callback *callback;
44
45unsigned long
46microblaze_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 "%d 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
75void
76microblaze_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
101struct sim_state microblaze_state;
102
103int memcycles = 1;
104
105static SIM_OPEN_KIND sim_kind;
106static char *myname;
107
108static int issue_messages = 0;
109
110long
111int_sbrk (int inc_bytes)
112{
113 long addr;
114
115 addr = heap_ptr;
116
117 heap_ptr += inc_bytes;
118
119 if (issue_messages && heap_ptr > SP)
120 fprintf (stderr, "Warning: heap_ptr overlaps stack!\n");
121
122 return addr;
123}
124
125static void /* INLINE */
126wbat (word x, word v)
127{
128 if (((uword)x) >= CPU.msize)
129 {
130 if (issue_messages)
131 fprintf (stderr, "byte write to 0x%x outside memory range\n", x);
132
133 CPU.exception = SIGSEGV;
134 }
135 else
136 {
137 unsigned char *p = CPU.memory + x;
138 p[0] = v;
139 }
140}
141
142static void /* INLINE */
143wlat (word x, word v)
144{
145 if (((uword)x) >= CPU.msize)
146 {
147 if (issue_messages)
148 fprintf (stderr, "word write to 0x%x outside memory range\n", x);
149
150 CPU.exception = SIGSEGV;
151 }
152 else
153 {
154 if ((x & 3) != 0)
155 {
156 if (issue_messages)
157 fprintf (stderr, "word write to unaligned memory address: 0x%x\n", x);
158
159 CPU.exception = SIGBUS;
160 }
161 else if (!target_big_endian)
162 {
163 unsigned char *p = CPU.memory + x;
164 p[3] = v >> 24;
165 p[2] = v >> 16;
166 p[1] = v >> 8;
167 p[0] = v;
168 }
169 else
170 {
171 unsigned char *p = CPU.memory + x;
172 p[0] = v >> 24;
173 p[1] = v >> 16;
174 p[2] = v >> 8;
175 p[3] = v;
176 }
177 }
178}
179
180static void /* INLINE */
181what (word x, word v)
182{
183 if (((uword)x) >= CPU.msize)
184 {
185 if (issue_messages)
186 fprintf (stderr, "short write to 0x%x outside memory range\n", x);
187
188 CPU.exception = SIGSEGV;
189 }
190 else
191 {
192 if ((x & 1) != 0)
193 {
194 if (issue_messages)
195 fprintf (stderr, "short write to unaligned memory address: 0x%x\n",
196 x);
197
198 CPU.exception = SIGBUS;
199 }
200 else if (!target_big_endian)
201 {
202 unsigned char *p = CPU.memory + x;
203 p[1] = v >> 8;
204 p[0] = v;
205 }
206 else
207 {
208 unsigned char *p = CPU.memory + x;
209 p[0] = v >> 8;
210 p[1] = v;
211 }
212 }
213}
214
215/* Read functions. */
216static int /* INLINE */
217rbat (word x)
218{
219 if (((uword)x) >= CPU.msize)
220 {
221 if (issue_messages)
222 fprintf (stderr, "byte read from 0x%x outside memory range\n", x);
223
224 CPU.exception = SIGSEGV;
225 return 0;
226 }
227 else
228 {
229 unsigned char *p = CPU.memory + x;
230 return p[0];
231 }
232}
233
234static int /* INLINE */
235rlat (word x)
236{
237 if (((uword) x) >= CPU.msize)
238 {
239 if (issue_messages)
240 fprintf (stderr, "word read from 0x%x outside memory range\n", x);
241
242 CPU.exception = SIGSEGV;
243 return 0;
244 }
245 else
246 {
247 if ((x & 3) != 0)
248 {
249 if (issue_messages)
250 fprintf (stderr, "word read from unaligned address: 0x%x\n", x);
251
252 CPU.exception = SIGBUS;
253 return 0;
254 }
255 else if (! target_big_endian)
256 {
257 unsigned char *p = CPU.memory + x;
258 return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
259 }
260 else
261 {
262 unsigned char *p = CPU.memory + x;
263 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
264 }
265 }
266}
267
268static int /* INLINE */
269rhat (word x)
270{
271 if (((uword)x) >= CPU.msize)
272 {
273 if (issue_messages)
274 fprintf (stderr, "short read from 0x%x outside memory range\n", x);
275
276 CPU.exception = SIGSEGV;
277 return 0;
278 }
279 else
280 {
281 if ((x & 1) != 0)
282 {
283 if (issue_messages)
284 fprintf (stderr, "short read from unaligned address: 0x%x\n", x);
285
286 CPU.exception = SIGBUS;
287 return 0;
288 }
289 else if (!target_big_endian)
290 {
291 unsigned char *p = CPU.memory + x;
292 return (p[1] << 8) | p[0];
293 }
294 else
295 {
296 unsigned char *p = CPU.memory + x;
297 return (p[0] << 8) | p[1];
298 }
299 }
300}
301
302
303#define SEXTB(x) (((x & 0xff) ^ (~ 0x7f)) + 0x80)
304#define SEXTW(y) ((int)((short)y))
305
306static int
307IOMEM (int addr, int write, int value)
308{
309}
310
311/* Default to a 8 Mbyte (== 2^23) memory space. */
312static int sim_memory_size = 1 << 23;
313
314#define MEM_SIZE_FLOOR 64
315void
316sim_size (int size)
317{
318 sim_memory_size = size;
319 CPU.msize = sim_memory_size;
320
321 if (CPU.memory)
322 free (CPU.memory);
323
324 CPU.memory = (unsigned char *) calloc (1, CPU.msize);
325
326 if (!CPU.memory)
327 {
328 if (issue_messages)
329 fprintf (stderr,
330 "Not enough VM for simulation of %d bytes of RAM\n",
331 CPU.msize);
332
333 CPU.msize = 1;
334 CPU.memory = (unsigned char *) calloc (1, 1);
335 }
336}
337
338static void
339init_pointers ()
340{
341 if (CPU.msize != (sim_memory_size))
342 sim_size (sim_memory_size);
343}
344
345static void
346set_initial_gprs ()
347{
348 int i;
349 long space;
350 unsigned long memsize;
351
352 init_pointers ();
353
354 /* Set up machine just out of reset. */
355 PC = 0;
356 MSR = 0;
357
358 memsize = CPU.msize / (1024 * 1024);
359
360 if (issue_messages > 1)
361 fprintf (stderr, "Simulated memory of %d Mbytes (0x0 .. 0x%08x)\n",
362 memsize, CPU.msize - 1);
363
364 /* Clean out the GPRs */
365 for (i = 0; i < 32; i++)
366 CPU.regs[i] = 0;
367 CPU.insts = 0;
368 CPU.cycles = 0;
369 CPU.imm_enable = 0;
370
371}
372
373static void
374interrupt ()
375{
376 CPU.exception = SIGINT;
377}
378
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. */
383
384unsigned char opened[100];
385
386static void
387log_open (int fd)
388{
389 if (fd < 0 || fd > NUM_ELEM (opened))
390 return;
391
392 opened[fd] = 1;
393}
394
395static void
396log_close (int fd)
397{
398 if (fd < 0 || fd > NUM_ELEM (opened))
399 return;
400
401 opened[fd] = 0;
402}
403
404static int
405is_opened (int fd)
406{
407 if (fd < 0 || fd > NUM_ELEM (opened))
408 return 0;
409
410 return opened[fd];
411}
412
413static void
414handle_trap1 ()
415{
416}
417
418static void
419process_stub (int what)
420{
421 /* These values should match those in libgloss/microblaze/syscalls.s. */
422 switch (what)
423 {
424 case 3: /* _read */
425 case 4: /* _write */
426 case 5: /* _open */
427 case 6: /* _close */
428 case 10: /* _unlink */
429 case 19: /* _lseek */
430 case 43: /* _times */
431 handle_trap1 ();
432 break;
433
434 default:
435 if (issue_messages)
436 fprintf (stderr, "Unhandled stub opcode: %d\n", what);
437 break;
438 }
439}
440
441static void
442util (unsigned what)
443{
444 switch (what)
445 {
446 case 0: /* exit */
447 CPU.exception = SIGQUIT;
448 break;
449
450 case 1: /* printf */
451 {
452 unsigned long a[6];
453 unsigned char *s;
454 int i;
455
456 for (s = (unsigned char *)a[0], i = 1 ; *s && i < 6 ; s++)
457 if (*s == '%')
458 i++;
459 }
460 break;
461
462 case 2: /* scanf */
463 if (issue_messages)
464 fprintf (stderr, "WARNING: scanf unimplemented\n");
465 break;
466
467 case 3: /* utime */
468 break;
469
470 case 0xFF:
471 process_stub (CPU.regs[1]);
472 break;
473
474 default:
475 if (issue_messages)
476 fprintf (stderr, "Unhandled util code: %x\n", what);
477 break;
478 }
479}
480
481/* For figuring out whether we carried; addc/subc use this. */
482static int
483iu_carry (unsigned long a, unsigned long b, int cin)
484{
485 unsigned long x;
486
487 x = (a & 0xffff) + (b & 0xffff) + cin;
488 x = (x >> 16) + (a >> 16) + (b >> 16);
489 x >>= 16;
490
491 return (x != 0);
492}
493
494#define WATCHFUNCTIONS 1
495#ifdef WATCHFUNCTIONS
496
497#define MAXWL 80
498word WL[MAXWL];
499char *WLstr[MAXWL];
500
501int ENDWL=0;
502int WLincyc;
503int WLcyc[MAXWL];
504int WLcnts[MAXWL];
505int WLmax[MAXWL];
506int WLmin[MAXWL];
507word WLendpc;
508int WLbcyc;
509int WLW;
510#endif
511
512static int tracing = 0;
513
514void
515sim_resume (SIM_DESC sd, int step, int siggnal)
516{
517 int needfetch;
518 word inst;
519 enum microblaze_instr op;
520 void (*sigsave)();
521 int memops;
522 int bonus_cycles;
523 int insts;
524 int w;
525 int cycs;
526 word WLhash;
527 ubyte carry;
528 int imm_unsigned;
529 short ra, rb, rd;
530 long immword;
531 uword oldpc, newpc;
532 short delay_slot_enable;
533 short branch_taken;
534 short num_delay_slot; /* UNUSED except as reqd parameter */
535 enum microblaze_instr_type insn_type;
536
537 sigsave = signal (SIGINT, interrupt);
538 CPU.exception = step ? SIGTRAP : 0;
539
540 memops = 0;
541 bonus_cycles = 0;
542 insts = 0;
543
544 do
545 {
546 /* Fetch the initial instructions that we'll decode. */
547 inst = rlat (PC & 0xFFFFFFFC);
548
549 op = get_insn_microblaze (inst, &imm_unsigned, &insn_type,
550 &num_delay_slot);
551
552 if (op == invalid_inst)
553 fprintf (stderr, "Unknown instruction 0x%04x", inst);
554
555 if (tracing)
556 fprintf (stderr, "%.4x: inst = %.4x ", PC, inst);
557
558 rd = GET_RD;
559 rb = GET_RB;
560 ra = GET_RA;
561 /* immword = IMM_W; */
562
563 oldpc = PC;
564 delay_slot_enable = 0;
565 branch_taken = 0;
566 if (op == microblaze_brk)
567 CPU.exception = SIGTRAP;
568 else if (inst == MICROBLAZE_HALT_INST)
569 {
570 CPU.exception = SIGQUIT;
571 insts += 1;
572 bonus_cycles++;
573 }
574 else
575 {
576 switch(op)
577 {
578#define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
579 case NAME: \
580 ACTION; \
581 break;
582#include "microblaze.isa"
583#undef INSTRUCTION
584
585 default:
586 CPU.exception = SIGILL;
587 fprintf (stderr, "ERROR: Unknown opcode\n");
588 }
589 /* Make R0 consistent */
590 CPU.regs[0] = 0;
591
592 /* Check for imm instr */
593 if (op == imm)
594 IMM_ENABLE = 1;
595 else
596 IMM_ENABLE = 0;
597
598 /* Update cycle counts */
599 insts ++;
600 if (insn_type == memory_store_inst || insn_type == memory_load_inst)
601 memops++;
602 if (insn_type == mult_inst)
603 bonus_cycles++;
604 if (insn_type == barrel_shift_inst)
605 bonus_cycles++;
606 if (insn_type == anyware_inst)
607 bonus_cycles++;
608 if (insn_type == div_inst)
609 bonus_cycles += 33;
610
611 if ((insn_type == branch_inst || insn_type == return_inst)
612 && branch_taken)
613 {
614 /* Add an extra cycle for taken branches */
615 bonus_cycles++;
616 /* For branch instructions handle the instruction in the delay slot */
617 if (delay_slot_enable)
618 {
619 newpc = PC;
620 PC = oldpc + INST_SIZE;
621 inst = rlat (PC & 0xFFFFFFFC);
622 op = get_insn_microblaze (inst, &imm_unsigned, &insn_type,
623 &num_delay_slot);
624 if (op == invalid_inst)
625 fprintf (stderr, "Unknown instruction 0x%04x", inst);
626 if (tracing)
627 fprintf (stderr, "%.4x: inst = %.4x ", PC, inst);
628 rd = GET_RD;
629 rb = GET_RB;
630 ra = GET_RA;
631 /* immword = IMM_W; */
632 if (op == microblaze_brk)
633 {
634 if (issue_messages)
635 fprintf (stderr, "Breakpoint set in delay slot "
636 "(at address 0x%x) will not be honored\n", PC);
637 /* ignore the breakpoint */
638 }
639 else if (insn_type == branch_inst || insn_type == return_inst)
640 {
641 if (issue_messages)
642 fprintf (stderr, "Cannot have branch or return instructions "
643 "in delay slot (at address 0x%x)\n", PC);
644 CPU.exception = SIGILL;
645 }
646 else
647 {
648 switch(op)
649 {
650#define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
651 case NAME: \
652 ACTION; \
653 break;
654#include "microblaze.isa"
655#undef INSTRUCTION
656
657 default:
658 CPU.exception = SIGILL;
659 fprintf (stderr, "ERROR: Unknown opcode at 0x%x\n", PC);
660 }
661 /* Update cycle counts */
662 insts++;
663 if (insn_type == memory_store_inst
664 || insn_type == memory_load_inst)
665 memops++;
666 if (insn_type == mult_inst)
667 bonus_cycles++;
668 if (insn_type == barrel_shift_inst)
669 bonus_cycles++;
670 if (insn_type == anyware_inst)
671 bonus_cycles++;
672 if (insn_type == div_inst)
673 bonus_cycles += 33;
674 }
675 /* Restore the PC */
676 PC = newpc;
677 /* Make R0 consistent */
678 CPU.regs[0] = 0;
679 /* Check for imm instr */
680 if (op == imm)
681 IMM_ENABLE = 1;
682 else
683 IMM_ENABLE = 0;
684 }
685 else
686 /* no delay slot: increment cycle count */
687 bonus_cycles++;
688 }
689 }
690
691 if (tracing)
692 fprintf (stderr, "\n");
693 }
694 while (!CPU.exception);
695
696 /* Hide away the things we've cached while executing. */
697 /* CPU.pc = pc; */
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 */
702
703 signal (SIGINT, sigsave);
704}
705
706
707int
5558e7e6 708sim_write (SIM_DESC sd, SIM_ADDR addr, const unsigned char *buffer, int size)
bd30e45a
ME
709{
710 int i;
711 init_pointers ();
712
713 memcpy (&CPU.memory[addr], buffer, size);
714
715 return size;
716}
717
718int
719sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
720{
721 int i;
722 init_pointers ();
723
724 memcpy (buffer, &CPU.memory[addr], size);
725
726 return size;
727}
728
729
730int
731sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
732{
733 init_pointers ();
734
735 if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
736 {
737 if (length == 4)
738 {
739 /* misalignment safe */
740 long ival = microblaze_extract_unsigned_integer (memory, 4);
741 if (rn < NUM_REGS)
742 CPU.regs[rn] = ival;
743 else
744 CPU.spregs[rn-NUM_REGS] = ival;
745 return 4;
746 }
747 else
748 return 0;
749 }
750 else
751 return 0;
752}
753
754int
755sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
756{
757 long ival;
758 init_pointers ();
759
760 if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
761 {
762 if (length == 4)
763 {
764 if (rn < NUM_REGS)
765 ival = CPU.regs[rn];
766 else
767 ival = CPU.spregs[rn-NUM_REGS];
768
769 /* misalignment-safe */
770 microblaze_store_unsigned_integer (memory, 4, ival);
771 return 4;
772 }
773 else
774 return 0;
775 }
776 else
777 return 0;
778}
779
780
781int
782sim_trace (SIM_DESC sd)
783{
784 tracing = 1;
785
786 sim_resume (sd, 0, 0);
787
788 tracing = 0;
789
790 return 1;
791}
792
793void
794sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
795{
796 if (CPU.exception == SIGQUIT)
797 {
798 *reason = sim_exited;
799 *sigrc = RETREG;
800 }
801 else
802 {
803 *reason = sim_stopped;
804 *sigrc = CPU.exception;
805 }
806}
807
808
809int
810sim_stop (SIM_DESC sd)
811{
812 CPU.exception = SIGINT;
813 return 1;
814}
815
816
817void
818sim_info (SIM_DESC sd, int verbose)
819{
820#ifdef WATCHFUNCTIONS
821 int w, wcyc;
822#endif
823
824 callback->printf_filtered (callback, "\n\n# instructions executed %10d\n",
825 CPU.insts);
826 callback->printf_filtered (callback, "# cycles %10d\n",
827 (CPU.cycles) ? CPU.cycles+2 : 0);
828
829#ifdef WATCHFUNCTIONS
830 callback->printf_filtered (callback, "\nNumber of watched functions: %d\n",
831 ENDWL);
832
833 wcyc = 0;
834
835 for (w = 1; w <= ENDWL; w++)
836 {
837 callback->printf_filtered (callback, "WL = %s %8x\n",WLstr[w],WL[w]);
838 callback->printf_filtered (callback, " calls = %d, cycles = %d\n",
839 WLcnts[w],WLcyc[w]);
840
841 if (WLcnts[w] != 0)
842 callback->printf_filtered (callback,
843 " maxcpc = %d, mincpc = %d, avecpc = %d\n",
844 WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]);
845 wcyc += WLcyc[w];
846 }
847
848 callback->printf_filtered (callback,
849 "Total cycles for watched functions: %d\n",wcyc);
850#endif
851}
852
853struct aout
854{
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];
864} aout;
865
866#define LONG(x) (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
867#define SHORT(x) (((x)[0]<<8)|(x)[1])
868
869SIM_DESC
870sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv)
871{
872 /* SIM_DESC sd = sim_state_alloc(kind, alloc);*/
873
874 int osize = sim_memory_size;
875 myname = argv[0];
876 callback = cb;
877
878 if (kind == SIM_OPEN_STANDALONE)
879 issue_messages = 1;
880
881 /* Discard and reacquire memory -- start with a clean slate. */
882 sim_size (1); /* small */
883 sim_size (osize); /* and back again */
884
885 set_initial_gprs (); /* Reset the GPR registers. */
886
887 return ((SIM_DESC) 1);
888}
889
890void
891sim_close (SIM_DESC sd, int quitting)
892{
893 if (CPU.memory)
894 {
895 free(CPU.memory);
896 CPU.memory = NULL;
897 CPU.msize = 0;
898 }
899}
900
901SIM_RC
902sim_load (SIM_DESC sd, char *prog, bfd *abfd, int from_tty)
903{
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". */
909
910 extern bfd *sim_load_file (); /* ??? Don't know where this should live. */
911 bfd *prog_bfd;
912
913 {
914 bfd *handle;
915 asection *s;
916 int found_loadable_section = 0;
917 bfd_vma max_addr = 0;
918 handle = bfd_openr (prog, 0);
919
920 if (!handle)
921 {
922 printf("``%s'' could not be opened.\n", prog);
923 return SIM_RC_FAIL;
924 }
925
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))
929 {
930 /* wasn't an object file */
931 bfd_close (handle);
932 printf ("``%s'' is not appropriate object file.\n", prog);
933 return SIM_RC_FAIL;
934 }
935
936 for (s = handle->sections; s; s = s->next)
937 {
938 if (s->flags & SEC_ALLOC)
939 {
940 bfd_vma vma = 0;
941 int size = bfd_get_section_size (s);
942 if (size > 0)
943 {
944 vma = bfd_section_vma (handle, s);
945 if (vma >= max_addr)
946 {
947 max_addr = vma + size;
948 }
949 }
950 if (s->flags & SEC_LOAD)
951 found_loadable_section = 1;
952 }
953 }
954
955 if (!found_loadable_section)
956 {
957 /* No loadable sections */
958 bfd_close(handle);
959 printf("No loadable sections in file %s\n", prog);
960 return SIM_RC_FAIL;
961 }
962
963 sim_memory_size = (unsigned long) max_addr;
964
965 /* Clean up after ourselves. */
966 bfd_close (handle);
967
968 }
969
970 /* from sh -- dac */
971 prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
972 /* sim_kind == SIM_OPEN_DEBUG, */
973 1,
974 0, sim_write);
975 if (prog_bfd == NULL)
976 return SIM_RC_FAIL;
977
978 target_big_endian = bfd_big_endian (prog_bfd);
979 PC = bfd_get_start_address (prog_bfd);
980
981 if (abfd == NULL)
982 bfd_close (prog_bfd);
983
984 return SIM_RC_OK;
985}
986
987SIM_RC
988sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env)
989{
990 char **avp;
991 int nargs = 0;
992 int nenv = 0;
993 int s_length;
994 int l;
995 unsigned long strings;
996 unsigned long pointers;
997 unsigned long hi_stack;
998
999
1000 /* Set the initial register set. */
1001 l = issue_messages;
1002 issue_messages = 0;
1003 set_initial_gprs ();
1004 issue_messages = l;
1005
1006 hi_stack = CPU.msize - 4;
1007 PC = bfd_get_start_address (prog_bfd);
1008
1009 /* For now ignore all parameters to the program */
1010
1011 return SIM_RC_OK;
1012}
1013
1014void
1015sim_kill (SIM_DESC sd)
1016{
1017 /* nothing to do */
1018}
1019
1020void
1021sim_do_command (SIM_DESC sd, char * cmd)
1022{
1023 /* Nothing there yet; it's all an error. */
1024
1025 if (cmd != NULL)
1026 {
1027 char ** simargv = buildargv (cmd);
1028
1029 if (strcmp (simargv[0], "watch") == 0)
1030 {
1031 if ((simargv[1] == NULL) || (simargv[2] == NULL))
1032 {
1033 fprintf (stderr, "Error: missing argument to watch cmd.\n");
1034 return;
1035 }
1036
1037 ENDWL++;
1038
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],
1042 WL[ENDWL], ENDWL);
1043
1044 }
1045 else if (strcmp (simargv[0], "dumpmem") == 0)
1046 {
1047 unsigned char * p;
1048 FILE * dumpfile;
1049
1050 if (simargv[1] == NULL)
1051 fprintf (stderr, "Error: missing argument to dumpmem cmd.\n");
1052
1053 fprintf (stderr, "Writing dumpfile %s...",simargv[1]);
1054
1055 dumpfile = fopen (simargv[1], "w");
1056 p = CPU.memory;
1057 fwrite (p, CPU.msize-1, 1, dumpfile);
1058 fclose (dumpfile);
1059
1060 fprintf (stderr, "done.\n");
1061 }
1062 else if (strcmp (simargv[0], "clearstats") == 0)
1063 {
1064 CPU.cycles = 0;
1065 CPU.insts = 0;
1066 ENDWL = 0;
1067 }
1068 else if (strcmp (simargv[0], "verbose") == 0)
1069 {
1070 issue_messages = 2;
1071 }
1072 else
1073 {
1074 fprintf (stderr,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
1075 cmd);
1076 }
1077 }
1078 else
1079 {
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");
1085 }
1086}
1087
1088void
1089sim_set_callbacks (host_callback *ptr)
1090{
1091 callback = ptr;
1092}
af9f7da7
MF
1093
1094char **
1095sim_complete_command (SIM_DESC sd, char *text, char *word)
1096{
1097 return NULL;
1098}
This page took 0.275858 seconds and 4 git commands to generate.