1 #include "sim-main.h"
2 #include "sim-options.h"
3 #include "v850_sim.h"
4 #include "sim-assert.h"
5 #include "itable.h"
6 
7 #ifdef HAVE_STDLIB_H
8 #include <stdlib.h>
9 #endif
10 
11 #ifdef HAVE_STRING_H
12 #include <string.h>
13 #else
14 #ifdef HAVE_STRINGS_H
15 #include <strings.h>
16 #endif
17 #endif
18 
19 #include "bfd.h"
20 
21 #ifndef INLINE
22 #ifdef __GNUC__
23 #define INLINE inline
24 #else
25 #define INLINE
26 #endif
27 #endif
28 
29 static const char * get_insn_name (sim_cpu *, int);
30 
31 /* For compatibility */
32 SIM_DESC simulator;
33 
34 
35 
36 /* v850 interrupt model */
37 
38 enum interrupt_type
39 {
40   int_reset,
41   int_nmi,
42   int_intov1,
43   int_intp10,
44   int_intp11,
45   int_intp12,
46   int_intp13,
47   int_intcm4,
48   num_int_types
49 };
50 
51 char *interrupt_names[] = {
52   "reset",
53   "nmi",
54   "intov1",
55   "intp10",
56   "intp11",
57   "intp12",
58   "intp13",
59   "intcm4",
60   NULL
61 };
62 
63 static void
do_interrupt(sd,data)64 do_interrupt (sd, data)
65      SIM_DESC sd;
66      void *data;
67 {
68   char **interrupt_name = (char**)data;
69   enum interrupt_type inttype;
70   inttype = (interrupt_name - STATE_WATCHPOINTS (sd)->interrupt_names);
71 
72   /* For a hardware reset, drop everything and jump to the start
73      address */
74   if (inttype == int_reset)
75     {
76       PC = 0;
77       PSW = 0x20;
78       ECR = 0;
79       sim_engine_restart (sd, NULL, NULL, NULL_CIA);
80     }
81 
82   /* Deliver an NMI when allowed */
83   if (inttype == int_nmi)
84     {
85       if (PSW & PSW_NP)
86 	{
87 	  /* We're already working on an NMI, so this one must wait
88 	     around until the previous one is done.  The processor
89 	     ignores subsequent NMIs, so we don't need to count them.
90 	     Just keep re-scheduling a single NMI until it manages to
91 	     be delivered */
92 	  if (STATE_CPU (sd, 0)->pending_nmi != NULL)
93 	    sim_events_deschedule (sd, STATE_CPU (sd, 0)->pending_nmi);
94 	  STATE_CPU (sd, 0)->pending_nmi =
95 	    sim_events_schedule (sd, 1, do_interrupt, data);
96 	  return;
97 	}
98       else
99 	{
100 	  /* NMI can be delivered.  Do not deschedule pending_nmi as
101              that, if still in the event queue, is a second NMI that
102              needs to be delivered later. */
103 	  FEPC = PC;
104 	  FEPSW = PSW;
105 	  /* Set the FECC part of the ECR. */
106 	  ECR &= 0x0000ffff;
107 	  ECR |= 0x10;
108 	  PSW |= PSW_NP;
109 	  PSW &= ~PSW_EP;
110 	  PSW |= PSW_ID;
111 	  PC = 0x10;
112 	  sim_engine_restart (sd, NULL, NULL, NULL_CIA);
113 	}
114     }
115 
116   /* deliver maskable interrupt when allowed */
117   if (inttype > int_nmi && inttype < num_int_types)
118     {
119       if ((PSW & PSW_NP) || (PSW & PSW_ID))
120 	{
121 	  /* Can't deliver this interrupt, reschedule it for later */
122 	  sim_events_schedule (sd, 1, do_interrupt, data);
123 	  return;
124 	}
125       else
126 	{
127 	  /* save context */
128 	  EIPC = PC;
129 	  EIPSW = PSW;
130 	  /* Disable further interrupts.  */
131 	  PSW |= PSW_ID;
132 	  /* Indicate that we're doing interrupt not exception processing.  */
133 	  PSW &= ~PSW_EP;
134 	  /* Clear the EICC part of the ECR, will set below. */
135 	  ECR &= 0xffff0000;
136 	  switch (inttype)
137 	    {
138 	    case int_intov1:
139 	      PC = 0x80;
140 	      ECR |= 0x80;
141 	      break;
142 	    case int_intp10:
143 	      PC = 0x90;
144 	      ECR |= 0x90;
145 	      break;
146 	    case int_intp11:
147 	      PC = 0xa0;
148 	      ECR |= 0xa0;
149 	      break;
150 	    case int_intp12:
151 	      PC = 0xb0;
152 	      ECR |= 0xb0;
153 	      break;
154 	    case int_intp13:
155 	      PC = 0xc0;
156 	      ECR |= 0xc0;
157 	      break;
158 	    case int_intcm4:
159 	      PC = 0xd0;
160 	      ECR |= 0xd0;
161 	      break;
162 	    default:
163 	      /* Should never be possible.  */
164 	      sim_engine_abort (sd, NULL, NULL_CIA,
165 				"do_interrupt - internal error - bad switch");
166 	      break;
167 	    }
168 	}
169       sim_engine_restart (sd, NULL, NULL, NULL_CIA);
170     }
171 
172   /* some other interrupt? */
173   sim_engine_abort (sd, NULL, NULL_CIA,
174 		    "do_interrupt - internal error - interrupt %d unknown",
175 		    inttype);
176 }
177 
178 /* Return name of an insn, used by insn profiling.  */
179 
180 static const char *
get_insn_name(sim_cpu * cpu,int i)181 get_insn_name (sim_cpu *cpu, int i)
182 {
183   return itable[i].name;
184 }
185 
186 /* These default values correspond to expected usage for the chip.  */
187 
188 uint32 OP[4];
189 
190 
191 SIM_DESC
sim_open(kind,cb,abfd,argv)192 sim_open (kind, cb, abfd, argv)
193      SIM_OPEN_KIND kind;
194      host_callback *cb;
195      struct bfd *abfd;
196      char **argv;
197 {
198   SIM_DESC sd = sim_state_alloc (kind, cb);
199   int mach;
200 
201   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
202 
203   /* for compatibility */
204   simulator = sd;
205 
206   /* FIXME: should be better way of setting up interrupts */
207   STATE_WATCHPOINTS (sd)->pc = &(PC);
208   STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
209   STATE_WATCHPOINTS (sd)->interrupt_handler = do_interrupt;
210   STATE_WATCHPOINTS (sd)->interrupt_names = interrupt_names;
211 
212   /* Initialize the mechanism for doing insn profiling.  */
213   CPU_INSN_NAME (STATE_CPU (sd, 0)) = get_insn_name;
214   CPU_MAX_INSNS (STATE_CPU (sd, 0)) = nr_itable_entries;
215 
216   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
217     return 0;
218 
219   /* Allocate core managed memory */
220 
221   /* "Mirror" the ROM addresses below 1MB. */
222   sim_do_commandf (sd, "memory region 0,0x100000,0x%lx", V850_ROM_SIZE);
223   /* Chunk of ram adjacent to rom */
224   sim_do_commandf (sd, "memory region 0x100000,0x%lx", V850_LOW_END-0x100000);
225   /* peripheral I/O region - mirror 1K across 4k (0x1000) */
226   sim_do_command (sd, "memory region 0xfff000,0x1000,1024");
227   /* similarly if in the internal RAM region */
228   sim_do_command (sd, "memory region 0xffe000,0x1000,1024");
229 
230   /* getopt will print the error message so we just have to exit if this fails.
231      FIXME: Hmmm...  in the case of gdb we need getopt to call
232      print_filtered.  */
233   if (sim_parse_args (sd, argv) != SIM_RC_OK)
234     {
235       /* Uninstall the modules to avoid memory leaks,
236 	 file descriptor leaks, etc.  */
237       sim_module_uninstall (sd);
238       return 0;
239     }
240 
241   /* check for/establish the a reference program image */
242   if (sim_analyze_program (sd,
243 			   (STATE_PROG_ARGV (sd) != NULL
244 			    ? *STATE_PROG_ARGV (sd)
245 			    : NULL),
246 			   abfd) != SIM_RC_OK)
247     {
248       sim_module_uninstall (sd);
249       return 0;
250     }
251 
252   /* establish any remaining configuration options */
253   if (sim_config (sd) != SIM_RC_OK)
254     {
255       sim_module_uninstall (sd);
256       return 0;
257     }
258 
259   if (sim_post_argv_init (sd) != SIM_RC_OK)
260     {
261       /* Uninstall the modules to avoid memory leaks,
262 	 file descriptor leaks, etc.  */
263       sim_module_uninstall (sd);
264       return 0;
265     }
266 
267 
268   /* determine the machine type */
269   if (STATE_ARCHITECTURE (sd) != NULL
270       && STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850)
271     mach = STATE_ARCHITECTURE (sd)->mach;
272   else
273     mach = bfd_mach_v850; /* default */
274 
275   /* set machine specific configuration */
276   switch (mach)
277     {
278     case bfd_mach_v850:
279     case bfd_mach_v850e:
280     case bfd_mach_v850e1:
281       STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT
282 				     | PSW_CY | PSW_OV | PSW_S | PSW_Z);
283       break;
284     }
285 
286   return sd;
287 }
288 
289 
290 void
sim_close(sd,quitting)291 sim_close (sd, quitting)
292      SIM_DESC sd;
293      int quitting;
294 {
295   sim_module_uninstall (sd);
296 }
297 
298 SIM_RC
sim_create_inferior(sd,prog_bfd,argv,env)299 sim_create_inferior (sd, prog_bfd, argv, env)
300      SIM_DESC sd;
301      struct bfd *prog_bfd;
302      char **argv;
303      char **env;
304 {
305   memset (&State, 0, sizeof (State));
306   if (prog_bfd != NULL)
307     PC = bfd_get_start_address (prog_bfd);
308   return SIM_RC_OK;
309 }
310 
311 int
sim_fetch_register(sd,rn,memory,length)312 sim_fetch_register (sd, rn, memory, length)
313      SIM_DESC sd;
314      int rn;
315      unsigned char *memory;
316      int length;
317 {
318   *(unsigned32*)memory = H2T_4 (State.regs[rn]);
319   return -1;
320 }
321 
322 int
sim_store_register(sd,rn,memory,length)323 sim_store_register (sd, rn, memory, length)
324      SIM_DESC sd;
325      int rn;
326      unsigned char *memory;
327      int length;
328 {
329   State.regs[rn] = T2H_4 (*(unsigned32*)memory);
330   return -1;
331 }
332 
333 void
sim_do_command(sd,cmd)334 sim_do_command (sd, cmd)
335      SIM_DESC sd;
336      char *cmd;
337 {
338   char *mm_cmd = "memory-map";
339   char *int_cmd = "interrupt";
340 
341   if (sim_args_command (sd, cmd) != SIM_RC_OK)
342     {
343       if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0))
344 	sim_io_eprintf (sd, "`memory-map' command replaced by `sim memory'\n");
345       else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0)
346 	sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n");
347       else
348 	sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
349     }
350 }
351