Add _bfd_elf_ifunc_get_synthetic_symtab
[platform/upstream/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
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 const 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   const char **interrupt_name = (const 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           || STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850_rh850))
272     mach = STATE_ARCHITECTURE (sd)->mach;
273   else
274     mach = bfd_mach_v850; /* default */
275
276   /* set machine specific configuration */
277   switch (mach)
278     {
279     case bfd_mach_v850:
280     case bfd_mach_v850e:
281     case bfd_mach_v850e1:
282     case bfd_mach_v850e2:
283     case bfd_mach_v850e2v3:
284     case bfd_mach_v850e3v5:
285       STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT
286                                      | PSW_CY | PSW_OV | PSW_S | PSW_Z);
287       break;
288     }
289
290   return sd;
291 }
292
293
294 void
295 sim_close (sd, quitting)
296      SIM_DESC sd;
297      int quitting;
298 {
299   sim_module_uninstall (sd);
300 }
301
302 SIM_RC
303 sim_create_inferior (sd, prog_bfd, argv, env)
304      SIM_DESC sd;
305      struct bfd *prog_bfd;
306      char **argv;
307      char **env;
308 {
309   memset (&State, 0, sizeof (State));
310   if (prog_bfd != NULL)
311     PC = bfd_get_start_address (prog_bfd);
312   return SIM_RC_OK;
313 }
314
315 int
316 sim_fetch_register (sd, rn, memory, length)
317      SIM_DESC sd;
318      int rn;
319      unsigned char *memory;
320      int length;
321 {
322   *(unsigned32*)memory = H2T_4 (State.regs[rn]);
323   return -1;
324 }
325  
326 int
327 sim_store_register (sd, rn, memory, length)
328      SIM_DESC sd;
329      int rn;
330      unsigned char *memory;
331      int length;
332 {
333   State.regs[rn] = T2H_4 (*(unsigned32*)memory);
334   return length;
335 }