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