]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/microblaze/interp.c
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / sim / microblaze / interp.c
1 /* Simulator for Xilinx MicroBlaze processor
2 Copyright 2009-2013 Free Software Foundation, Inc.
3
4 This file is part of GDB, the GNU debugger.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>. */
18
19 #include "config.h"
20 #include <signal.h>
21 #include "sysdep.h"
22 #include <sys/times.h>
23 #include <sys/param.h>
24 #include <netinet/in.h> /* for byte ordering macros */
25 #include "bfd.h"
26 #include "gdb/callback.h"
27 #include "libiberty.h"
28 #include "gdb/remote-sim.h"
29 #include "sim-main.h"
30 #include "sim-utils.h"
31 #include "microblaze-dis.h"
32
33
34 #ifndef NUM_ELEM
35 #define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
36 #endif
37
38 static int target_big_endian = 1;
39 static unsigned long heap_ptr = 0;
40 static unsigned long stack_ptr = 0;
41 host_callback *callback;
42
43 unsigned long
44 microblaze_extract_unsigned_integer (unsigned char *addr, int len)
45 {
46 unsigned long retval;
47 unsigned char *p;
48 unsigned char *startaddr = (unsigned char *)addr;
49 unsigned char *endaddr = startaddr + len;
50
51 if (len > (int) sizeof (unsigned long))
52 printf ("That operation is not available on integers of more than "
53 "%d bytes.", sizeof (unsigned long));
54
55 /* Start at the most significant end of the integer, and work towards
56 the least significant. */
57 retval = 0;
58
59 if (!target_big_endian)
60 {
61 for (p = endaddr; p > startaddr;)
62 retval = (retval << 8) | * -- p;
63 }
64 else
65 {
66 for (p = startaddr; p < endaddr;)
67 retval = (retval << 8) | * p ++;
68 }
69
70 return retval;
71 }
72
73 void
74 microblaze_store_unsigned_integer (unsigned char *addr, int len,
75 unsigned long val)
76 {
77 unsigned char *p;
78 unsigned char *startaddr = (unsigned char *)addr;
79 unsigned char *endaddr = startaddr + len;
80
81 if (!target_big_endian)
82 {
83 for (p = startaddr; p < endaddr;)
84 {
85 *p++ = val & 0xff;
86 val >>= 8;
87 }
88 }
89 else
90 {
91 for (p = endaddr; p > startaddr;)
92 {
93 *--p = val & 0xff;
94 val >>= 8;
95 }
96 }
97 }
98
99 struct sim_state microblaze_state;
100
101 int memcycles = 1;
102
103 static SIM_OPEN_KIND sim_kind;
104 static char *myname;
105
106 static int issue_messages = 0;
107
108 long
109 int_sbrk (int inc_bytes)
110 {
111 long addr;
112
113 addr = heap_ptr;
114
115 heap_ptr += inc_bytes;
116
117 if (issue_messages && heap_ptr > SP)
118 fprintf (stderr, "Warning: heap_ptr overlaps stack!\n");
119
120 return addr;
121 }
122
123 static void /* INLINE */
124 wbat (word x, word v)
125 {
126 if (((uword)x) >= CPU.msize)
127 {
128 if (issue_messages)
129 fprintf (stderr, "byte write to 0x%x outside memory range\n", x);
130
131 CPU.exception = SIGSEGV;
132 }
133 else
134 {
135 unsigned char *p = CPU.memory + x;
136 p[0] = v;
137 }
138 }
139
140 static void /* INLINE */
141 wlat (word x, word v)
142 {
143 if (((uword)x) >= CPU.msize)
144 {
145 if (issue_messages)
146 fprintf (stderr, "word write to 0x%x outside memory range\n", x);
147
148 CPU.exception = SIGSEGV;
149 }
150 else
151 {
152 if ((x & 3) != 0)
153 {
154 if (issue_messages)
155 fprintf (stderr, "word write to unaligned memory address: 0x%x\n", x);
156
157 CPU.exception = SIGBUS;
158 }
159 else if (!target_big_endian)
160 {
161 unsigned char *p = CPU.memory + x;
162 p[3] = v >> 24;
163 p[2] = v >> 16;
164 p[1] = v >> 8;
165 p[0] = v;
166 }
167 else
168 {
169 unsigned char *p = CPU.memory + x;
170 p[0] = v >> 24;
171 p[1] = v >> 16;
172 p[2] = v >> 8;
173 p[3] = v;
174 }
175 }
176 }
177
178 static void /* INLINE */
179 what (word x, word v)
180 {
181 if (((uword)x) >= CPU.msize)
182 {
183 if (issue_messages)
184 fprintf (stderr, "short write to 0x%x outside memory range\n", x);
185
186 CPU.exception = SIGSEGV;
187 }
188 else
189 {
190 if ((x & 1) != 0)
191 {
192 if (issue_messages)
193 fprintf (stderr, "short write to unaligned memory address: 0x%x\n",
194 x);
195
196 CPU.exception = SIGBUS;
197 }
198 else if (!target_big_endian)
199 {
200 unsigned char *p = CPU.memory + x;
201 p[1] = v >> 8;
202 p[0] = v;
203 }
204 else
205 {
206 unsigned char *p = CPU.memory + x;
207 p[0] = v >> 8;
208 p[1] = v;
209 }
210 }
211 }
212
213 /* Read functions. */
214 static int /* INLINE */
215 rbat (word x)
216 {
217 if (((uword)x) >= CPU.msize)
218 {
219 if (issue_messages)
220 fprintf (stderr, "byte read from 0x%x outside memory range\n", x);
221
222 CPU.exception = SIGSEGV;
223 return 0;
224 }
225 else
226 {
227 unsigned char *p = CPU.memory + x;
228 return p[0];
229 }
230 }
231
232 static int /* INLINE */
233 rlat (word x)
234 {
235 if (((uword) x) >= CPU.msize)
236 {
237 if (issue_messages)
238 fprintf (stderr, "word read from 0x%x outside memory range\n", x);
239
240 CPU.exception = SIGSEGV;
241 return 0;
242 }
243 else
244 {
245 if ((x & 3) != 0)
246 {
247 if (issue_messages)
248 fprintf (stderr, "word read from unaligned address: 0x%x\n", x);
249
250 CPU.exception = SIGBUS;
251 return 0;
252 }
253 else if (! target_big_endian)
254 {
255 unsigned char *p = CPU.memory + x;
256 return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
257 }
258 else
259 {
260 unsigned char *p = CPU.memory + x;
261 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
262 }
263 }
264 }
265
266 static int /* INLINE */
267 rhat (word x)
268 {
269 if (((uword)x) >= CPU.msize)
270 {
271 if (issue_messages)
272 fprintf (stderr, "short read from 0x%x outside memory range\n", x);
273
274 CPU.exception = SIGSEGV;
275 return 0;
276 }
277 else
278 {
279 if ((x & 1) != 0)
280 {
281 if (issue_messages)
282 fprintf (stderr, "short read from unaligned address: 0x%x\n", x);
283
284 CPU.exception = SIGBUS;
285 return 0;
286 }
287 else if (!target_big_endian)
288 {
289 unsigned char *p = CPU.memory + x;
290 return (p[1] << 8) | p[0];
291 }
292 else
293 {
294 unsigned char *p = CPU.memory + x;
295 return (p[0] << 8) | p[1];
296 }
297 }
298 }
299
300
301 #define SEXTB(x) (((x & 0xff) ^ (~ 0x7f)) + 0x80)
302 #define SEXTW(y) ((int)((short)y))
303
304 static int
305 IOMEM (int addr, int write, int value)
306 {
307 }
308
309 /* Default to a 8 Mbyte (== 2^23) memory space. */
310 static int sim_memory_size = 1 << 23;
311
312 #define MEM_SIZE_FLOOR 64
313 void
314 sim_size (int size)
315 {
316 sim_memory_size = size;
317 CPU.msize = sim_memory_size;
318
319 if (CPU.memory)
320 free (CPU.memory);
321
322 CPU.memory = (unsigned char *) calloc (1, CPU.msize);
323
324 if (!CPU.memory)
325 {
326 if (issue_messages)
327 fprintf (stderr,
328 "Not enough VM for simulation of %d bytes of RAM\n",
329 CPU.msize);
330
331 CPU.msize = 1;
332 CPU.memory = (unsigned char *) calloc (1, 1);
333 }
334 }
335
336 static void
337 init_pointers ()
338 {
339 if (CPU.msize != (sim_memory_size))
340 sim_size (sim_memory_size);
341 }
342
343 static void
344 set_initial_gprs ()
345 {
346 int i;
347 long space;
348 unsigned long memsize;
349
350 init_pointers ();
351
352 /* Set up machine just out of reset. */
353 PC = 0;
354 MSR = 0;
355
356 memsize = CPU.msize / (1024 * 1024);
357
358 if (issue_messages > 1)
359 fprintf (stderr, "Simulated memory of %d Mbytes (0x0 .. 0x%08x)\n",
360 memsize, CPU.msize - 1);
361
362 /* Clean out the GPRs */
363 for (i = 0; i < 32; i++)
364 CPU.regs[i] = 0;
365 CPU.insts = 0;
366 CPU.cycles = 0;
367 CPU.imm_enable = 0;
368
369 }
370
371 static void
372 interrupt ()
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
382 unsigned char opened[100];
383
384 static void
385 log_open (int fd)
386 {
387 if (fd < 0 || fd > NUM_ELEM (opened))
388 return;
389
390 opened[fd] = 1;
391 }
392
393 static void
394 log_close (int fd)
395 {
396 if (fd < 0 || fd > NUM_ELEM (opened))
397 return;
398
399 opened[fd] = 0;
400 }
401
402 static int
403 is_opened (int fd)
404 {
405 if (fd < 0 || fd > NUM_ELEM (opened))
406 return 0;
407
408 return opened[fd];
409 }
410
411 static void
412 handle_trap1 ()
413 {
414 }
415
416 static void
417 process_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
439 static void
440 util (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. */
480 static int
481 iu_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
496 word WL[MAXWL];
497 char *WLstr[MAXWL];
498
499 int ENDWL=0;
500 int WLincyc;
501 int WLcyc[MAXWL];
502 int WLcnts[MAXWL];
503 int WLmax[MAXWL];
504 int WLmin[MAXWL];
505 word WLendpc;
506 int WLbcyc;
507 int WLW;
508 #endif
509
510 static int tracing = 0;
511
512 void
513 sim_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
705 int
706 sim_write (SIM_DESC sd, SIM_ADDR addr, const unsigned char *buffer, int size)
707 {
708 int i;
709 init_pointers ();
710
711 memcpy (&CPU.memory[addr], buffer, size);
712
713 return size;
714 }
715
716 int
717 sim_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
728 int
729 sim_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
752 int
753 sim_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
779 int
780 sim_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
791 void
792 sim_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
807 int
808 sim_stop (SIM_DESC sd)
809 {
810 CPU.exception = SIGINT;
811 return 1;
812 }
813
814
815 void
816 sim_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
851 struct 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
867 SIM_DESC
868 sim_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
888 void
889 sim_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
899 SIM_RC
900 sim_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
985 SIM_RC
986 sim_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
1012 void
1013 sim_kill (SIM_DESC sd)
1014 {
1015 /* nothing to do */
1016 }
1017
1018 void
1019 sim_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
1086 void
1087 sim_set_callbacks (host_callback *ptr)
1088 {
1089 callback = ptr;
1090 }
1091
1092 char **
1093 sim_complete_command (SIM_DESC sd, char *text, char *word)
1094 {
1095 return NULL;
1096 }