Restrict ldsr (load system register) to modifying just non-reserved PSW bits.
[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 /* Disable further interrupts. */
70 PSW |= PSW_ID;
71 /* Indicate that we're doing interrupt not exception processing. */
72 PSW &= ~PSW_EP;
73 if (inttype == int_reset)
74 {
75 PC = 0;
76 PSW = 0x20;
77 ECR = 0;
78 /* (Might be useful to init other regs with random values.) */
79 }
80 else 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 State.pending_nmi = 1;
88 }
89 else
90 {
91 FEPC = PC;
92 FEPSW = PSW;
93 /* Set the FECC part of the ECR. */
94 ECR &= 0x0000ffff;
95 ECR |= 0x10;
96 PSW |= PSW_NP;
97 PC = 0x10;
98 }
99 }
100 else
101 {
102 EIPC = PC;
103 EIPSW = PSW;
104 /* Clear the EICC part of the ECR, will set below. */
105 ECR &= 0xffff0000;
106 switch (inttype)
107 {
108 case int_intov1:
109 PC = 0x80;
110 ECR |= 0x80;
111 break;
112 case int_intp10:
113 PC = 0x90;
114 ECR |= 0x90;
115 break;
116 case int_intp11:
117 PC = 0xa0;
118 ECR |= 0xa0;
119 break;
120 case int_intp12:
121 PC = 0xb0;
122 ECR |= 0xb0;
123 break;
124 case int_intp13:
125 PC = 0xc0;
126 ECR |= 0xc0;
127 break;
128 case int_intcm4:
129 PC = 0xd0;
130 ECR |= 0xd0;
131 break;
132 default:
133 /* Should never be possible. */
134 abort ();
135 break;
136 }
137 }
138 }
139
140 /* These default values correspond to expected usage for the chip. */
141
142 int v850_debug;
143
144 uint32 OP[4];
145
146 static long hash PARAMS ((long));
147 #if 0
148 static void do_format_1_2 PARAMS ((uint32));
149 static void do_format_3 PARAMS ((uint32));
150 static void do_format_4 PARAMS ((uint32));
151 static void do_format_5 PARAMS ((uint32));
152 static void do_format_6 PARAMS ((uint32));
153 static void do_format_7 PARAMS ((uint32));
154 static void do_format_8 PARAMS ((uint32));
155 static void do_format_9_10 PARAMS ((uint32));
156 #endif
157
158 #define MAX_HASH 63
159
160 struct hash_entry
161 {
162 struct hash_entry *next;
163 unsigned long opcode;
164 unsigned long mask;
165 struct simops *ops;
166 };
167
168 struct hash_entry hash_table[MAX_HASH+1];
169
170
171 static INLINE long
172 hash(insn)
173 long insn;
174 {
175 if ( (insn & 0x0600) == 0
176 || (insn & 0x0700) == 0x0200
177 || (insn & 0x0700) == 0x0600
178 || (insn & 0x0780) == 0x0700)
179 return (insn & 0x07e0) >> 5;
180
181 if ((insn & 0x0700) == 0x0300
182 || (insn & 0x0700) == 0x0400
183 || (insn & 0x0700) == 0x0500)
184 return (insn & 0x0780) >> 7;
185
186 if ((insn & 0x07c0) == 0x0780)
187 return (insn & 0x07c0) >> 6;
188
189 return (insn & 0x07e0) >> 5;
190 }
191
192 #if 0
193 static struct hash_entry *
194 lookup_hash (sd, ins)
195 SIM_DESC sd;
196 uint32 ins;
197 {
198 struct hash_entry *h;
199
200 h = &hash_table[hash(ins)];
201
202 while ((ins & h->mask) != h->opcode)
203 {
204 if (h->next == NULL)
205 {
206 sim_io_error (sd, "ERROR looking up hash for 0x%lx, PC=0x%lx",
207 (long) ins, (long) PC);
208 }
209 h = h->next;
210 }
211 return (h);
212 }
213 #endif
214
215 SIM_DESC
216 sim_open (kind, cb, abfd, argv)
217 SIM_OPEN_KIND kind;
218 host_callback *cb;
219 struct _bfd *abfd;
220 char **argv;
221 {
222 SIM_DESC sd = sim_state_alloc (kind, cb);
223 int mach;
224
225 /* for compatibility */
226 simulator = sd;
227
228 /* FIXME: should be better way of setting up interrupts */
229 STATE_WATCHPOINTS (sd)->pc = &(PC);
230 STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
231 STATE_WATCHPOINTS (sd)->interrupt_handler = do_interrupt;
232 STATE_WATCHPOINTS (sd)->interrupt_names = interrupt_names;
233
234 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
235 return 0;
236
237 /* Allocate core managed memory */
238
239 /* "Mirror" the ROM addresses below 1MB. */
240 sim_do_commandf (sd, "memory region 0,0x100000,0x%lx", V850_ROM_SIZE);
241 /* Chunk of ram adjacent to rom */
242 sim_do_commandf (sd, "memory region 0x100000,0x%lx", V850_LOW_END-0x100000);
243 /* peripheral I/O region - mirror 1K across 4k (0x1000) */
244 sim_do_command (sd, "memory region 0xfff000,0x1000,1024");
245 /* similarly if in the internal RAM region */
246 sim_do_command (sd, "memory region 0xffe000,0x1000,1024");
247
248 /* getopt will print the error message so we just have to exit if this fails.
249 FIXME: Hmmm... in the case of gdb we need getopt to call
250 print_filtered. */
251 if (sim_parse_args (sd, argv) != SIM_RC_OK)
252 {
253 /* Uninstall the modules to avoid memory leaks,
254 file descriptor leaks, etc. */
255 sim_module_uninstall (sd);
256 return 0;
257 }
258
259 /* check for/establish the a reference program image */
260 if (sim_analyze_program (sd,
261 (STATE_PROG_ARGV (sd) != NULL
262 ? *STATE_PROG_ARGV (sd)
263 : NULL),
264 abfd) != SIM_RC_OK)
265 {
266 sim_module_uninstall (sd);
267 return 0;
268 }
269
270 /* establish any remaining configuration options */
271 if (sim_config (sd) != SIM_RC_OK)
272 {
273 sim_module_uninstall (sd);
274 return 0;
275 }
276
277 if (sim_post_argv_init (sd) != SIM_RC_OK)
278 {
279 /* Uninstall the modules to avoid memory leaks,
280 file descriptor leaks, etc. */
281 sim_module_uninstall (sd);
282 return 0;
283 }
284
285
286 /* determine the machine type */
287 if (STATE_ARCHITECTURE (sd) != NULL
288 && STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850)
289 mach = STATE_ARCHITECTURE (sd)->mach;
290 else
291 mach = bfd_mach_v850; /* default */
292
293 /* set machine specific configuration */
294 switch (mach)
295 {
296 case bfd_mach_v850:
297 /* start-sanitize-v850e */
298 case bfd_mach_v850e:
299 /* end-sanitize-v850e */
300 STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT
301 | PSW_CY | PSW_OV | PSW_S | PSW_Z);
302 break;
303 /* start-sanitize-v850eq */
304 case bfd_mach_v850eq:
305 PSW |= PSW_US;
306 STATE_CPU (sd, 0)->psw_mask = (PSW_US
307 | PSW_NP | PSW_EP | PSW_ID | PSW_SAT
308 | PSW_CY | PSW_OV | PSW_S | PSW_Z);
309 break;
310 /* end-sanitize-v850eq */
311 }
312
313 return sd;
314 }
315
316
317 void
318 sim_close (sd, quitting)
319 SIM_DESC sd;
320 int quitting;
321 {
322 sim_module_uninstall (sd);
323 }
324
325 int
326 sim_stop (sd)
327 SIM_DESC sd;
328 {
329 return 0;
330 }
331
332 #if 0
333 void
334 sim_engine_run (sd, next_cpu_nr, siggnal)
335 SIM_DESC sd;
336 int next_cpu_nr;
337 int siggnal;
338 {
339 uint32 inst;
340 SIM_ADDR oldpc;
341
342 while (1)
343 {
344 struct hash_entry * h;
345 /* Fetch the current instruction. */
346 inst = RLW (PC);
347 oldpc = PC;
348
349 h = lookup_hash (sd, inst);
350 OP[0] = inst & 0x1f;
351 OP[1] = (inst >> 11) & 0x1f;
352 OP[2] = (inst >> 16) & 0xffff;
353 OP[3] = inst;
354
355 /* fprintf (stderr, "PC = %x, SP = %x\n", PC, SP ); */
356
357 if (inst == 0)
358 {
359 fprintf (stderr, "NOP encountered!\n");
360 break;
361 }
362
363 PC += h->ops->func ();
364
365 if (oldpc == PC)
366 {
367 sim_io_eprintf (sd, "simulator loop at %lx\n", (long) PC );
368 break;
369 }
370
371 if (sim_events_tick (sd))
372 {
373 sim_events_process (sd);
374 }
375 }
376 }
377 #endif
378
379 #if 0
380 int
381 sim_trace (sd)
382 SIM_DESC sd;
383 {
384 #ifdef DEBUG
385 v850_debug = DEBUG;
386 #endif
387 sim_resume (sd, 0, 0);
388 return 1;
389 }
390 #endif
391
392 void
393 sim_info (sd, verbose)
394 SIM_DESC sd;
395 int verbose;
396 {
397 profile_print (sd, STATE_VERBOSE_P (sd), NULL, NULL);
398 }
399
400 SIM_RC
401 sim_create_inferior (sd, prog_bfd, argv, env)
402 SIM_DESC sd;
403 struct _bfd *prog_bfd;
404 char **argv;
405 char **env;
406 {
407 memset (&State, 0, sizeof (State));
408 if (prog_bfd != NULL)
409 PC = bfd_get_start_address (prog_bfd);
410 /* start-sanitize-v850eq */
411 /* For v850eq, set PSW[US] by default */
412 if (STATE_ARCHITECTURE (sd) != NULL
413 && STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850
414 && STATE_ARCHITECTURE (sd)->mach == bfd_mach_v850eq)
415 PSW |= PSW_US;
416 /* end-sanitize-v850eq */
417 return SIM_RC_OK;
418 }
419
420 void
421 sim_fetch_register (sd, rn, memory)
422 SIM_DESC sd;
423 int rn;
424 unsigned char *memory;
425 {
426 *(unsigned32*)memory = H2T_4 (State.regs[rn]);
427 }
428
429 void
430 sim_store_register (sd, rn, memory)
431 SIM_DESC sd;
432 int rn;
433 unsigned char *memory;
434 {
435 State.regs[rn] = T2H_4 (*(unsigned32*)memory);
436 }
437
438 void
439 sim_do_command (sd, cmd)
440 SIM_DESC sd;
441 char *cmd;
442 {
443 char *mm_cmd = "memory-map";
444 char *int_cmd = "interrupt";
445
446 if (sim_args_command (sd, cmd) != SIM_RC_OK)
447 {
448 if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0))
449 sim_io_eprintf (sd, "`memory-map' command replaced by `sim memory'\n");
450 else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0)
451 sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n");
452 else
453 sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
454 }
455 }