* configure: Regenerated to track ../common/aclocal.m4 changes.
[binutils-gdb.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
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 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
192
193 /* for compatibility */
194 simulator = sd;
195
196 /* FIXME: should be better way of setting up interrupts */
197 STATE_WATCHPOINTS (sd)->pc = &(PC);
198 STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
199 STATE_WATCHPOINTS (sd)->interrupt_handler = do_interrupt;
200 STATE_WATCHPOINTS (sd)->interrupt_names = interrupt_names;
201
202 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
203 return 0;
204
205 /* Allocate core managed memory */
206
207 /* "Mirror" the ROM addresses below 1MB. */
208 sim_do_commandf (sd, "memory region 0,0x100000,0x%lx", V850_ROM_SIZE);
209 /* Chunk of ram adjacent to rom */
210 sim_do_commandf (sd, "memory region 0x100000,0x%lx", V850_LOW_END-0x100000);
211 /* peripheral I/O region - mirror 1K across 4k (0x1000) */
212 sim_do_command (sd, "memory region 0xfff000,0x1000,1024");
213 /* similarly if in the internal RAM region */
214 sim_do_command (sd, "memory region 0xffe000,0x1000,1024");
215
216 /* getopt will print the error message so we just have to exit if this fails.
217 FIXME: Hmmm... in the case of gdb we need getopt to call
218 print_filtered. */
219 if (sim_parse_args (sd, argv) != SIM_RC_OK)
220 {
221 /* Uninstall the modules to avoid memory leaks,
222 file descriptor leaks, etc. */
223 sim_module_uninstall (sd);
224 return 0;
225 }
226
227 /* check for/establish the a reference program image */
228 if (sim_analyze_program (sd,
229 (STATE_PROG_ARGV (sd) != NULL
230 ? *STATE_PROG_ARGV (sd)
231 : NULL),
232 abfd) != SIM_RC_OK)
233 {
234 sim_module_uninstall (sd);
235 return 0;
236 }
237
238 /* establish any remaining configuration options */
239 if (sim_config (sd) != SIM_RC_OK)
240 {
241 sim_module_uninstall (sd);
242 return 0;
243 }
244
245 if (sim_post_argv_init (sd) != SIM_RC_OK)
246 {
247 /* Uninstall the modules to avoid memory leaks,
248 file descriptor leaks, etc. */
249 sim_module_uninstall (sd);
250 return 0;
251 }
252
253
254 /* determine the machine type */
255 if (STATE_ARCHITECTURE (sd) != NULL
256 && STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850)
257 mach = STATE_ARCHITECTURE (sd)->mach;
258 else
259 mach = bfd_mach_v850; /* default */
260
261 /* set machine specific configuration */
262 switch (mach)
263 {
264 case bfd_mach_v850:
265 /* start-sanitize-v850e */
266 case bfd_mach_v850e:
267 STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT
268 | PSW_CY | PSW_OV | PSW_S | PSW_Z);
269 break;
270 case bfd_mach_v850ea:
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-v850e */
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 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 /* start-sanitize-v850e */
309 /* For v850ea, set PSW[US] by default */
310 if (STATE_ARCHITECTURE (sd) != NULL
311 && STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850
312 && STATE_ARCHITECTURE (sd)->mach == bfd_mach_v850ea)
313 PSW |= PSW_US;
314 /* end-sanitize-v850e */
315 return SIM_RC_OK;
316 }
317
318 int
319 sim_fetch_register (sd, rn, memory, length)
320 SIM_DESC sd;
321 int rn;
322 unsigned char *memory;
323 int length;
324 {
325 *(unsigned32*)memory = H2T_4 (State.regs[rn]);
326 return -1;
327 }
328
329 int
330 sim_store_register (sd, rn, memory, length)
331 SIM_DESC sd;
332 int rn;
333 unsigned char *memory;
334 int length;
335 {
336 State.regs[rn] = T2H_4 (*(unsigned32*)memory);
337 return -1;
338 }
339
340 void
341 sim_do_command (sd, cmd)
342 SIM_DESC sd;
343 char *cmd;
344 {
345 char *mm_cmd = "memory-map";
346 char *int_cmd = "interrupt";
347
348 if (sim_args_command (sd, cmd) != SIM_RC_OK)
349 {
350 if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0))
351 sim_io_eprintf (sd, "`memory-map' command replaced by `sim memory'\n");
352 else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0)
353 sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n");
354 else
355 sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
356 }
357 }