xref: /netbsd-src/external/gpl3/gdb/dist/sim/microblaze/interp.c (revision 0d3e0572e40d81edb4fdbff937458d47b685c34c)
14e98e3e1Schristos /* Simulator for Xilinx MicroBlaze processor
2*0d3e0572Schristos    Copyright 2009-2024 Free Software Foundation, Inc.
34e98e3e1Schristos 
44e98e3e1Schristos    This file is part of GDB, the GNU debugger.
54e98e3e1Schristos 
64e98e3e1Schristos    This program is free software; you can redistribute it and/or modify
74e98e3e1Schristos    it under the terms of the GNU General Public License as published by
8a2e2270fSchristos    the Free Software Foundation; either version 3 of the License, or
94e98e3e1Schristos    (at your option) any later version.
104e98e3e1Schristos 
114e98e3e1Schristos    This program is distributed in the hope that it will be useful,
124e98e3e1Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
134e98e3e1Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
144e98e3e1Schristos    GNU General Public License for more details.
154e98e3e1Schristos 
164e98e3e1Schristos    You should have received a copy of the GNU General Public License
17a2e2270fSchristos    along with this program; if not, see <http://www.gnu.org/licenses/>.  */
184e98e3e1Schristos 
194b169a6bSchristos /* This must come before any other includes.  */
204b169a6bSchristos #include "defs.h"
214b169a6bSchristos 
22212397c6Schristos #include <stdlib.h>
23212397c6Schristos #include <string.h>
24212397c6Schristos #include <unistd.h>
254e98e3e1Schristos #include "bfd.h"
264b169a6bSchristos #include "sim/callback.h"
274e98e3e1Schristos #include "libiberty.h"
284b169a6bSchristos #include "sim/sim.h"
29212397c6Schristos 
304e98e3e1Schristos #include "sim-main.h"
31212397c6Schristos #include "sim-options.h"
324b169a6bSchristos #include "sim-signal.h"
334b169a6bSchristos #include "sim-syscall.h"
34212397c6Schristos 
35*0d3e0572Schristos #include "microblaze-sim.h"
36*0d3e0572Schristos #include "opcodes/microblaze-dis.h"
374e98e3e1Schristos 
384559860eSchristos #define target_big_endian (CURRENT_TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
394e98e3e1Schristos 
40212397c6Schristos static unsigned long
414b169a6bSchristos microblaze_extract_unsigned_integer (const unsigned char *addr, int len)
424e98e3e1Schristos {
434e98e3e1Schristos   unsigned long retval;
444e98e3e1Schristos   unsigned char *p;
454e98e3e1Schristos   unsigned char *startaddr = (unsigned char *)addr;
464e98e3e1Schristos   unsigned char *endaddr = startaddr + len;
474e98e3e1Schristos 
484e98e3e1Schristos   if (len > (int) sizeof (unsigned long))
494e98e3e1Schristos     printf ("That operation is not available on integers of more than "
50212397c6Schristos 	    "%zu bytes.", sizeof (unsigned long));
514e98e3e1Schristos 
524e98e3e1Schristos   /* Start at the most significant end of the integer, and work towards
534e98e3e1Schristos      the least significant.  */
544e98e3e1Schristos   retval = 0;
554e98e3e1Schristos 
564e98e3e1Schristos   if (!target_big_endian)
574e98e3e1Schristos     {
584e98e3e1Schristos       for (p = endaddr; p > startaddr;)
594e98e3e1Schristos 	retval = (retval << 8) | * -- p;
604e98e3e1Schristos     }
614e98e3e1Schristos   else
624e98e3e1Schristos     {
634e98e3e1Schristos       for (p = startaddr; p < endaddr;)
644e98e3e1Schristos 	retval = (retval << 8) | * p ++;
654e98e3e1Schristos     }
664e98e3e1Schristos 
674e98e3e1Schristos   return retval;
684e98e3e1Schristos }
694e98e3e1Schristos 
70212397c6Schristos static void
714e98e3e1Schristos microblaze_store_unsigned_integer (unsigned char *addr, int len,
724e98e3e1Schristos 				   unsigned long val)
734e98e3e1Schristos {
744e98e3e1Schristos   unsigned char *p;
754e98e3e1Schristos   unsigned char *startaddr = (unsigned char *)addr;
764e98e3e1Schristos   unsigned char *endaddr = startaddr + len;
774e98e3e1Schristos 
784e98e3e1Schristos   if (!target_big_endian)
794e98e3e1Schristos     {
804e98e3e1Schristos       for (p = startaddr; p < endaddr;)
814e98e3e1Schristos 	{
824e98e3e1Schristos 	  *p++ = val & 0xff;
834e98e3e1Schristos 	  val >>= 8;
844e98e3e1Schristos 	}
854e98e3e1Schristos     }
864e98e3e1Schristos   else
874e98e3e1Schristos     {
884e98e3e1Schristos       for (p = endaddr; p > startaddr;)
894e98e3e1Schristos 	{
904e98e3e1Schristos 	  *--p = val & 0xff;
914e98e3e1Schristos 	  val >>= 8;
924e98e3e1Schristos 	}
934e98e3e1Schristos     }
944e98e3e1Schristos }
954e98e3e1Schristos 
964e98e3e1Schristos static void
97212397c6Schristos set_initial_gprs (SIM_CPU *cpu)
984e98e3e1Schristos {
994e98e3e1Schristos   int i;
1004e98e3e1Schristos 
1014e98e3e1Schristos   /* Set up machine just out of reset.  */
1024e98e3e1Schristos   PC = 0;
1034e98e3e1Schristos   MSR = 0;
1044e98e3e1Schristos 
1054e98e3e1Schristos   /* Clean out the GPRs */
1064e98e3e1Schristos   for (i = 0; i < 32; i++)
1074e98e3e1Schristos     CPU.regs[i] = 0;
1084e98e3e1Schristos   CPU.insts = 0;
1094e98e3e1Schristos   CPU.cycles = 0;
1104e98e3e1Schristos   CPU.imm_enable = 0;
1114e98e3e1Schristos }
1124e98e3e1Schristos 
1134e98e3e1Schristos static int tracing = 0;
1144e98e3e1Schristos 
1154e98e3e1Schristos void
116212397c6Schristos sim_engine_run (SIM_DESC sd,
117212397c6Schristos 		int next_cpu_nr, /* ignore  */
118212397c6Schristos 		int nr_cpus, /* ignore  */
119212397c6Schristos 		int siggnal) /* ignore  */
1204e98e3e1Schristos {
121212397c6Schristos   SIM_CPU *cpu = STATE_CPU (sd, 0);
1224b169a6bSchristos   signed_4 inst;
1234e98e3e1Schristos   enum microblaze_instr op;
1244e98e3e1Schristos   int memops;
1254e98e3e1Schristos   int bonus_cycles;
1264e98e3e1Schristos   int insts;
1274b169a6bSchristos   unsigned_1 carry;
1284b169a6bSchristos   bool imm_unsigned;
1294e98e3e1Schristos   short ra, rb, rd;
1304b169a6bSchristos   unsigned_4 oldpc, newpc;
1314e98e3e1Schristos   short delay_slot_enable;
1324e98e3e1Schristos   short branch_taken;
1334e98e3e1Schristos   short num_delay_slot; /* UNUSED except as reqd parameter */
1344e98e3e1Schristos   enum microblaze_instr_type insn_type;
1354e98e3e1Schristos 
1364e98e3e1Schristos   memops = 0;
1374e98e3e1Schristos   bonus_cycles = 0;
1384e98e3e1Schristos   insts = 0;
1394e98e3e1Schristos 
140212397c6Schristos   while (1)
1414e98e3e1Schristos     {
1424e98e3e1Schristos       /* Fetch the initial instructions that we'll decode. */
143212397c6Schristos       inst = MEM_RD_WORD (PC & 0xFFFFFFFC);
1444e98e3e1Schristos 
1454e98e3e1Schristos       op = get_insn_microblaze (inst, &imm_unsigned, &insn_type,
1464e98e3e1Schristos 				&num_delay_slot);
1474e98e3e1Schristos 
1484e98e3e1Schristos       if (op == invalid_inst)
1494e98e3e1Schristos 	fprintf (stderr, "Unknown instruction 0x%04x", inst);
1504e98e3e1Schristos 
1514e98e3e1Schristos       if (tracing)
1524e98e3e1Schristos 	fprintf (stderr, "%.4x: inst = %.4x ", PC, inst);
1534e98e3e1Schristos 
1544e98e3e1Schristos       rd = GET_RD;
1554e98e3e1Schristos       rb = GET_RB;
1564e98e3e1Schristos       ra = GET_RA;
1574e98e3e1Schristos       /*      immword = IMM_W; */
1584e98e3e1Schristos 
1594e98e3e1Schristos       oldpc = PC;
1604e98e3e1Schristos       delay_slot_enable = 0;
1614e98e3e1Schristos       branch_taken = 0;
1624e98e3e1Schristos       if (op == microblaze_brk)
163212397c6Schristos 	sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
1644e98e3e1Schristos       else if (inst == MICROBLAZE_HALT_INST)
1654e98e3e1Schristos 	{
1664e98e3e1Schristos 	  insts += 1;
1674e98e3e1Schristos 	  bonus_cycles++;
1684b169a6bSchristos 	  TRACE_INSN (cpu, "HALT (%i)", RETREG);
169212397c6Schristos 	  sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_exited, RETREG);
1704e98e3e1Schristos 	}
1714e98e3e1Schristos       else
1724e98e3e1Schristos 	{
1734e98e3e1Schristos 	  switch(op)
1744e98e3e1Schristos 	    {
1754e98e3e1Schristos #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION)		\
1764e98e3e1Schristos 	    case NAME:					\
1774b169a6bSchristos 	      TRACE_INSN (cpu, #NAME);			\
1784e98e3e1Schristos 	      ACTION;					\
1794e98e3e1Schristos 	      break;
1804e98e3e1Schristos #include "microblaze.isa"
1814e98e3e1Schristos #undef INSTRUCTION
1824e98e3e1Schristos 
1834e98e3e1Schristos 	    default:
184212397c6Schristos 	      sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_signalled,
185212397c6Schristos 			       SIM_SIGILL);
1864e98e3e1Schristos 	      fprintf (stderr, "ERROR: Unknown opcode\n");
1874e98e3e1Schristos 	    }
1884e98e3e1Schristos 	  /* Make R0 consistent */
1894e98e3e1Schristos 	  CPU.regs[0] = 0;
1904e98e3e1Schristos 
1914e98e3e1Schristos 	  /* Check for imm instr */
1924e98e3e1Schristos 	  if (op == imm)
1934e98e3e1Schristos 	    IMM_ENABLE = 1;
1944e98e3e1Schristos 	  else
1954e98e3e1Schristos 	    IMM_ENABLE = 0;
1964e98e3e1Schristos 
1974e98e3e1Schristos 	  /* Update cycle counts */
1984e98e3e1Schristos 	  insts ++;
1994e98e3e1Schristos 	  if (insn_type == memory_store_inst || insn_type == memory_load_inst)
2004e98e3e1Schristos 	    memops++;
2014e98e3e1Schristos 	  if (insn_type == mult_inst)
2024e98e3e1Schristos 	    bonus_cycles++;
2034e98e3e1Schristos 	  if (insn_type == barrel_shift_inst)
2044e98e3e1Schristos 	    bonus_cycles++;
2054e98e3e1Schristos 	  if (insn_type == anyware_inst)
2064e98e3e1Schristos 	    bonus_cycles++;
2074e98e3e1Schristos 	  if (insn_type == div_inst)
2084e98e3e1Schristos 	    bonus_cycles += 33;
2094e98e3e1Schristos 
2104e98e3e1Schristos 	  if ((insn_type == branch_inst || insn_type == return_inst)
2114e98e3e1Schristos 	      && branch_taken)
2124e98e3e1Schristos 	    {
2134e98e3e1Schristos 	      /* Add an extra cycle for taken branches */
2144e98e3e1Schristos 	      bonus_cycles++;
2154e98e3e1Schristos 	      /* For branch instructions handle the instruction in the delay slot */
2164e98e3e1Schristos 	      if (delay_slot_enable)
2174e98e3e1Schristos 	        {
2184e98e3e1Schristos 	          newpc = PC;
2194e98e3e1Schristos 	          PC = oldpc + INST_SIZE;
220212397c6Schristos 	          inst = MEM_RD_WORD (PC & 0xFFFFFFFC);
2214e98e3e1Schristos 	          op = get_insn_microblaze (inst, &imm_unsigned, &insn_type,
2224e98e3e1Schristos 					    &num_delay_slot);
2234e98e3e1Schristos 	          if (op == invalid_inst)
2244e98e3e1Schristos 		    fprintf (stderr, "Unknown instruction 0x%04x", inst);
2254e98e3e1Schristos 	          if (tracing)
2264e98e3e1Schristos 		    fprintf (stderr, "%.4x: inst = %.4x ", PC, inst);
2274e98e3e1Schristos 	          rd = GET_RD;
2284e98e3e1Schristos 	          rb = GET_RB;
2294e98e3e1Schristos 	          ra = GET_RA;
2304e98e3e1Schristos 	          /*	      immword = IMM_W; */
2314e98e3e1Schristos 	          if (op == microblaze_brk)
2324e98e3e1Schristos 		    {
233212397c6Schristos 		      if (STATE_VERBOSE_P (sd))
2344e98e3e1Schristos 		        fprintf (stderr, "Breakpoint set in delay slot "
2354e98e3e1Schristos 			         "(at address 0x%x) will not be honored\n", PC);
2364e98e3e1Schristos 		      /* ignore the breakpoint */
2374e98e3e1Schristos 		    }
2384e98e3e1Schristos 	          else if (insn_type == branch_inst || insn_type == return_inst)
2394e98e3e1Schristos 		    {
240212397c6Schristos 		      if (STATE_VERBOSE_P (sd))
2414e98e3e1Schristos 		        fprintf (stderr, "Cannot have branch or return instructions "
2424e98e3e1Schristos 			         "in delay slot (at address 0x%x)\n", PC);
243212397c6Schristos 		      sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_signalled,
244212397c6Schristos 				       SIM_SIGILL);
2454e98e3e1Schristos 		    }
2464e98e3e1Schristos 	          else
2474e98e3e1Schristos 		    {
2484e98e3e1Schristos 		      switch(op)
2494e98e3e1Schristos 		        {
2504e98e3e1Schristos #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION)		\
2514e98e3e1Schristos 		        case NAME:			\
2524e98e3e1Schristos 			  ACTION;			\
2534e98e3e1Schristos 			  break;
2544e98e3e1Schristos #include "microblaze.isa"
2554e98e3e1Schristos #undef INSTRUCTION
2564e98e3e1Schristos 
2574e98e3e1Schristos 		        default:
258212397c6Schristos 		          sim_engine_halt (sd, NULL, NULL, NULL_CIA,
259212397c6Schristos 					   sim_signalled, SIM_SIGILL);
2604e98e3e1Schristos 		          fprintf (stderr, "ERROR: Unknown opcode at 0x%x\n", PC);
2614e98e3e1Schristos 		        }
2624e98e3e1Schristos 		      /* Update cycle counts */
2634e98e3e1Schristos 		      insts++;
2644e98e3e1Schristos 		      if (insn_type == memory_store_inst
2654e98e3e1Schristos 		          || insn_type == memory_load_inst)
2664e98e3e1Schristos 		        memops++;
2674e98e3e1Schristos 		      if (insn_type == mult_inst)
2684e98e3e1Schristos 		        bonus_cycles++;
2694e98e3e1Schristos 		      if (insn_type == barrel_shift_inst)
2704e98e3e1Schristos 		        bonus_cycles++;
2714e98e3e1Schristos 		      if (insn_type == anyware_inst)
2724e98e3e1Schristos 		        bonus_cycles++;
2734e98e3e1Schristos 		      if (insn_type == div_inst)
2744e98e3e1Schristos 		        bonus_cycles += 33;
2754e98e3e1Schristos 		    }
2764e98e3e1Schristos 	          /* Restore the PC */
2774e98e3e1Schristos 	          PC = newpc;
2784e98e3e1Schristos 	          /* Make R0 consistent */
2794e98e3e1Schristos 	          CPU.regs[0] = 0;
2804e98e3e1Schristos 	          /* Check for imm instr */
2814e98e3e1Schristos 	          if (op == imm)
2824e98e3e1Schristos 		    IMM_ENABLE = 1;
2834e98e3e1Schristos 	          else
2844e98e3e1Schristos 		    IMM_ENABLE = 0;
2854e98e3e1Schristos 	        }
2864e98e3e1Schristos 	      else
2874b169a6bSchristos 		{
2884b169a6bSchristos 		  if (op == brki && IMM == 8)
2894b169a6bSchristos 		    {
2904b169a6bSchristos 		      RETREG = sim_syscall (cpu, CPU.regs[12], CPU.regs[5],
2914b169a6bSchristos 					    CPU.regs[6], CPU.regs[7],
2924b169a6bSchristos 					    CPU.regs[8]);
2934b169a6bSchristos 		      PC = RD + INST_SIZE;
2944b169a6bSchristos 		    }
2954b169a6bSchristos 
2964e98e3e1Schristos 		  /* no delay slot: increment cycle count */
2974e98e3e1Schristos 		  bonus_cycles++;
2984e98e3e1Schristos 		}
2994e98e3e1Schristos 	    }
3004b169a6bSchristos 	}
3014e98e3e1Schristos 
3024e98e3e1Schristos       if (tracing)
3034e98e3e1Schristos 	fprintf (stderr, "\n");
304212397c6Schristos 
305212397c6Schristos       if (sim_events_tick (sd))
306212397c6Schristos 	sim_events_process (sd);
3074e98e3e1Schristos     }
3084e98e3e1Schristos 
3094e98e3e1Schristos   /* Hide away the things we've cached while executing.  */
3104e98e3e1Schristos   /*  CPU.pc = pc; */
3114e98e3e1Schristos   CPU.insts += insts;		/* instructions done ... */
3124e98e3e1Schristos   CPU.cycles += insts;		/* and each takes a cycle */
3134e98e3e1Schristos   CPU.cycles += bonus_cycles;	/* and extra cycles for branches */
3144e98e3e1Schristos   CPU.cycles += memops; 	/* and memop cycle delays */
3154e98e3e1Schristos }
3164e98e3e1Schristos 
317ba340e45Schristos static int
3184b169a6bSchristos microblaze_reg_store (SIM_CPU *cpu, int rn, const void *memory, int length)
3194e98e3e1Schristos {
3204e98e3e1Schristos   if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
3214e98e3e1Schristos     {
3224e98e3e1Schristos       if (length == 4)
3234e98e3e1Schristos 	{
3244e98e3e1Schristos 	  /* misalignment safe */
3254e98e3e1Schristos 	  long ival = microblaze_extract_unsigned_integer (memory, 4);
3264e98e3e1Schristos 	  if (rn < NUM_REGS)
3274e98e3e1Schristos 	    CPU.regs[rn] = ival;
3284e98e3e1Schristos 	  else
3294e98e3e1Schristos 	    CPU.spregs[rn-NUM_REGS] = ival;
3304e98e3e1Schristos 	  return 4;
3314e98e3e1Schristos 	}
3324e98e3e1Schristos       else
3334e98e3e1Schristos 	return 0;
3344e98e3e1Schristos     }
3354e98e3e1Schristos   else
3364e98e3e1Schristos     return 0;
3374e98e3e1Schristos }
3384e98e3e1Schristos 
339ba340e45Schristos static int
3404b169a6bSchristos microblaze_reg_fetch (SIM_CPU *cpu, int rn, void *memory, int length)
3414e98e3e1Schristos {
3424e98e3e1Schristos   long ival;
3434e98e3e1Schristos 
3444e98e3e1Schristos   if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
3454e98e3e1Schristos     {
3464e98e3e1Schristos       if (length == 4)
3474e98e3e1Schristos 	{
3484e98e3e1Schristos 	  if (rn < NUM_REGS)
3494e98e3e1Schristos 	    ival = CPU.regs[rn];
3504e98e3e1Schristos 	  else
3514e98e3e1Schristos 	    ival = CPU.spregs[rn-NUM_REGS];
3524e98e3e1Schristos 
3534e98e3e1Schristos 	  /* misalignment-safe */
3544e98e3e1Schristos 	  microblaze_store_unsigned_integer (memory, 4, ival);
3554e98e3e1Schristos 	  return 4;
3564e98e3e1Schristos 	}
3574e98e3e1Schristos       else
3584e98e3e1Schristos 	return 0;
3594e98e3e1Schristos     }
3604e98e3e1Schristos   else
3614e98e3e1Schristos     return 0;
3624e98e3e1Schristos }
3634e98e3e1Schristos 
3644e98e3e1Schristos void
365*0d3e0572Schristos sim_info (SIM_DESC sd, bool verbose)
3664e98e3e1Schristos {
367212397c6Schristos   SIM_CPU *cpu = STATE_CPU (sd, 0);
368212397c6Schristos   host_callback *callback = STATE_CALLBACK (sd);
3694e98e3e1Schristos 
3704e98e3e1Schristos   callback->printf_filtered (callback, "\n\n# instructions executed  %10d\n",
3714e98e3e1Schristos 			     CPU.insts);
3724e98e3e1Schristos   callback->printf_filtered (callback, "# cycles                 %10d\n",
3734e98e3e1Schristos 			     (CPU.cycles) ? CPU.cycles+2 : 0);
3744e98e3e1Schristos }
3754e98e3e1Schristos 
376212397c6Schristos static sim_cia
377212397c6Schristos microblaze_pc_get (sim_cpu *cpu)
378212397c6Schristos {
379*0d3e0572Schristos   return MICROBLAZE_SIM_CPU (cpu)->spregs[0];
3804e98e3e1Schristos }
3814e98e3e1Schristos 
382212397c6Schristos static void
383212397c6Schristos microblaze_pc_set (sim_cpu *cpu, sim_cia pc)
3844e98e3e1Schristos {
385*0d3e0572Schristos   MICROBLAZE_SIM_CPU (cpu)->spregs[0] = pc;
386212397c6Schristos }
3874e98e3e1Schristos 
388212397c6Schristos static void
389212397c6Schristos free_state (SIM_DESC sd)
390212397c6Schristos {
391212397c6Schristos   if (STATE_MODULES (sd) != NULL)
392212397c6Schristos     sim_module_uninstall (sd);
393212397c6Schristos   sim_cpu_free_all (sd);
394212397c6Schristos   sim_state_free (sd);
395212397c6Schristos }
3964e98e3e1Schristos 
3974e98e3e1Schristos SIM_DESC
398ba340e45Schristos sim_open (SIM_OPEN_KIND kind, host_callback *cb,
399ba340e45Schristos 	  struct bfd *abfd, char * const *argv)
4004e98e3e1Schristos {
401212397c6Schristos   int i;
402212397c6Schristos   SIM_DESC sd = sim_state_alloc (kind, cb);
403212397c6Schristos   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
4044e98e3e1Schristos 
405212397c6Schristos   /* The cpu data is kept in a separately allocated chunk of memory.  */
406*0d3e0572Schristos   if (sim_cpu_alloc_all_extra (sd, 0, sizeof (struct microblaze_regset))
407*0d3e0572Schristos       != SIM_RC_OK)
408212397c6Schristos     {
409212397c6Schristos       free_state (sd);
410212397c6Schristos       return 0;
411212397c6Schristos     }
4124e98e3e1Schristos 
413212397c6Schristos   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
414212397c6Schristos     {
415212397c6Schristos       free_state (sd);
416212397c6Schristos       return 0;
417212397c6Schristos     }
4184e98e3e1Schristos 
419ba340e45Schristos   /* The parser will print an error message for us, so we silently return.  */
420212397c6Schristos   if (sim_parse_args (sd, argv) != SIM_RC_OK)
421212397c6Schristos     {
422212397c6Schristos       free_state (sd);
423212397c6Schristos       return 0;
424212397c6Schristos     }
4254e98e3e1Schristos 
426212397c6Schristos   /* Check for/establish the a reference program image.  */
4274b169a6bSchristos   if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
428212397c6Schristos     {
429212397c6Schristos       free_state (sd);
430212397c6Schristos       return 0;
431212397c6Schristos     }
4324e98e3e1Schristos 
433212397c6Schristos   /* Configure/verify the target byte order and other runtime
434212397c6Schristos      configuration options.  */
435212397c6Schristos   if (sim_config (sd) != SIM_RC_OK)
436212397c6Schristos     {
437212397c6Schristos       sim_module_uninstall (sd);
438212397c6Schristos       return 0;
439212397c6Schristos     }
440212397c6Schristos 
441212397c6Schristos   if (sim_post_argv_init (sd) != SIM_RC_OK)
442212397c6Schristos     {
443212397c6Schristos       /* Uninstall the modules to avoid memory leaks,
444212397c6Schristos 	 file descriptor leaks, etc.  */
445212397c6Schristos       sim_module_uninstall (sd);
446212397c6Schristos       return 0;
447212397c6Schristos     }
448212397c6Schristos 
449212397c6Schristos   /* CPU specific initialization.  */
450212397c6Schristos   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
451212397c6Schristos     {
452212397c6Schristos       SIM_CPU *cpu = STATE_CPU (sd, i);
453212397c6Schristos 
454ba340e45Schristos       CPU_REG_FETCH (cpu) = microblaze_reg_fetch;
455ba340e45Schristos       CPU_REG_STORE (cpu) = microblaze_reg_store;
456212397c6Schristos       CPU_PC_FETCH (cpu) = microblaze_pc_get;
457212397c6Schristos       CPU_PC_STORE (cpu) = microblaze_pc_set;
458212397c6Schristos 
459212397c6Schristos       set_initial_gprs (cpu);
460212397c6Schristos     }
461212397c6Schristos 
462212397c6Schristos   /* Default to a 8 Mbyte (== 2^23) memory space.  */
463212397c6Schristos   sim_do_commandf (sd, "memory-size 0x800000");
464212397c6Schristos 
465212397c6Schristos   return sd;
4664e98e3e1Schristos }
4674e98e3e1Schristos 
4684e98e3e1Schristos SIM_RC
469ba340e45Schristos sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
470ba340e45Schristos 		     char * const *argv, char * const *env)
4714e98e3e1Schristos {
472212397c6Schristos   SIM_CPU *cpu = STATE_CPU (sd, 0);
4734e98e3e1Schristos 
4744e98e3e1Schristos   PC = bfd_get_start_address (prog_bfd);
4754e98e3e1Schristos 
4764e98e3e1Schristos   return SIM_RC_OK;
4774e98e3e1Schristos }
478