]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/microblaze/interp.c
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / sim / microblaze / interp.c
CommitLineData
bd30e45a 1/* Simulator for Xilinx MicroBlaze processor
8acc9f48 2 Copyright 2009-2013 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
3fd725ef 8 the Free Software Foundation; either version 3 of the License, or
bd30e45a
ME
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
51b318de 17 along with this program; if not, see <http://www.gnu.org/licenses/>. */
bd30e45a 18
8fe6640e 19#include "config.h"
bd30e45a
ME
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"
419c2fda 31#include "microblaze-dis.h"
bd30e45a
ME
32
33
34#ifndef NUM_ELEM
35#define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
36#endif
37
38static int target_big_endian = 1;
39static unsigned long heap_ptr = 0;
40static unsigned long stack_ptr = 0;
41host_callback *callback;
42
43unsigned long
44microblaze_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
73void
74microblaze_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
99struct sim_state microblaze_state;
100
101int memcycles = 1;
102
103static SIM_OPEN_KIND sim_kind;
104static char *myname;
105
106static int issue_messages = 0;
107
108long
109int_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
123static void /* INLINE */
124wbat (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
140static void /* INLINE */
141wlat (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
178static void /* INLINE */
179what (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. */
214static int /* INLINE */
215rbat (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
232static int /* INLINE */
233rlat (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
266static int /* INLINE */
267rhat (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
304static int
305IOMEM (int addr, int write, int value)
306{
307}
308
309/* Default to a 8 Mbyte (== 2^23) memory space. */
310static int sim_memory_size = 1 << 23;
311
312#define MEM_SIZE_FLOOR 64
313void
314sim_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
336static void
337init_pointers ()
338{
339 if (CPU.msize != (sim_memory_size))
340 sim_size (sim_memory_size);
341}
342
343static void
344set_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
371static void
372interrupt ()
373{
374 CPU.exception = SIGINT;
375}
376
377/* Functions so that trapped open/close don't interfere with the
378 parent's functions. We say that we can't close the descriptors
379 that we didn't open. exit() and cleanup() get in trouble here,
380 to some extent. That's the price of emulation. */
381
382unsigned char opened[100];
383
384static void
385log_open (int fd)
386{
387 if (fd < 0 || fd > NUM_ELEM (opened))
388 return;
389
390 opened[fd] = 1;
391}
392
393static void
394log_close (int fd)
395{
396 if (fd < 0 || fd > NUM_ELEM (opened))
397 return;
398
399 opened[fd] = 0;
400}
401
402static int
403is_opened (int fd)
404{
405 if (fd < 0 || fd > NUM_ELEM (opened))
406 return 0;
407
408 return opened[fd];
409}
410
411static void
412handle_trap1 ()
413{
414}
415
416static void
417process_stub (int what)
418{
419 /* These values should match those in libgloss/microblaze/syscalls.s. */
420 switch (what)
421 {
422 case 3: /* _read */
423 case 4: /* _write */
424 case 5: /* _open */
425 case 6: /* _close */
426 case 10: /* _unlink */
427 case 19: /* _lseek */
428 case 43: /* _times */
429 handle_trap1 ();
430 break;
431
432 default:
433 if (issue_messages)
434 fprintf (stderr, "Unhandled stub opcode: %d\n", what);
435 break;
436 }
437}
438
439static void
440util (unsigned what)
441{
442 switch (what)
443 {
444 case 0: /* exit */
445 CPU.exception = SIGQUIT;
446 break;
447
448 case 1: /* printf */
449 {
450 unsigned long a[6];
451 unsigned char *s;
452 int i;
453
454 for (s = (unsigned char *)a[0], i = 1 ; *s && i < 6 ; s++)
455 if (*s == '%')
456 i++;
457 }
458 break;
459
460 case 2: /* scanf */
461 if (issue_messages)
462 fprintf (stderr, "WARNING: scanf unimplemented\n");
463 break;
464
465 case 3: /* utime */
466 break;
467
468 case 0xFF:
469 process_stub (CPU.regs[1]);
470 break;
471
472 default:
473 if (issue_messages)
474 fprintf (stderr, "Unhandled util code: %x\n", what);
475 break;
476 }
477}
478
479/* For figuring out whether we carried; addc/subc use this. */
480static int
481iu_carry (unsigned long a, unsigned long b, int cin)
482{
483 unsigned long x;
484
485 x = (a & 0xffff) + (b & 0xffff) + cin;
486 x = (x >> 16) + (a >> 16) + (b >> 16);
487 x >>= 16;
488
489 return (x != 0);
490}
491
492#define WATCHFUNCTIONS 1
493#ifdef WATCHFUNCTIONS
494
495#define MAXWL 80
496word WL[MAXWL];
497char *WLstr[MAXWL];
498
499int ENDWL=0;
500int WLincyc;
501int WLcyc[MAXWL];
502int WLcnts[MAXWL];
503int WLmax[MAXWL];
504int WLmin[MAXWL];
505word WLendpc;
506int WLbcyc;
507int WLW;
508#endif
509
510static int tracing = 0;
511
512void
513sim_resume (SIM_DESC sd, int step, int siggnal)
514{
515 int needfetch;
516 word inst;
517 enum microblaze_instr op;
518 void (*sigsave)();
519 int memops;
520 int bonus_cycles;
521 int insts;
522 int w;
523 int cycs;
524 word WLhash;
525 ubyte carry;
526 int imm_unsigned;
527 short ra, rb, rd;
528 long immword;
529 uword oldpc, newpc;
530 short delay_slot_enable;
531 short branch_taken;
532 short num_delay_slot; /* UNUSED except as reqd parameter */
533 enum microblaze_instr_type insn_type;
534
535 sigsave = signal (SIGINT, interrupt);
536 CPU.exception = step ? SIGTRAP : 0;
537
538 memops = 0;
539 bonus_cycles = 0;
540 insts = 0;
541
542 do
543 {
544 /* Fetch the initial instructions that we'll decode. */
545 inst = rlat (PC & 0xFFFFFFFC);
546
547 op = get_insn_microblaze (inst, &imm_unsigned, &insn_type,
548 &num_delay_slot);
549
550 if (op == invalid_inst)
551 fprintf (stderr, "Unknown instruction 0x%04x", inst);
552
553 if (tracing)
554 fprintf (stderr, "%.4x: inst = %.4x ", PC, inst);
555
556 rd = GET_RD;
557 rb = GET_RB;
558 ra = GET_RA;
559 /* immword = IMM_W; */
560
561 oldpc = PC;
562 delay_slot_enable = 0;
563 branch_taken = 0;
564 if (op == microblaze_brk)
565 CPU.exception = SIGTRAP;
566 else if (inst == MICROBLAZE_HALT_INST)
567 {
568 CPU.exception = SIGQUIT;
569 insts += 1;
570 bonus_cycles++;
571 }
572 else
573 {
574 switch(op)
575 {
576#define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
577 case NAME: \
578 ACTION; \
579 break;
580#include "microblaze.isa"
581#undef INSTRUCTION
582
583 default:
584 CPU.exception = SIGILL;
585 fprintf (stderr, "ERROR: Unknown opcode\n");
586 }
587 /* Make R0 consistent */
588 CPU.regs[0] = 0;
589
590 /* Check for imm instr */
591 if (op == imm)
592 IMM_ENABLE = 1;
593 else
594 IMM_ENABLE = 0;
595
596 /* Update cycle counts */
597 insts ++;
598 if (insn_type == memory_store_inst || insn_type == memory_load_inst)
599 memops++;
600 if (insn_type == mult_inst)
601 bonus_cycles++;
602 if (insn_type == barrel_shift_inst)
603 bonus_cycles++;
604 if (insn_type == anyware_inst)
605 bonus_cycles++;
606 if (insn_type == div_inst)
607 bonus_cycles += 33;
608
609 if ((insn_type == branch_inst || insn_type == return_inst)
610 && branch_taken)
611 {
612 /* Add an extra cycle for taken branches */
613 bonus_cycles++;
614 /* For branch instructions handle the instruction in the delay slot */
615 if (delay_slot_enable)
616 {
617 newpc = PC;
618 PC = oldpc + INST_SIZE;
619 inst = rlat (PC & 0xFFFFFFFC);
620 op = get_insn_microblaze (inst, &imm_unsigned, &insn_type,
621 &num_delay_slot);
622 if (op == invalid_inst)
623 fprintf (stderr, "Unknown instruction 0x%04x", inst);
624 if (tracing)
625 fprintf (stderr, "%.4x: inst = %.4x ", PC, inst);
626 rd = GET_RD;
627 rb = GET_RB;
628 ra = GET_RA;
629 /* immword = IMM_W; */
630 if (op == microblaze_brk)
631 {
632 if (issue_messages)
633 fprintf (stderr, "Breakpoint set in delay slot "
634 "(at address 0x%x) will not be honored\n", PC);
635 /* ignore the breakpoint */
636 }
637 else if (insn_type == branch_inst || insn_type == return_inst)
638 {
639 if (issue_messages)
640 fprintf (stderr, "Cannot have branch or return instructions "
641 "in delay slot (at address 0x%x)\n", PC);
642 CPU.exception = SIGILL;
643 }
644 else
645 {
646 switch(op)
647 {
648#define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
649 case NAME: \
650 ACTION; \
651 break;
652#include "microblaze.isa"
653#undef INSTRUCTION
654
655 default:
656 CPU.exception = SIGILL;
657 fprintf (stderr, "ERROR: Unknown opcode at 0x%x\n", PC);
658 }
659 /* Update cycle counts */
660 insts++;
661 if (insn_type == memory_store_inst
662 || insn_type == memory_load_inst)
663 memops++;
664 if (insn_type == mult_inst)
665 bonus_cycles++;
666 if (insn_type == barrel_shift_inst)
667 bonus_cycles++;
668 if (insn_type == anyware_inst)
669 bonus_cycles++;
670 if (insn_type == div_inst)
671 bonus_cycles += 33;
672 }
673 /* Restore the PC */
674 PC = newpc;
675 /* Make R0 consistent */
676 CPU.regs[0] = 0;
677 /* Check for imm instr */
678 if (op == imm)
679 IMM_ENABLE = 1;
680 else
681 IMM_ENABLE = 0;
682 }
683 else
684 /* no delay slot: increment cycle count */
685 bonus_cycles++;
686 }
687 }
688
689 if (tracing)
690 fprintf (stderr, "\n");
691 }
692 while (!CPU.exception);
693
694 /* Hide away the things we've cached while executing. */
695 /* CPU.pc = pc; */
696 CPU.insts += insts; /* instructions done ... */
697 CPU.cycles += insts; /* and each takes a cycle */
698 CPU.cycles += bonus_cycles; /* and extra cycles for branches */
699 CPU.cycles += memops; /* and memop cycle delays */
700
701 signal (SIGINT, sigsave);
702}
703
704
705int
5558e7e6 706sim_write (SIM_DESC sd, SIM_ADDR addr, const unsigned char *buffer, int size)
bd30e45a
ME
707{
708 int i;
709 init_pointers ();
710
711 memcpy (&CPU.memory[addr], buffer, size);
712
713 return size;
714}
715
716int
717sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
718{
719 int i;
720 init_pointers ();
721
722 memcpy (buffer, &CPU.memory[addr], size);
723
724 return size;
725}
726
727
728int
729sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
730{
731 init_pointers ();
732
733 if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
734 {
735 if (length == 4)
736 {
737 /* misalignment safe */
738 long ival = microblaze_extract_unsigned_integer (memory, 4);
739 if (rn < NUM_REGS)
740 CPU.regs[rn] = ival;
741 else
742 CPU.spregs[rn-NUM_REGS] = ival;
743 return 4;
744 }
745 else
746 return 0;
747 }
748 else
749 return 0;
750}
751
752int
753sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
754{
755 long ival;
756 init_pointers ();
757
758 if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
759 {
760 if (length == 4)
761 {
762 if (rn < NUM_REGS)
763 ival = CPU.regs[rn];
764 else
765 ival = CPU.spregs[rn-NUM_REGS];
766
767 /* misalignment-safe */
768 microblaze_store_unsigned_integer (memory, 4, ival);
769 return 4;
770 }
771 else
772 return 0;
773 }
774 else
775 return 0;
776}
777
778
779int
780sim_trace (SIM_DESC sd)
781{
782 tracing = 1;
783
784 sim_resume (sd, 0, 0);
785
786 tracing = 0;
787
788 return 1;
789}
790
791void
792sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
793{
794 if (CPU.exception == SIGQUIT)
795 {
796 *reason = sim_exited;
797 *sigrc = RETREG;
798 }
799 else
800 {
801 *reason = sim_stopped;
802 *sigrc = CPU.exception;
803 }
804}
805
806
807int
808sim_stop (SIM_DESC sd)
809{
810 CPU.exception = SIGINT;
811 return 1;
812}
813
814
815void
816sim_info (SIM_DESC sd, int verbose)
817{
818#ifdef WATCHFUNCTIONS
819 int w, wcyc;
820#endif
821
822 callback->printf_filtered (callback, "\n\n# instructions executed %10d\n",
823 CPU.insts);
824 callback->printf_filtered (callback, "# cycles %10d\n",
825 (CPU.cycles) ? CPU.cycles+2 : 0);
826
827#ifdef WATCHFUNCTIONS
828 callback->printf_filtered (callback, "\nNumber of watched functions: %d\n",
829 ENDWL);
830
831 wcyc = 0;
832
833 for (w = 1; w <= ENDWL; w++)
834 {
835 callback->printf_filtered (callback, "WL = %s %8x\n",WLstr[w],WL[w]);
836 callback->printf_filtered (callback, " calls = %d, cycles = %d\n",
837 WLcnts[w],WLcyc[w]);
838
839 if (WLcnts[w] != 0)
840 callback->printf_filtered (callback,
841 " maxcpc = %d, mincpc = %d, avecpc = %d\n",
842 WLmax[w],WLmin[w],WLcyc[w]/WLcnts[w]);
843 wcyc += WLcyc[w];
844 }
845
846 callback->printf_filtered (callback,
847 "Total cycles for watched functions: %d\n",wcyc);
848#endif
849}
850
851struct aout
852{
853 unsigned char sa_machtype[2];
854 unsigned char sa_magic[2];
855 unsigned char sa_tsize[4];
856 unsigned char sa_dsize[4];
857 unsigned char sa_bsize[4];
858 unsigned char sa_syms[4];
859 unsigned char sa_entry[4];
860 unsigned char sa_trelo[4];
861 unsigned char sa_drelo[4];
862} aout;
863
864#define LONG(x) (((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
865#define SHORT(x) (((x)[0]<<8)|(x)[1])
866
867SIM_DESC
868sim_open (SIM_OPEN_KIND kind, host_callback *cb, struct bfd *abfd, char **argv)
869{
870 /* SIM_DESC sd = sim_state_alloc(kind, alloc);*/
871
872 int osize = sim_memory_size;
873 myname = argv[0];
874 callback = cb;
875
876 if (kind == SIM_OPEN_STANDALONE)
877 issue_messages = 1;
878
879 /* Discard and reacquire memory -- start with a clean slate. */
880 sim_size (1); /* small */
881 sim_size (osize); /* and back again */
882
883 set_initial_gprs (); /* Reset the GPR registers. */
884
885 return ((SIM_DESC) 1);
886}
887
888void
889sim_close (SIM_DESC sd, int quitting)
890{
891 if (CPU.memory)
892 {
893 free(CPU.memory);
894 CPU.memory = NULL;
895 CPU.msize = 0;
896 }
897}
898
899SIM_RC
900sim_load (SIM_DESC sd, char *prog, bfd *abfd, int from_tty)
901{
902 /* Do the right thing for ELF executables; this turns out to be
903 just about the right thing for any object format that:
904 - we crack using BFD routines
905 - follows the traditional UNIX text/data/bss layout
906 - calls the bss section ".bss". */
907
908 extern bfd *sim_load_file (); /* ??? Don't know where this should live. */
909 bfd *prog_bfd;
910
911 {
912 bfd *handle;
913 asection *s;
914 int found_loadable_section = 0;
915 bfd_vma max_addr = 0;
916 handle = bfd_openr (prog, 0);
917
918 if (!handle)
919 {
920 printf("``%s'' could not be opened.\n", prog);
921 return SIM_RC_FAIL;
922 }
923
924 /* Makes sure that we have an object file, also cleans gets the
925 section headers in place. */
926 if (!bfd_check_format (handle, bfd_object))
927 {
928 /* wasn't an object file */
929 bfd_close (handle);
930 printf ("``%s'' is not appropriate object file.\n", prog);
931 return SIM_RC_FAIL;
932 }
933
934 for (s = handle->sections; s; s = s->next)
935 {
936 if (s->flags & SEC_ALLOC)
937 {
938 bfd_vma vma = 0;
939 int size = bfd_get_section_size (s);
940 if (size > 0)
941 {
942 vma = bfd_section_vma (handle, s);
943 if (vma >= max_addr)
944 {
945 max_addr = vma + size;
946 }
947 }
948 if (s->flags & SEC_LOAD)
949 found_loadable_section = 1;
950 }
951 }
952
953 if (!found_loadable_section)
954 {
955 /* No loadable sections */
956 bfd_close(handle);
957 printf("No loadable sections in file %s\n", prog);
958 return SIM_RC_FAIL;
959 }
960
961 sim_memory_size = (unsigned long) max_addr;
962
963 /* Clean up after ourselves. */
964 bfd_close (handle);
965
966 }
967
968 /* from sh -- dac */
969 prog_bfd = sim_load_file (sd, myname, callback, prog, abfd,
970 /* sim_kind == SIM_OPEN_DEBUG, */
971 1,
972 0, sim_write);
973 if (prog_bfd == NULL)
974 return SIM_RC_FAIL;
975
976 target_big_endian = bfd_big_endian (prog_bfd);
977 PC = bfd_get_start_address (prog_bfd);
978
979 if (abfd == NULL)
980 bfd_close (prog_bfd);
981
982 return SIM_RC_OK;
983}
984
985SIM_RC
986sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd, char **argv, char **env)
987{
988 char **avp;
989 int nargs = 0;
990 int nenv = 0;
991 int s_length;
992 int l;
993 unsigned long strings;
994 unsigned long pointers;
995 unsigned long hi_stack;
996
997
998 /* Set the initial register set. */
999 l = issue_messages;
1000 issue_messages = 0;
1001 set_initial_gprs ();
1002 issue_messages = l;
1003
1004 hi_stack = CPU.msize - 4;
1005 PC = bfd_get_start_address (prog_bfd);
1006
1007 /* For now ignore all parameters to the program */
1008
1009 return SIM_RC_OK;
1010}
1011
1012void
1013sim_kill (SIM_DESC sd)
1014{
1015 /* nothing to do */
1016}
1017
1018void
1019sim_do_command (SIM_DESC sd, char * cmd)
1020{
1021 /* Nothing there yet; it's all an error. */
1022
1023 if (cmd != NULL)
1024 {
1025 char ** simargv = buildargv (cmd);
1026
1027 if (strcmp (simargv[0], "watch") == 0)
1028 {
1029 if ((simargv[1] == NULL) || (simargv[2] == NULL))
1030 {
1031 fprintf (stderr, "Error: missing argument to watch cmd.\n");
1032 return;
1033 }
1034
1035 ENDWL++;
1036
1037 WL[ENDWL] = strtol (simargv[2], NULL, 0);
1038 WLstr[ENDWL] = strdup (simargv[1]);
1039 fprintf (stderr, "Added %s (%x) to watchlist, #%d\n",WLstr[ENDWL],
1040 WL[ENDWL], ENDWL);
1041
1042 }
1043 else if (strcmp (simargv[0], "dumpmem") == 0)
1044 {
1045 unsigned char * p;
1046 FILE * dumpfile;
1047
1048 if (simargv[1] == NULL)
1049 fprintf (stderr, "Error: missing argument to dumpmem cmd.\n");
1050
1051 fprintf (stderr, "Writing dumpfile %s...",simargv[1]);
1052
1053 dumpfile = fopen (simargv[1], "w");
1054 p = CPU.memory;
1055 fwrite (p, CPU.msize-1, 1, dumpfile);
1056 fclose (dumpfile);
1057
1058 fprintf (stderr, "done.\n");
1059 }
1060 else if (strcmp (simargv[0], "clearstats") == 0)
1061 {
1062 CPU.cycles = 0;
1063 CPU.insts = 0;
1064 ENDWL = 0;
1065 }
1066 else if (strcmp (simargv[0], "verbose") == 0)
1067 {
1068 issue_messages = 2;
1069 }
1070 else
1071 {
1072 fprintf (stderr,"Error: \"%s\" is not a valid M.CORE simulator command.\n",
1073 cmd);
1074 }
1075 }
1076 else
1077 {
1078 fprintf (stderr, "M.CORE sim commands: \n");
1079 fprintf (stderr, " watch <funcname> <addr>\n");
1080 fprintf (stderr, " dumpmem <filename>\n");
1081 fprintf (stderr, " clearstats\n");
1082 fprintf (stderr, " verbose\n");
1083 }
1084}
1085
1086void
1087sim_set_callbacks (host_callback *ptr)
1088{
1089 callback = ptr;
1090}
af9f7da7
MF
1091
1092char **
1093sim_complete_command (SIM_DESC sd, char *text, char *word)
1094{
1095 return NULL;
1096}