]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/v850/interp.c
Initial creation of sourceware repository
[thirdparty/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 #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 STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT
281 | PSW_CY | PSW_OV | PSW_S | PSW_Z);
282 break;
283 case bfd_mach_v850ea:
284 PSW |= PSW_US;
285 STATE_CPU (sd, 0)->psw_mask = (PSW_US
286 | PSW_NP | PSW_EP | PSW_ID | PSW_SAT
287 | PSW_CY | PSW_OV | PSW_S | PSW_Z);
288 break;
289 }
290
291 return sd;
292 }
293
294
295 void
296 sim_close (sd, quitting)
297 SIM_DESC sd;
298 int quitting;
299 {
300 sim_module_uninstall (sd);
301 }
302
303 SIM_RC
304 sim_create_inferior (sd, prog_bfd, argv, env)
305 SIM_DESC sd;
306 struct _bfd *prog_bfd;
307 char **argv;
308 char **env;
309 {
310 memset (&State, 0, sizeof (State));
311 if (prog_bfd != NULL)
312 PC = bfd_get_start_address (prog_bfd);
313 /* For v850ea, set PSW[US] by default */
314 if (STATE_ARCHITECTURE (sd) != NULL
315 && STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850
316 && STATE_ARCHITECTURE (sd)->mach == bfd_mach_v850ea)
317 PSW |= PSW_US;
318 return SIM_RC_OK;
319 }
320
321 int
322 sim_fetch_register (sd, rn, memory, length)
323 SIM_DESC sd;
324 int rn;
325 unsigned char *memory;
326 int length;
327 {
328 *(unsigned32*)memory = H2T_4 (State.regs[rn]);
329 return -1;
330 }
331
332 int
333 sim_store_register (sd, rn, memory, length)
334 SIM_DESC sd;
335 int rn;
336 unsigned char *memory;
337 int length;
338 {
339 State.regs[rn] = T2H_4 (*(unsigned32*)memory);
340 return -1;
341 }
342
343 void
344 sim_do_command (sd, cmd)
345 SIM_DESC sd;
346 char *cmd;
347 {
348 char *mm_cmd = "memory-map";
349 char *int_cmd = "interrupt";
350
351 if (sim_args_command (sd, cmd) != SIM_RC_OK)
352 {
353 if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0))
354 sim_io_eprintf (sd, "`memory-map' command replaced by `sim memory'\n");
355 else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0)
356 sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n");
357 else
358 sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
359 }
360 }