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