Add multi-sim support to v850/v850e/v850eq simulators.
[external/binutils.git] / sim / v850 / interp.c
1 #include <signal.h>
2 #include "sim-main.h"
3 #include "sim-options.h"
4 #include "v850_sim.h"
5
6 #ifdef HAVE_STDLIB_H
7 #include <stdlib.h>
8 #endif
9
10 #ifdef HAVE_STRING_H
11 #include <string.h>
12 #else
13 #ifdef HAVE_STRINGS_H
14 #include <strings.h>
15 #endif
16 #endif
17
18 #include "bfd.h"
19
20 #ifndef INLINE
21 #ifdef __GNUC__
22 #define INLINE inline
23 #else
24 #define INLINE
25 #endif
26 #endif
27
28
29 /* For compatibility */
30 SIM_DESC simulator;
31
32
33
34 /* v850 interrupt model */
35
36 enum interrupt_type
37 {
38   int_reset,
39   int_nmi,
40   int_intov1,
41   int_intp10,
42   int_intp11,
43   int_intp12,
44   int_intp13,
45   int_intcm4,
46   num_int_types
47 };
48
49 char *interrupt_names[] = {
50   "reset",
51   "nmi",
52   "intov1",
53   "intp10",
54   "intp11",
55   "intp12",
56   "intp13",
57   "intcm4",
58   NULL
59 };
60
61 static void
62 do_interrupt (sd, data)
63      SIM_DESC sd;
64      void *data;
65 {
66   enum interrupt_type inttype = *(int*)data;
67   /* Disable further interrupts.  */
68   PSW |= PSW_ID;
69   /* Indicate that we're doing interrupt not exception processing.  */
70   PSW &= ~PSW_EP;
71   if (inttype == int_reset)
72     {
73       PC = 0;
74       PSW = 0x20;
75       ECR = 0;
76       /* (Might be useful to init other regs with random values.) */
77     }
78   else if (inttype == int_nmi)
79     {
80       if (PSW & PSW_NP)
81         {
82           /* We're already working on an NMI, so this one must wait
83              around until the previous one is done.  The processor
84              ignores subsequent NMIs, so we don't need to count them.  */
85           State.pending_nmi = 1;
86         }
87       else
88         {
89           FEPC = PC;
90           FEPSW = PSW;
91           /* Set the FECC part of the ECR. */
92           ECR &= 0x0000ffff;
93           ECR |= 0x10;
94           PSW |= PSW_NP;
95           PC = 0x10;
96         }
97     }
98   else
99     {
100       EIPC = PC;
101       EIPSW = PSW;
102       /* Clear the EICC part of the ECR, will set below. */
103       ECR &= 0xffff0000;
104       switch (inttype)
105         {
106         case int_intov1:
107           PC = 0x80;
108           ECR |= 0x80;
109           break;
110         case int_intp10:
111           PC = 0x90;
112           ECR |= 0x90;
113           break;
114         case int_intp11:
115           PC = 0xa0;
116           ECR |= 0xa0;
117           break;
118         case int_intp12:
119           PC = 0xb0;
120           ECR |= 0xb0;
121           break;
122         case int_intp13:
123           PC = 0xc0;
124           ECR |= 0xc0;
125           break;
126         case int_intcm4:
127           PC = 0xd0;
128           ECR |= 0xd0;
129           break;
130         default:
131           /* Should never be possible.  */
132           abort ();
133           break;
134         }
135     }
136 }
137
138 /* These default values correspond to expected usage for the chip.  */
139
140 int v850_debug;
141
142 uint32 OP[4];
143
144 static long hash PARAMS ((long));
145 #if 0
146 static void do_format_1_2 PARAMS ((uint32));
147 static void do_format_3 PARAMS ((uint32));
148 static void do_format_4 PARAMS ((uint32));
149 static void do_format_5 PARAMS ((uint32));
150 static void do_format_6 PARAMS ((uint32));
151 static void do_format_7 PARAMS ((uint32));
152 static void do_format_8 PARAMS ((uint32));
153 static void do_format_9_10 PARAMS ((uint32));
154 #endif
155
156 #define MAX_HASH  63
157
158 struct hash_entry
159 {
160   struct hash_entry *next;
161   unsigned long opcode;
162   unsigned long mask;
163   struct simops *ops;
164 };
165
166 struct hash_entry hash_table[MAX_HASH+1];
167
168
169 static INLINE long 
170 hash(insn)
171      long insn;
172 {
173   if (   (insn & 0x0600) == 0
174       || (insn & 0x0700) == 0x0200
175       || (insn & 0x0700) == 0x0600
176       || (insn & 0x0780) == 0x0700)
177     return (insn & 0x07e0) >> 5;
178
179   if ((insn & 0x0700) == 0x0300
180       || (insn & 0x0700) == 0x0400
181       || (insn & 0x0700) == 0x0500)
182     return (insn & 0x0780) >> 7;
183
184   if ((insn & 0x07c0) == 0x0780)
185     return (insn & 0x07c0) >> 6;
186
187   return (insn & 0x07e0) >> 5;
188 }
189
190 #if 0
191 static struct hash_entry *
192 lookup_hash (sd, ins)
193      SIM_DESC sd;
194      uint32 ins;
195 {
196   struct hash_entry *h;
197
198   h = &hash_table[hash(ins)];
199
200   while ((ins & h->mask) != h->opcode)
201     {
202       if (h->next == NULL)
203         {
204           sim_io_error (sd, "ERROR looking up hash for 0x%lx, PC=0x%lx",
205                         (long) ins, (long) PC);
206         }
207       h = h->next;
208     }
209   return (h);
210 }
211 #endif
212
213 SIM_DESC
214 sim_open (kind, cb, abfd, argv)
215      SIM_OPEN_KIND kind;
216      host_callback *cb;
217      struct _bfd *abfd;
218      char **argv;
219 {
220   char *buf;
221   SIM_DESC sd = sim_state_alloc (kind, cb);
222 #if 0
223   struct simops *s;
224   struct hash_entry *h;
225 #endif
226
227   /* for compatibility */
228   simulator = sd;
229
230   /* FIXME: should be better way of setting up interrupts */
231   STATE_WATCHPOINTS (sd)->pc = &(PC);
232   STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
233   STATE_WATCHPOINTS (sd)->interrupt_handler = do_interrupt;
234   STATE_WATCHPOINTS (sd)->interrupt_names = interrupt_names;
235
236   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
237     return 0;
238
239   /* Allocate core managed memory */
240   /* "Mirror" the ROM addresses below 1MB. */
241   asprintf (&buf, "memory region 0,0x100000,0x%lx", V850_ROM_SIZE);
242   sim_do_command (sd, buf);
243   free (buf);
244   /* Chunk of ram adjacent to rom */
245   asprintf (&buf, "memory region 0x100000,0x%lx", V850_LOW_END - 0x100000);
246   sim_do_command (sd, buf);
247   free (buf);
248   /* peripheral I/O region - mirror 1K across 4k (0x1000) */
249   sim_do_command (sd, "memory region 0xfff000,0x1000,1024");
250   /* similarly if in the internal RAM region */
251   sim_do_command (sd, "memory region 0xffe000,0x1000,1024");
252
253   /* getopt will print the error message so we just have to exit if this fails.
254      FIXME: Hmmm...  in the case of gdb we need getopt to call
255      print_filtered.  */
256   if (sim_parse_args (sd, argv) != SIM_RC_OK)
257     {
258       /* Uninstall the modules to avoid memory leaks,
259          file descriptor leaks, etc.  */
260       sim_module_uninstall (sd);
261       return 0;
262     }
263
264   /* check for/establish the a reference program image */
265   if (sim_analyze_program (sd,
266                            (STATE_PROG_ARGV (sd) != NULL
267                             ? *STATE_PROG_ARGV (sd)
268                             : NULL),
269                            abfd) != SIM_RC_OK)
270     {
271       sim_module_uninstall (sd);
272       return 0;
273     }
274
275   /* establish any remaining configuration options */
276   if (sim_config (sd) != SIM_RC_OK)
277     {
278       sim_module_uninstall (sd);
279       return 0;
280     }
281
282   if (sim_post_argv_init (sd) != SIM_RC_OK)
283     {
284       /* Uninstall the modules to avoid memory leaks,
285          file descriptor leaks, etc.  */
286       sim_module_uninstall (sd);
287       return 0;
288     }
289
290 #if 0
291   /* put all the opcodes in the hash table */
292   for (s = Simops; s->func; s++)
293     {
294       h = &hash_table[hash(s->opcode)];
295       
296       /* go to the last entry in the chain */
297       while (h->next)
298           h = h->next;
299
300       if (h->ops)
301         {
302           h->next = (struct hash_entry *) calloc(1,sizeof(struct hash_entry));
303           h = h->next;
304         }
305       h->ops = s;
306       h->mask = s->mask;
307       h->opcode = s->opcode;
308     }
309 #endif
310
311   return sd;
312 }
313
314
315 void
316 sim_close (sd, quitting)
317      SIM_DESC sd;
318      int quitting;
319 {
320   sim_module_uninstall (sd);
321 }
322
323 int
324 sim_stop (sd)
325      SIM_DESC sd;
326 {
327   return 0;
328 }
329
330 #if 0
331 void
332 sim_engine_run (sd, next_cpu_nr, siggnal)
333      SIM_DESC sd;
334      int next_cpu_nr;
335      int siggnal;
336 {
337   uint32 inst;
338   SIM_ADDR oldpc;
339
340   while (1)
341     {
342       struct hash_entry * h;
343       /* Fetch the current instruction.  */
344       inst  = RLW (PC);
345       oldpc = PC;
346
347       h     = lookup_hash (sd, inst);
348       OP[0] = inst & 0x1f;
349       OP[1] = (inst >> 11) & 0x1f;
350       OP[2] = (inst >> 16) & 0xffff;
351       OP[3] = inst;
352
353       /* fprintf (stderr, "PC = %x, SP = %x\n", PC, SP ); */
354
355       if (inst == 0)
356         {
357           fprintf (stderr, "NOP encountered!\n");
358           break;
359         }
360       
361       PC += h->ops->func ();
362
363       if (oldpc == PC)
364         {
365           sim_io_eprintf (sd, "simulator loop at %lx\n", (long) PC );
366           break;
367         }
368       
369       if (sim_events_tick (sd))
370         {
371           sim_events_process (sd);
372         }
373     }
374 }
375 #endif
376
377 #if 0
378 int
379 sim_trace (sd)
380      SIM_DESC sd;
381 {
382 #ifdef DEBUG
383   v850_debug = DEBUG;
384 #endif
385   sim_resume (sd, 0, 0);
386   return 1;
387 }
388 #endif
389
390 void
391 sim_info (sd, verbose)
392      SIM_DESC sd;
393      int verbose;
394 {
395   /* do nothing */
396 }
397
398 SIM_RC
399 sim_create_inferior (sd, prog_bfd, argv, env)
400      SIM_DESC sd;
401      struct _bfd *prog_bfd;
402      char **argv;
403      char **env;
404 {
405   memset (&State, 0, sizeof (State));
406   if (prog_bfd != NULL)
407     PC = bfd_get_start_address (prog_bfd);
408   return SIM_RC_OK;
409 }
410
411 void
412 sim_fetch_register (sd, rn, memory)
413      SIM_DESC sd;
414      int rn;
415      unsigned char *memory;
416 {
417   *(unsigned32*)memory = H2T_4 (State.regs[rn]);
418 }
419  
420 void
421 sim_store_register (sd, rn, memory)
422      SIM_DESC sd;
423      int rn;
424      unsigned char *memory;
425 {
426   State.regs[rn] = T2H_4 (*(unsigned32*)memory);
427 }
428
429 void
430 sim_do_command (sd, cmd)
431      SIM_DESC sd;
432      char *cmd;
433 {
434   char *mm_cmd = "memory-map";
435   char *int_cmd = "interrupt";
436
437   if (sim_args_command (sd, cmd) != SIM_RC_OK)
438     {
439       if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0))
440         sim_io_eprintf (sd, "`memory-map' command replaced by `sim memory'\n");
441       else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0)
442         sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n");
443       else
444         sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
445     }
446 }