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