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 /* non-zero if we opened prog_bfd */
80 static int prog_bfd_was_opened_p
;
83 static SIM_OPEN_KIND sim_kind
;
88 static struct hash_entry
*lookup_hash
PARAMS ((uint32 ins
));
89 static long hash
PARAMS ((long));
90 static void do_format_1_2
PARAMS ((uint32
));
91 static void do_format_3
PARAMS ((uint32
));
92 static void do_format_4
PARAMS ((uint32
));
93 static void do_format_5
PARAMS ((uint32
));
94 static void do_format_6
PARAMS ((uint32
));
95 static void do_format_7
PARAMS ((uint32
));
96 static void do_format_8
PARAMS ((uint32
));
97 static void do_format_9_10
PARAMS ((uint32
));
98 static void init_system
PARAMS ((void));
104 struct hash_entry
*next
;
110 struct hash_entry hash_table
[MAX_HASH
+1];
117 if ( (insn
& 0x0600) == 0
118 || (insn
& 0x0700) == 0x0200
119 || (insn
& 0x0700) == 0x0600
120 || (insn
& 0x0780) == 0x0700)
121 return (insn
& 0x07e0) >> 5;
123 if ((insn
& 0x0700) == 0x0300
124 || (insn
& 0x0700) == 0x0400
125 || (insn
& 0x0700) == 0x0500)
126 return (insn
& 0x0780) >> 7;
128 if ((insn
& 0x07c0) == 0x0780)
129 return (insn
& 0x07c0) >> 6;
131 return (insn
& 0x07e0) >> 5;
134 static struct hash_entry
*
138 struct hash_entry
*h
;
140 h
= &hash_table
[hash(ins
)];
142 while ((ins
& h
->mask
) != h
->opcode
)
146 (*v850_callback
->printf_filtered
) (v850_callback
, "ERROR looking up hash for 0x%x, PC=0x%x\n", ins
, PC
);
154 /* FIXME These would more efficient to use than load_mem/store_mem,
155 but need to be changed to use the memory map. */
169 return (a
[1] << 8) + (a
[0]);
177 return (a
[3]<<24) + (a
[2]<<16) + (a
[1]<<8) + (a
[0]);
181 put_byte (addr
, data
)
190 put_half (addr
, data
)
196 a
[1] = (data
>> 8) & 0xff;
200 put_word (addr
, data
)
206 a
[1] = (data
>> 8) & 0xff;
207 a
[2] = (data
>> 16) & 0xff;
208 a
[3] = (data
>> 24) & 0xff;
217 /* Mask down to 24 bits. */
222 /* "Mirror" the addresses below 1MB. */
224 addr
&= (rom_size
- 1);
226 addr
+= (rom_size
- 0x100000);
227 return (uint8
*) (addr
+ State
.mem
);
229 else if (addr
>= high_start
)
231 /* If in the peripheral I/O region, mirror 1K region across 4K,
232 and similarly if in the internal RAM region. */
233 if (addr
>= 0xfff000)
235 else if (addr
>= 0xffe000)
237 return (uint8
*) (addr
- high_start
+ high_base
+ State
.mem
);
241 fprintf (stderr
, "segmentation fault: access address: %x not below %x or above %x [ep = %x]\n", addr
, low_end
, high_start
, State
.regs
[30]);
243 /* Signal a memory error. */
244 State
.exception
= SIGSEGV
;
245 /* Point to a location not in main memory - renders invalid
246 addresses harmless until we get back to main insn loop. */
247 return (uint8
*) &(State
.dummy_mem
);
256 uint8
*p
= map (addr
);
263 return p
[1] << 8 | p
[0];
265 return p
[3] << 24 | p
[2] << 16 | p
[1] << 8 | p
[0];
272 store_mem (addr
, len
, data
)
277 uint8
*p
= map (addr
);
309 totsize
= rom_size
+ (low_end
- 0x100000) + (0x1000000 - high_start
);
311 high_base
= rom_size
+ (low_end
- 0x100000);
313 State
.mem
= (uint8
*) calloc (1, totsize
);
316 (*v850_callback
->printf_filtered
) (v850_callback
, "Allocation of main memory failed.\n");
322 sim_set_memory_map (spec
)
325 char *reststr
, *nreststr
;
326 SIM_ADDR new_low_end
, new_high_start
;
328 new_low_end
= low_end
;
329 new_high_start
= high_start
;
330 if (! strncmp (spec
, "hole=", 5))
332 new_low_end
= sim_parse_number (spec
+ 5, &reststr
);
333 if (new_low_end
< 0x100000)
335 (*v850_callback
->printf_filtered
) (v850_callback
,
336 "Low end must be at least 0x100000\n");
342 new_high_start
= sim_parse_number (reststr
, &nreststr
);
343 /* FIXME Check high_start also */
345 (*v850_callback
->printf_filtered
) (v850_callback
,
346 "Hole goes from 0x%x to 0x%x\n",
347 new_low_end
, new_high_start
);
351 (*v850_callback
->printf_filtered
) (v850_callback
, "Invalid specification for memory map, must be `hole=<m>[,<n>]'\n");
354 if (new_low_end
!= low_end
|| new_high_start
!= high_start
)
356 low_end
= new_low_end
;
357 high_start
= new_high_start
;
360 (*v850_callback
->printf_filtered
) (v850_callback
, "Reconfiguring memory (old contents will be lost)\n");
366 /* Parse a number in hex, octal, or decimal form. */
369 sim_parse_number (str
, rest
)
372 if (str
[0] == '0' && str
[1] == 'x')
373 return strtol (str
, rest
, 16);
374 else if (str
[0] == '0')
375 return strtol (str
, rest
, 16);
377 return strtol (str
, rest
, 10);
388 sim_write (sd
, addr
, buffer
, size
)
391 unsigned char *buffer
;
398 for (i
= 0; i
< size
; i
++)
399 store_mem (addr
+ i
, 1, buffer
[i
]);
405 sim_open (kind
, cb
, abfd
, argv
)
412 struct hash_entry
*h
;
421 for (p
= argv
+ 1; *p
; ++p
)
424 if (strcmp (*p
, "-t") == 0)
428 (*v850_callback
->printf_filtered
) (v850_callback
, "ERROR: unsupported option(s): %s\n",*p
);
432 /* put all the opcodes in the hash table */
433 for (s
= Simops
; s
->func
; s
++)
435 h
= &hash_table
[hash(s
->opcode
)];
437 /* go to the last entry in the chain */
443 h
->next
= (struct hash_entry
*) calloc(1,sizeof(struct hash_entry
));
448 h
->opcode
= s
->opcode
;
451 /* fudge our descriptor for now */
457 sim_close (sd
, quitting
)
461 if (prog_bfd
!= NULL
&& prog_bfd_was_opened_p
)
462 bfd_close (prog_bfd
);
469 (*v850_callback
->printf_filtered
) (v850_callback
, "sim_set_profile %d\n", n
);
473 sim_set_profile_size (n
)
476 (*v850_callback
->printf_filtered
) (v850_callback
, "sim_set_profile_size %d\n", n
);
481 static void do_interrupt
PARAMS ((enum interrupt_type
));
491 sim_resume (sd
, step
, siggnal
)
497 struct interrupt_generator
*intgen
;
501 State
.exception
= SIGTRAP
;
509 struct hash_entry
* h
;
510 /* Fetch the current instruction. */
514 h
= lookup_hash (inst
);
516 OP
[1] = (inst
>> 11) & 0x1f;
517 OP
[2] = (inst
>> 16) & 0xffff;
520 // fprintf (stderr, "PC = %x, SP = %x\n", PC, SP );
524 fprintf (stderr
, "NOP encountered!\n");
528 PC
+= h
->ops
->func ();
532 fprintf (stderr
, "simulator loop at %x\n", PC
);
536 /* Check for and handle pending interrupts. */
537 if (intgen_list
&& (have_nm_generator
|| !(PSW
& PSW_ID
)))
540 for (intgen
= intgen_list
; intgen
!= NULL
; intgen
= intgen
->next
)
542 if (intgen
->cond_type
== int_cond_pc
543 && oldpc
== intgen
->address
548 else if (intgen
->cond_type
== int_cond_time
552 if (((long) now
- (long) start_time
) > intgen
->time
)
560 do_interrupt (intgen
->type
);
562 else if (State
.pending_nmi
)
564 State
.pending_nmi
= 0;
565 do_interrupt (int_nmi
);
568 while (!State
.exception
);
572 do_interrupt (inttype
)
573 enum interrupt_type inttype
;
575 /* Disable further interrupts. */
577 /* Indicate that we're doing interrupt not exception processing. */
579 if (inttype
== int_reset
)
584 /* (Might be useful to init other regs with random values.) */
586 else if (inttype
== int_nmi
)
590 /* We're already working on an NMI, so this one must wait
591 around until the previous one is done. The processor
592 ignores subsequent NMIs, so we don't need to count them. */
593 State
.pending_nmi
= 1;
599 /* Set the FECC part of the ECR. */
610 /* Clear the EICC part of the ECR, will set below. */
639 /* Should never be possible. */
653 sim_resume (sd
, 0, 0);
658 sim_info (sd
, verbose
)
662 (*v850_callback
->printf_filtered
) (v850_callback
, "sim_info\n");
666 sim_create_inferior (sd
, abfd
, argv
, env
)
673 PC
= bfd_get_start_address (prog_bfd
);
680 sim_set_callbacks (p
)
686 /* All the code for exiting, signals, etc needs to be revamped.
688 This is enough to get c-torture limping though. */
691 sim_stop_reason (sd
, reason
, sigrc
)
693 enum sim_stop
*reason
;
696 if (State
.exception
== SIG_V850_EXIT
)
698 *reason
= sim_exited
;
699 *sigrc
= State
.regs
[7];
703 *reason
= sim_stopped
;
704 *sigrc
= State
.exception
;
709 sim_fetch_register (sd
, rn
, memory
)
712 unsigned char *memory
;
714 put_word (memory
, State
.regs
[rn
]);
718 sim_store_register (sd
, rn
, memory
)
721 unsigned char *memory
;
723 State
.regs
[rn
] = get_word (memory
);
727 sim_read (sd
, addr
, buffer
, size
)
730 unsigned char *buffer
;
734 for (i
= 0; i
< size
; i
++)
735 buffer
[i
] = load_mem (addr
+ i
, 1);
740 int current_intgen_number
= 1;
743 sim_set_interrupt (spec
)
748 struct interrupt_generator
*intgen
, *tmpgen
;
749 extern char **buildargv ();
751 argv
= buildargv (spec
);
753 if (*argv
&& ! strcmp (*argv
, "add"))
755 /* Create a new interrupt generator object. */
756 intgen
= (struct interrupt_generator
*)
757 malloc (sizeof(struct interrupt_generator
));
758 intgen
->type
= int_none
;
759 intgen
->cond_type
= int_cond_none
;
764 /* Match on interrupt type name. */
765 for (i
= 0; i
< num_int_types
; ++i
)
767 if (*argv
&& ! strcmp (*argv
, interrupt_names
[i
]))
773 if (intgen
->type
== int_none
)
775 (*v850_callback
->printf_filtered
) (v850_callback
, "Interrupt type unknown; known types are\n");
776 for (i
= 0; i
< num_int_types
; ++i
)
778 (*v850_callback
->printf_filtered
) (v850_callback
, " %s", interrupt_names
[i
]);
780 (*v850_callback
->printf_filtered
) (v850_callback
, "\n");
787 if (*argv
&& ! strcmp (*argv
, "pc"))
789 intgen
->cond_type
= int_cond_pc
;
791 intgen
->address
= sim_parse_number (*argv
, NULL
);
793 else if (*argv
&& ! strcmp (*argv
, "time"))
795 intgen
->cond_type
= int_cond_time
;
797 intgen
->time
= sim_parse_number (*argv
, NULL
);
801 (*v850_callback
->printf_filtered
) (v850_callback
, "Condition type must be `pc' or `time'.\n");
805 /* We now have a valid interrupt generator. Number it and add
806 to the list of generators. */
807 intgen
->number
= current_intgen_number
++;
809 intgen
->next
= intgen_list
;
810 intgen_list
= intgen
;
811 (*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
);
813 else if (*argv
&& !strcmp (*argv
, "remove"))
816 num
= sim_parse_number (*argv
, NULL
);
820 if (intgen_list
->number
== num
)
822 tmpgen
= intgen_list
;
823 intgen_list
= intgen_list
->next
;
827 for (intgen
= intgen_list
; intgen
!= NULL
; intgen
= intgen
->next
)
829 if (intgen
->next
!= NULL
&& intgen
->next
->number
== num
)
831 tmpgen
= intgen
->next
;
832 intgen
->next
= intgen
->next
->next
;
840 (*v850_callback
->printf_filtered
) (v850_callback
,
841 "No interrupt generator numbered %d, ignoring.\n", num
);
844 else if (*argv
&& !strcmp (*argv
, "info"))
848 for (intgen
= intgen_list
; intgen
!= NULL
; intgen
= intgen
->next
)
849 (*v850_callback
->printf_filtered
) (v850_callback
,
850 "Interrupt generator %d (%s) at pc=0x%x/time=%d%s.\n",
852 interrupt_names
[intgen
->type
],
855 (intgen
->enabled
? "" : " (disabled)"));
859 (*v850_callback
->printf_filtered
) (v850_callback
, "No interrupt generators defined.\n");
865 (*v850_callback
->printf_filtered
) (v850_callback
,
866 "Invalid interrupt command, must be one of `add', `remove', or `info'.\n");
868 /* Cache the presence of a non-maskable generator. */
869 have_nm_generator
= 0;
870 for (intgen
= intgen_list
; intgen
!= NULL
; intgen
= intgen
->next
)
872 if (intgen
->type
== int_nmi
|| intgen
->type
== int_reset
)
874 have_nm_generator
= 1;
881 sim_do_command (sd
, cmd
)
885 char *mm_cmd
= "memory-map";
886 char *int_cmd
= "interrupt";
888 if (! strncmp (cmd
, mm_cmd
, strlen (mm_cmd
))
889 && strchr (" ", cmd
[strlen(mm_cmd
)]))
890 sim_set_memory_map (cmd
+ strlen(mm_cmd
) + 1);
892 else if (! strncmp (cmd
, int_cmd
, strlen (int_cmd
))
893 && strchr (" ", cmd
[strlen(int_cmd
)]))
894 sim_set_interrupt (cmd
+ strlen(int_cmd
) + 1);
896 else if (! strcmp (cmd
, "help"))
898 (*v850_callback
->printf_filtered
) (v850_callback
, "V850 simulator commands:\n\n");
899 (*v850_callback
->printf_filtered
) (v850_callback
, "interrupt add <inttype> { pc | time } <value> -- Set up an interrupt generator\n");
900 (*v850_callback
->printf_filtered
) (v850_callback
, "interrupt remove <n> -- Remove an existing interrupt generator\n");
901 (*v850_callback
->printf_filtered
) (v850_callback
, "interrupt info -- List all the interrupt generators\n");
902 (*v850_callback
->printf_filtered
) (v850_callback
, "memory-map hole=<m>,<n> -- Set the memory map to have a hole between <m> and <n>\n");
903 (*v850_callback
->printf_filtered
) (v850_callback
, "\n");
906 (*v850_callback
->printf_filtered
) (v850_callback
, "\"%s\" is not a valid V850 simulator command.\n",
911 sim_load (sd
, prog
, abfd
, from_tty
)
917 extern bfd
*sim_load_file (); /* ??? Don't know where this should live. */
919 if (prog_bfd
!= NULL
&& prog_bfd_was_opened_p
)
920 bfd_close (prog_bfd
);
921 prog_bfd
= sim_load_file (sd
, myname
, v850_callback
, prog
, abfd
,
922 sim_kind
== SIM_OPEN_DEBUG
);
923 if (prog_bfd
== NULL
)
925 prog_bfd_was_opened_p
= abfd
== NULL
;