xref: /netbsd-src/external/gpl3/gdb/dist/sim/microblaze/interp.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /* Simulator for Xilinx MicroBlaze processor
2    Copyright 2009, 2010, 2011 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 }
1092