21 enum interrupt_cond_type
28 struct interrupt_generator
30 enum interrupt_type type
;
31 enum interrupt_cond_type cond_type
;
36 struct interrupt_generator
*next
;
39 char *interrupt_names
[] = {
52 struct interrupt_generator
*intgen_list
;
54 /* True if a non-maskable (such as NMI or reset) interrupt generator
57 static int have_nm_generator
;
67 /* These default values correspond to expected usage for the chip. */
69 SIM_ADDR rom_size
= 0x8000;
70 SIM_ADDR low_end
= 0x200000;
71 SIM_ADDR high_start
= 0xffe000;
75 host_callback
*v850_callback
;
79 static SIM_OPEN_KIND sim_kind
;
84 static struct hash_entry
*lookup_hash
PARAMS ((uint32 ins
));
85 static long hash
PARAMS ((long));
86 static void do_format_1_2
PARAMS ((uint32
));
87 static void do_format_3
PARAMS ((uint32
));
88 static void do_format_4
PARAMS ((uint32
));
89 static void do_format_5
PARAMS ((uint32
));
90 static void do_format_6
PARAMS ((uint32
));
91 static void do_format_7
PARAMS ((uint32
));
92 static void do_format_8
PARAMS ((uint32
));
93 static void do_format_9_10
PARAMS ((uint32
));
94 static void init_system
PARAMS ((void));
100 struct hash_entry
*next
;
106 struct hash_entry hash_table
[MAX_HASH
+1];
113 if ((insn
& 0x0600) == 0
114 || (insn
& 0x0700) == 0x0200
115 || (insn
& 0x0700) == 0x0600
116 || (insn
& 0x0780) == 0x0700)
117 return (insn
& 0x07e0) >> 5;
119 if ((insn
& 0x0700) == 0x0300
120 || (insn
& 0x0700) == 0x0400
121 || (insn
& 0x0700) == 0x0500)
122 return (insn
& 0x0780) >> 7;
124 if ((insn
& 0x07c0) == 0x0780)
125 return (insn
& 0x07c0) >> 6;
127 return (insn
& 0x07e0) >> 5;
130 static struct hash_entry
*
134 struct hash_entry
*h
;
136 h
= &hash_table
[hash(ins
)];
138 while ((ins
& h
->mask
) != h
->opcode
)
142 (*v850_callback
->printf_filtered
) (v850_callback
, "ERROR looking up hash for 0x%x, PC=0x%x\n", ins
, PC
);
150 /* FIXME These would more efficient to use than load_mem/store_mem,
151 but need to be changed to use the memory map. */
165 return (a
[1] << 8) + (a
[0]);
173 return (a
[3]<<24) + (a
[2]<<16) + (a
[1]<<8) + (a
[0]);
177 put_byte (addr
, data
)
186 put_half (addr
, data
)
192 a
[1] = (data
>> 8) & 0xff;
196 put_word (addr
, data
)
202 a
[1] = (data
>> 8) & 0xff;
203 a
[2] = (data
>> 16) & 0xff;
204 a
[3] = (data
>> 24) & 0xff;
213 /* Mask down to 24 bits. */
218 /* "Mirror" the addresses below 1MB. */
220 addr
&= (rom_size
- 1);
222 addr
+= (rom_size
- 0x100000);
223 return (uint8
*) (addr
+ State
.mem
);
225 else if (addr
>= high_start
)
227 /* If in the peripheral I/O region, mirror 1K region across 4K,
228 and similarly if in the internal RAM region. */
229 if (addr
>= 0xfff000)
231 else if (addr
>= 0xffe000)
233 return (uint8
*) (addr
- high_start
+ high_base
+ State
.mem
);
237 /* Signal a memory error. */
238 State
.exception
= SIGSEGV
;
239 /* Point to a location not in main memory - renders invalid
240 addresses harmless until we get back to main insn loop. */
241 return (uint8
*) &(State
.dummy_mem
);
250 uint8
*p
= map (addr
);
257 return p
[1] << 8 | p
[0];
259 return p
[3] << 24 | p
[2] << 16 | p
[1] << 8 | p
[0];
266 store_mem (addr
, len
, data
)
271 uint8
*p
= map (addr
);
297 struct hash_entry
*h
;
299 h
= lookup_hash (insn
);
301 OP
[1] = (insn
>> 11) & 0x1f;
309 struct hash_entry
*h
;
311 h
= lookup_hash (insn
);
312 OP
[0] = (((insn
& 0x70) >> 4) | ((insn
& 0xf800) >> 8)) << 1;
320 struct hash_entry
*h
;
322 h
= lookup_hash (insn
);
323 OP
[0] = (insn
>> 11) & 0x1f;
324 OP
[1] = (insn
& 0x7f);
332 struct hash_entry
*h
;
334 h
= lookup_hash (insn
);
335 OP
[0] = (((insn
& 0x3f) << 15) | ((insn
>> 17) & 0x7fff)) << 1;
336 OP
[1] = (insn
>> 11) & 0x1f;
344 struct hash_entry
*h
;
346 h
= lookup_hash (insn
);
347 OP
[0] = (insn
>> 16) & 0xffff;
349 OP
[2] = (insn
>> 11) & 0x1f;
357 struct hash_entry
*h
;
359 h
= lookup_hash (insn
);
361 OP
[1] = (insn
>> 11) & 0x1f;
362 OP
[2] = (insn
>> 16) & 0xffff;
370 struct hash_entry
*h
;
372 h
= lookup_hash (insn
);
374 OP
[1] = (insn
>> 11) & 0x7;
375 OP
[2] = (insn
>> 16) & 0xffff;
380 do_format_9_10 (insn
)
383 struct hash_entry
*h
;
385 h
= lookup_hash (insn
);
387 OP
[1] = (insn
>> 11) & 0x1f;
401 totsize
= rom_size
+ (low_end
- 0x100000) + (0x1000000 - high_start
);
403 high_base
= rom_size
+ (low_end
- 0x100000);
405 State
.mem
= (uint8
*) calloc (1, totsize
);
408 (*v850_callback
->printf_filtered
) (v850_callback
, "Allocation of main memory failed.\n");
414 sim_set_memory_map (spec
)
417 char *reststr
, *nreststr
;
418 SIM_ADDR new_low_end
, new_high_start
;
420 new_low_end
= low_end
;
421 new_high_start
= high_start
;
422 if (! strncmp (spec
, "hole=", 5))
424 new_low_end
= sim_parse_number (spec
+ 5, &reststr
);
425 if (new_low_end
< 0x100000)
427 (*v850_callback
->printf_filtered
) (v850_callback
,
428 "Low end must be at least 0x100000\n");
434 new_high_start
= sim_parse_number (reststr
, &nreststr
);
435 /* FIXME Check high_start also */
437 (*v850_callback
->printf_filtered
) (v850_callback
,
438 "Hole goes from 0x%x to 0x%x\n",
439 new_low_end
, new_high_start
);
443 (*v850_callback
->printf_filtered
) (v850_callback
, "Invalid specification for memory map, must be `hole=<m>[,<n>]'\n");
446 if (new_low_end
!= low_end
|| new_high_start
!= high_start
)
448 low_end
= new_low_end
;
449 high_start
= new_high_start
;
452 (*v850_callback
->printf_filtered
) (v850_callback
, "Reconfiguring memory (old contents will be lost)\n");
458 /* Parse a number in hex, octal, or decimal form. */
461 sim_parse_number (str
, rest
)
464 if (str
[0] == '0' && str
[1] == 'x')
465 return strtol (str
, rest
, 16);
466 else if (str
[0] == '0')
467 return strtol (str
, rest
, 16);
469 return strtol (str
, rest
, 10);
480 sim_write (sd
, addr
, buffer
, size
)
483 unsigned char *buffer
;
490 for (i
= 0; i
< size
; i
++)
491 store_mem (addr
+ i
, 1, buffer
[i
]);
502 struct hash_entry
*h
;
508 for (p
= argv
+ 1; *p
; ++p
)
510 if (strcmp (*p
, "-E") == 0)
511 ++p
; /* ignore endian spec */
514 if (strcmp (*p
, "-t") == 0)
518 (*v850_callback
->printf_filtered
) (v850_callback
, "ERROR: unsupported option(s): %s\n",*p
);
521 /* put all the opcodes in the hash table */
522 for (s
= Simops
; s
->func
; s
++)
524 h
= &hash_table
[hash(s
->opcode
)];
526 /* go to the last entry in the chain */
532 h
->next
= (struct hash_entry
*) calloc(1,sizeof(struct hash_entry
));
537 h
->opcode
= s
->opcode
;
540 /* fudge our descriptor for now */
546 sim_close (sd
, quitting
)
557 (*v850_callback
->printf_filtered
) (v850_callback
, "sim_set_profile %d\n", n
);
561 sim_set_profile_size (n
)
564 (*v850_callback
->printf_filtered
) (v850_callback
, "sim_set_profile_size %d\n", n
);
569 static void do_interrupt
PARAMS ((enum interrupt_type
));
572 sim_resume (sd
, step
, siggnal
)
578 struct interrupt_generator
*intgen
;
582 State
.exception
= SIGTRAP
;
590 /* Fetch the current instruction. */
593 opcode
= (inst
& 0x07e0) >> 5;
595 /* Decode the opcode field. */
596 if ((opcode
& 0x30) == 0
597 || (opcode
& 0x38) == 0x10)
599 do_format_1_2 (inst
& 0xffff);
602 else if ((opcode
& 0x3C) == 0x18
603 || (opcode
& 0x3C) == 0x1C
604 || (opcode
& 0x3C) == 0x20
605 || (opcode
& 0x3C) == 0x24
606 || (opcode
& 0x3C) == 0x28)
608 do_format_4 (inst
& 0xffff);
611 else if ((opcode
& 0x3C) == 0x2C)
613 do_format_3 (inst
& 0xffff);
614 /* No PC update, it's done in the instruction. */
616 else if ((opcode
& 0x38) == 0x30)
621 else if ((opcode
& 0x3C) == 0x38)
626 else if ((opcode
& 0x3E) == 0x3C)
629 /* No PC update, it's done in the instruction. */
631 else if ((opcode
& 0x3F) == 0x3E)
638 do_format_9_10 (inst
);
642 /* Check for and handle pending interrupts. */
643 if (intgen_list
&& (have_nm_generator
|| !(PSW
& PSW_ID
)))
646 for (intgen
= intgen_list
; intgen
!= NULL
; intgen
= intgen
->next
)
648 if (intgen
->cond_type
== int_cond_pc
649 && oldpc
== intgen
->address
654 else if (intgen
->cond_type
== int_cond_time
658 if (((long) now
- (long) start_time
) > intgen
->time
)
666 do_interrupt (intgen
->type
);
668 else if (State
.pending_nmi
)
670 State
.pending_nmi
= 0;
671 do_interrupt (int_nmi
);
674 while (!State
.exception
);
678 do_interrupt (inttype
)
679 enum interrupt_type inttype
;
681 /* Disable further interrupts. */
683 /* Indicate that we're doing interrupt not exception processing. */
685 if (inttype
== int_reset
)
690 /* (Might be useful to init other regs with random values.) */
692 else if (inttype
== int_nmi
)
696 /* We're already working on an NMI, so this one must wait
697 around until the previous one is done. The processor
698 ignores subsequent NMIs, so we don't need to count them. */
699 State
.pending_nmi
= 1;
705 /* Set the FECC part of the ECR. */
716 /* Clear the EICC part of the ECR, will set below. */
745 /* Should never be possible. */
759 sim_resume (sd
, 0, 0);
764 sim_info (sd
, verbose
)
768 (*v850_callback
->printf_filtered
) (v850_callback
, "sim_info\n");
772 sim_create_inferior (sd
, argv
, env
)
788 sim_set_callbacks (sd
, p
)
795 /* All the code for exiting, signals, etc needs to be revamped.
797 This is enough to get c-torture limping though. */
800 sim_stop_reason (sd
, reason
, sigrc
)
802 enum sim_stop
*reason
;
805 if (State
.exception
== SIG_V850_EXIT
)
807 *reason
= sim_exited
;
808 *sigrc
= State
.regs
[7];
812 *reason
= sim_stopped
;
813 *sigrc
= State
.exception
;
818 sim_fetch_register (sd
, rn
, memory
)
821 unsigned char *memory
;
823 put_word (memory
, State
.regs
[rn
]);
827 sim_store_register (sd
, rn
, memory
)
830 unsigned char *memory
;
832 State
.regs
[rn
] = get_word (memory
);
836 sim_read (sd
, addr
, buffer
, size
)
839 unsigned char *buffer
;
843 for (i
= 0; i
< size
; i
++)
844 buffer
[i
] = load_mem (addr
+ i
, 1);
849 int current_intgen_number
= 1;
852 sim_set_interrupt (spec
)
857 struct interrupt_generator
*intgen
, *tmpgen
;
858 extern char **buildargv ();
860 argv
= buildargv (spec
);
862 if (*argv
&& ! strcmp (*argv
, "add"))
864 /* Create a new interrupt generator object. */
865 intgen
= (struct interrupt_generator
*)
866 malloc (sizeof(struct interrupt_generator
));
867 intgen
->type
= int_none
;
868 intgen
->cond_type
= int_cond_none
;
873 /* Match on interrupt type name. */
874 for (i
= 0; i
< num_int_types
; ++i
)
876 if (*argv
&& ! strcmp (*argv
, interrupt_names
[i
]))
882 if (intgen
->type
== int_none
)
884 (*v850_callback
->printf_filtered
) (v850_callback
, "Interrupt type unknown; known types are\n");
885 for (i
= 0; i
< num_int_types
; ++i
)
887 (*v850_callback
->printf_filtered
) (v850_callback
, " %s", interrupt_names
[i
]);
889 (*v850_callback
->printf_filtered
) (v850_callback
, "\n");
896 if (*argv
&& ! strcmp (*argv
, "pc"))
898 intgen
->cond_type
= int_cond_pc
;
900 intgen
->address
= sim_parse_number (*argv
, NULL
);
902 else if (*argv
&& ! strcmp (*argv
, "time"))
904 intgen
->cond_type
= int_cond_time
;
906 intgen
->time
= sim_parse_number (*argv
, NULL
);
910 (*v850_callback
->printf_filtered
) (v850_callback
, "Condition type must be `pc' or `time'.\n");
914 /* We now have a valid interrupt generator. Number it and add
915 to the list of generators. */
916 intgen
->number
= current_intgen_number
++;
918 intgen
->next
= intgen_list
;
919 intgen_list
= intgen
;
920 (*v850_callback
->printf_filtered
) (v850_callback
, "Interrupt generator %d (NMI) at pc=0x%x, time=%d.\n", intgen_list
->number
, intgen_list
->address
, intgen_list
->time
);
922 else if (*argv
&& !strcmp (*argv
, "remove"))
925 num
= sim_parse_number (*argv
, NULL
);
929 if (intgen_list
->number
== num
)
931 tmpgen
= intgen_list
;
932 intgen_list
= intgen_list
->next
;
936 for (intgen
= intgen_list
; intgen
!= NULL
; intgen
= intgen
->next
)
938 if (intgen
->next
!= NULL
&& intgen
->next
->number
== num
)
940 tmpgen
= intgen
->next
;
941 intgen
->next
= intgen
->next
->next
;
949 (*v850_callback
->printf_filtered
) (v850_callback
,
950 "No interrupt generator numbered %d, ignoring.\n", num
);
953 else if (*argv
&& !strcmp (*argv
, "info"))
957 for (intgen
= intgen_list
; intgen
!= NULL
; intgen
= intgen
->next
)
958 (*v850_callback
->printf_filtered
) (v850_callback
,
959 "Interrupt generator %d (%s) at pc=0x%x/time=%d%s.\n",
961 interrupt_names
[intgen
->type
],
964 (intgen
->enabled
? "" : " (disabled)"));
968 (*v850_callback
->printf_filtered
) (v850_callback
, "No interrupt generators defined.\n");
974 (*v850_callback
->printf_filtered
) (v850_callback
,
975 "Invalid interrupt command, must be one of `add', `remove', or `info'.\n");
977 /* Cache the presence of a non-maskable generator. */
978 have_nm_generator
= 0;
979 for (intgen
= intgen_list
; intgen
!= NULL
; intgen
= intgen
->next
)
981 if (intgen
->type
== int_nmi
|| intgen
->type
== int_reset
)
983 have_nm_generator
= 1;
990 sim_do_command (sd
, cmd
)
994 char *mm_cmd
= "memory-map";
995 char *int_cmd
= "interrupt";
997 if (! strncmp (cmd
, mm_cmd
, strlen (mm_cmd
))
998 && strchr (" ", cmd
[strlen(mm_cmd
)]))
999 sim_set_memory_map (cmd
+ strlen(mm_cmd
) + 1);
1001 else if (! strncmp (cmd
, int_cmd
, strlen (int_cmd
))
1002 && strchr (" ", cmd
[strlen(int_cmd
)]))
1003 sim_set_interrupt (cmd
+ strlen(int_cmd
) + 1);
1005 else if (! strcmp (cmd
, "help"))
1007 (*v850_callback
->printf_filtered
) (v850_callback
, "V850 simulator commands:\n\n");
1008 (*v850_callback
->printf_filtered
) (v850_callback
, "interrupt add <inttype> { pc | time } <value> -- Set up an interrupt generator\n");
1009 (*v850_callback
->printf_filtered
) (v850_callback
, "interrupt remove <n> -- Remove an existing interrupt generator\n");
1010 (*v850_callback
->printf_filtered
) (v850_callback
, "interrupt info -- List all the interrupt generators\n");
1011 (*v850_callback
->printf_filtered
) (v850_callback
, "memory-map hole=<m>,<n> -- Set the memory map to have a hole between <m> and <n>\n");
1012 (*v850_callback
->printf_filtered
) (v850_callback
, "\n");
1015 (*v850_callback
->printf_filtered
) (v850_callback
, "\"%s\" is not a valid V850 simulator command.\n",
1020 sim_load (sd
, prog
, abfd
, from_tty
)
1026 extern bfd
*sim_load_file (); /* ??? Don't know where this should live. */
1029 prog_bfd
= sim_load_file (sd
, myname
, v850_callback
, prog
, abfd
,
1030 sim_kind
== SIM_OPEN_DEBUG
);
1031 if (prog_bfd
== NULL
)
1033 PC
= bfd_get_start_address (prog_bfd
);
1035 bfd_close (prog_bfd
);