OSDN Git Service

* configure: Regenerate to track ../common/common.m4 changes.
[pf3gnuchains/sourceware.git] / sim / v850 / interp.c
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
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 *
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
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
291 sim_close (sd, quitting)
292      SIM_DESC sd;
293      int quitting;
294 {
295   sim_module_uninstall (sd);
296 }
297
298 SIM_RC
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
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
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
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 }