sim: m68hc11/mips/mn10300/v850: add basic sim_pc_get
[external/binutils.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 /* 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 const char *interrupt_names[] =
50 {
51   "reset",
52   "nmi",
53   "intov1",
54   "intp10",
55   "intp11",
56   "intp12",
57   "intp13",
58   "intcm4",
59   NULL
60 };
61
62 static void
63 do_interrupt (SIM_DESC sd, void *data)
64 {
65   const char **interrupt_name = (const char**)data;
66   enum interrupt_type inttype;
67   inttype = (interrupt_name - STATE_WATCHPOINTS (sd)->interrupt_names);
68
69   /* For a hardware reset, drop everything and jump to the start
70      address */
71   if (inttype == int_reset)
72     {
73       PC = 0;
74       PSW = 0x20;
75       ECR = 0;
76       sim_engine_restart (sd, NULL, NULL, NULL_CIA);
77     }
78
79   /* Deliver an NMI when allowed */
80   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              Just keep re-scheduling a single NMI until it manages to
88              be delivered */
89           if (STATE_CPU (sd, 0)->pending_nmi != NULL)
90             sim_events_deschedule (sd, STATE_CPU (sd, 0)->pending_nmi);
91           STATE_CPU (sd, 0)->pending_nmi =
92             sim_events_schedule (sd, 1, do_interrupt, data);
93           return;
94         }
95       else
96         {
97           /* NMI can be delivered.  Do not deschedule pending_nmi as
98              that, if still in the event queue, is a second NMI that
99              needs to be delivered later. */
100           FEPC = PC;
101           FEPSW = PSW;
102           /* Set the FECC part of the ECR. */
103           ECR &= 0x0000ffff;
104           ECR |= 0x10;
105           PSW |= PSW_NP;
106           PSW &= ~PSW_EP;
107           PSW |= PSW_ID;
108           PC = 0x10;
109           sim_engine_restart (sd, NULL, NULL, NULL_CIA);
110         }
111     }
112
113   /* deliver maskable interrupt when allowed */
114   if (inttype > int_nmi && inttype < num_int_types)
115     {
116       if ((PSW & PSW_NP) || (PSW & PSW_ID))
117         {
118           /* Can't deliver this interrupt, reschedule it for later */
119           sim_events_schedule (sd, 1, do_interrupt, data);
120           return;
121         }
122       else
123         {
124           /* save context */
125           EIPC = PC;
126           EIPSW = PSW;
127           /* Disable further interrupts.  */
128           PSW |= PSW_ID;
129           /* Indicate that we're doing interrupt not exception processing.  */
130           PSW &= ~PSW_EP;
131           /* Clear the EICC part of the ECR, will set below. */
132           ECR &= 0xffff0000;
133           switch (inttype)
134             {
135             case int_intov1:
136               PC = 0x80;
137               ECR |= 0x80;
138               break;
139             case int_intp10:
140               PC = 0x90;
141               ECR |= 0x90;
142               break;
143             case int_intp11:
144               PC = 0xa0;
145               ECR |= 0xa0;
146               break;
147             case int_intp12:
148               PC = 0xb0;
149               ECR |= 0xb0;
150               break;
151             case int_intp13:
152               PC = 0xc0;
153               ECR |= 0xc0;
154               break;
155             case int_intcm4:
156               PC = 0xd0;
157               ECR |= 0xd0;
158               break;
159             default:
160               /* Should never be possible.  */
161               sim_engine_abort (sd, NULL, NULL_CIA,
162                                 "do_interrupt - internal error - bad switch");
163               break;
164             }
165         }
166       sim_engine_restart (sd, NULL, NULL, NULL_CIA);
167     }
168   
169   /* some other interrupt? */
170   sim_engine_abort (sd, NULL, NULL_CIA,
171                     "do_interrupt - internal error - interrupt %d unknown",
172                     inttype);
173 }
174
175 /* Return name of an insn, used by insn profiling.  */
176
177 static const char *
178 get_insn_name (sim_cpu *cpu, int i)
179 {
180   return itable[i].name;
181 }
182
183 /* These default values correspond to expected usage for the chip.  */
184
185 uint32 OP[4];
186
187
188 SIM_DESC
189 sim_open (SIM_OPEN_KIND    kind,
190           host_callback *  cb,
191           struct bfd *     abfd,
192           char **          argv)
193 {
194   SIM_DESC sd = sim_state_alloc (kind, cb);
195   int mach;
196
197   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
198
199   /* for compatibility */
200   simulator = sd;
201
202   /* FIXME: should be better way of setting up interrupts */
203   STATE_WATCHPOINTS (sd)->pc = &(PC);
204   STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
205   STATE_WATCHPOINTS (sd)->interrupt_handler = do_interrupt;
206   STATE_WATCHPOINTS (sd)->interrupt_names = interrupt_names;
207
208   /* Initialize the mechanism for doing insn profiling.  */
209   CPU_INSN_NAME (STATE_CPU (sd, 0)) = get_insn_name;
210   CPU_MAX_INSNS (STATE_CPU (sd, 0)) = nr_itable_entries;
211
212   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
213     return 0;
214
215   /* Allocate core managed memory */
216
217   /* "Mirror" the ROM addresses below 1MB. */
218   sim_do_commandf (sd, "memory region 0,0x100000,0x%lx", V850_ROM_SIZE);
219   /* Chunk of ram adjacent to rom */
220   sim_do_commandf (sd, "memory region 0x100000,0x%lx", V850_LOW_END-0x100000);
221   /* peripheral I/O region - mirror 1K across 4k (0x1000) */
222   sim_do_command (sd, "memory region 0xfff000,0x1000,1024");
223   /* similarly if in the internal RAM region */
224   sim_do_command (sd, "memory region 0xffe000,0x1000,1024");
225
226   /* getopt will print the error message so we just have to exit if this fails.
227      FIXME: Hmmm...  in the case of gdb we need getopt to call
228      print_filtered.  */
229   if (sim_parse_args (sd, argv) != SIM_RC_OK)
230     {
231       /* Uninstall the modules to avoid memory leaks,
232          file descriptor leaks, etc.  */
233       sim_module_uninstall (sd);
234       return 0;
235     }
236
237   /* check for/establish the a reference program image */
238   if (sim_analyze_program (sd,
239                            (STATE_PROG_ARGV (sd) != NULL
240                             ? *STATE_PROG_ARGV (sd)
241                             : NULL),
242                            abfd) != SIM_RC_OK)
243     {
244       sim_module_uninstall (sd);
245       return 0;
246     }
247
248   /* establish any remaining configuration options */
249   if (sim_config (sd) != SIM_RC_OK)
250     {
251       sim_module_uninstall (sd);
252       return 0;
253     }
254
255   if (sim_post_argv_init (sd) != SIM_RC_OK)
256     {
257       /* Uninstall the modules to avoid memory leaks,
258          file descriptor leaks, etc.  */
259       sim_module_uninstall (sd);
260       return 0;
261     }
262
263
264   /* determine the machine type */
265   if (STATE_ARCHITECTURE (sd) != NULL
266       && (STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850
267           || STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850_rh850))
268     mach = STATE_ARCHITECTURE (sd)->mach;
269   else
270     mach = bfd_mach_v850; /* default */
271
272   /* set machine specific configuration */
273   switch (mach)
274     {
275     case bfd_mach_v850:
276     case bfd_mach_v850e:
277     case bfd_mach_v850e1:
278     case bfd_mach_v850e2:
279     case bfd_mach_v850e2v3:
280     case bfd_mach_v850e3v5:
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 (SIM_DESC sd, int quitting)
292 {
293   sim_module_uninstall (sd);
294 }
295
296 SIM_RC
297 sim_create_inferior (SIM_DESC      sd,
298                      struct bfd *  prog_bfd,
299                      char **       argv,
300                      char **       env)
301 {
302   memset (&State, 0, sizeof (State));
303   if (prog_bfd != NULL)
304     PC = bfd_get_start_address (prog_bfd);
305   return SIM_RC_OK;
306 }
307
308 int
309 sim_fetch_register (SIM_DESC         sd,
310                     int              rn,
311                     unsigned char *  memory,
312                     int              length)
313 {
314   *(unsigned32*)memory = H2T_4 (State.regs[rn]);
315   return -1;
316 }
317  
318 int
319 sim_store_register (SIM_DESC        sd,
320                     int             rn,
321                     unsigned char * memory,
322                     int             length)
323 {
324   State.regs[rn] = T2H_4 (*(unsigned32 *) memory);
325   return length;
326 }
327
328 sim_cia
329 sim_pc_get (sim_cpu *cpu)
330 {
331   return PC;
332 }