]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/v850/interp.c
35320116a4e65f7eeccebc94346c155a1fb7a05d
[thirdparty/binutils-gdb.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 }