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