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