Silence uninitialized warning on ehdr_start_save
[platform/upstream/binutils.git] / sim / microblaze / interp.c
1 /* Simulator for Xilinx MicroBlaze processor
2    Copyright 2009-2014 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, const char *text, const char *word)
1094 {
1095   return NULL;
1096 }