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