Add profiling support to v850*.
[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 #if 0
224 struct simops *s;
225 struct hash_entry *h;
226 #endif
227
228 /* for compatibility */
229 simulator = sd;
230
231 /* FIXME: should be better way of setting up interrupts */
232 STATE_WATCHPOINTS (sd)->pc = &(PC);
233 STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
234 STATE_WATCHPOINTS (sd)->interrupt_handler = do_interrupt;
235 STATE_WATCHPOINTS (sd)->interrupt_names = interrupt_names;
236
237 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
238 return 0;
239
240 /* Allocate core managed memory */
241
242 /* "Mirror" the ROM addresses below 1MB. */
243 sim_do_commandf (sd, "memory region 0,0x100000,0x%lx", V850_ROM_SIZE);
244 /* Chunk of ram adjacent to rom */
245 sim_do_commandf (sd, "memory region 0x100000,0x%lx", V850_LOW_END-0x100000);
246 /* peripheral I/O region - mirror 1K across 4k (0x1000) */
247 sim_do_command (sd, "memory region 0xfff000,0x1000,1024");
248 /* similarly if in the internal RAM region */
249 sim_do_command (sd, "memory region 0xffe000,0x1000,1024");
250
251 /* getopt will print the error message so we just have to exit if this fails.
252 FIXME: Hmmm... in the case of gdb we need getopt to call
253 print_filtered. */
254 if (sim_parse_args (sd, argv) != SIM_RC_OK)
255 {
256 /* Uninstall the modules to avoid memory leaks,
257 file descriptor leaks, etc. */
258 sim_module_uninstall (sd);
259 return 0;
260 }
261
262 /* check for/establish the a reference program image */
263 if (sim_analyze_program (sd,
264 (STATE_PROG_ARGV (sd) != NULL
265 ? *STATE_PROG_ARGV (sd)
266 : NULL),
267 abfd) != SIM_RC_OK)
268 {
269 sim_module_uninstall (sd);
270 return 0;
271 }
272
273 /* establish any remaining configuration options */
274 if (sim_config (sd) != SIM_RC_OK)
275 {
276 sim_module_uninstall (sd);
277 return 0;
278 }
279
280 if (sim_post_argv_init (sd) != SIM_RC_OK)
281 {
282 /* Uninstall the modules to avoid memory leaks,
283 file descriptor leaks, etc. */
284 sim_module_uninstall (sd);
285 return 0;
286 }
287
288 #if 0
289 /* put all the opcodes in the hash table */
290 for (s = Simops; s->func; s++)
291 {
292 h = &hash_table[hash(s->opcode)];
293
294 /* go to the last entry in the chain */
295 while (h->next)
296 h = h->next;
297
298 if (h->ops)
299 {
300 h->next = (struct hash_entry *) calloc(1,sizeof(struct hash_entry));
301 h = h->next;
302 }
303 h->ops = s;
304 h->mask = s->mask;
305 h->opcode = s->opcode;
306 }
307 #endif
308
309 return sd;
310 }
311
312
313 void
314 sim_close (sd, quitting)
315 SIM_DESC sd;
316 int quitting;
317 {
318 sim_module_uninstall (sd);
319 }
320
321 int
322 sim_stop (sd)
323 SIM_DESC sd;
324 {
325 return 0;
326 }
327
328 #if 0
329 void
330 sim_engine_run (sd, next_cpu_nr, siggnal)
331 SIM_DESC sd;
332 int next_cpu_nr;
333 int siggnal;
334 {
335 uint32 inst;
336 SIM_ADDR oldpc;
337
338 while (1)
339 {
340 struct hash_entry * h;
341 /* Fetch the current instruction. */
342 inst = RLW (PC);
343 oldpc = PC;
344
345 h = lookup_hash (sd, inst);
346 OP[0] = inst & 0x1f;
347 OP[1] = (inst >> 11) & 0x1f;
348 OP[2] = (inst >> 16) & 0xffff;
349 OP[3] = inst;
350
351 /* fprintf (stderr, "PC = %x, SP = %x\n", PC, SP ); */
352
353 if (inst == 0)
354 {
355 fprintf (stderr, "NOP encountered!\n");
356 break;
357 }
358
359 PC += h->ops->func ();
360
361 if (oldpc == PC)
362 {
363 sim_io_eprintf (sd, "simulator loop at %lx\n", (long) PC );
364 break;
365 }
366
367 if (sim_events_tick (sd))
368 {
369 sim_events_process (sd);
370 }
371 }
372 }
373 #endif
374
375 #if 0
376 int
377 sim_trace (sd)
378 SIM_DESC sd;
379 {
380 #ifdef DEBUG
381 v850_debug = DEBUG;
382 #endif
383 sim_resume (sd, 0, 0);
384 return 1;
385 }
386 #endif
387
388 void
389 sim_info (sd, verbose)
390 SIM_DESC sd;
391 int verbose;
392 {
393 profile_print (sd, STATE_VERBOSE_P (sd), NULL, NULL);
394 }
395
396 SIM_RC
397 sim_create_inferior (sd, prog_bfd, argv, env)
398 SIM_DESC sd;
399 struct _bfd *prog_bfd;
400 char **argv;
401 char **env;
402 {
403 memset (&State, 0, sizeof (State));
404 if (prog_bfd != NULL)
405 PC = bfd_get_start_address (prog_bfd);
406 return SIM_RC_OK;
407 }
408
409 void
410 sim_fetch_register (sd, rn, memory)
411 SIM_DESC sd;
412 int rn;
413 unsigned char *memory;
414 {
415 *(unsigned32*)memory = H2T_4 (State.regs[rn]);
416 }
417
418 void
419 sim_store_register (sd, rn, memory)
420 SIM_DESC sd;
421 int rn;
422 unsigned char *memory;
423 {
424 State.regs[rn] = T2H_4 (*(unsigned32*)memory);
425 }
426
427 void
428 sim_do_command (sd, cmd)
429 SIM_DESC sd;
430 char *cmd;
431 {
432 char *mm_cmd = "memory-map";
433 char *int_cmd = "interrupt";
434
435 if (sim_args_command (sd, cmd) != SIM_RC_OK)
436 {
437 if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0))
438 sim_io_eprintf (sd, "`memory-map' command replaced by `sim memory'\n");
439 else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0)
440 sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n");
441 else
442 sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
443 }
444 }