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