xref: /netbsd-src/external/gpl3/gdb.old/dist/sim/v850/interp.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* This must come before any other includes.  */
2 #include "defs.h"
3 
4 #include "sim-main.h"
5 #include "sim-options.h"
6 #include "v850_sim.h"
7 #include "sim-assert.h"
8 #include "itable.h"
9 
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #include "bfd.h"
14 
15 #include "target-newlib-syscall.h"
16 
17 static const char * get_insn_name (sim_cpu *, int);
18 
19 /* For compatibility.  */
20 SIM_DESC simulator;
21 
22 /* V850 interrupt model.  */
23 
24 enum interrupt_type
25 {
26   int_reset,
27   int_nmi,
28   int_intov1,
29   int_intp10,
30   int_intp11,
31   int_intp12,
32   int_intp13,
33   int_intcm4,
34   num_int_types
35 };
36 
37 const char *interrupt_names[] =
38 {
39   "reset",
40   "nmi",
41   "intov1",
42   "intp10",
43   "intp11",
44   "intp12",
45   "intp13",
46   "intcm4",
47   NULL
48 };
49 
50 static void
51 do_interrupt (SIM_DESC sd, void *data)
52 {
53   const char **interrupt_name = (const char**)data;
54   enum interrupt_type inttype;
55   inttype = (interrupt_name - STATE_WATCHPOINTS (sd)->interrupt_names);
56 
57   /* For a hardware reset, drop everything and jump to the start
58      address */
59   if (inttype == int_reset)
60     {
61       PC = 0;
62       PSW = 0x20;
63       ECR = 0;
64       sim_engine_restart (sd, NULL, NULL, NULL_CIA);
65     }
66 
67   /* Deliver an NMI when allowed */
68   if (inttype == int_nmi)
69     {
70       if (PSW & PSW_NP)
71 	{
72 	  /* We're already working on an NMI, so this one must wait
73 	     around until the previous one is done.  The processor
74 	     ignores subsequent NMIs, so we don't need to count them.
75 	     Just keep re-scheduling a single NMI until it manages to
76 	     be delivered */
77 	  if (STATE_CPU (sd, 0)->pending_nmi != NULL)
78 	    sim_events_deschedule (sd, STATE_CPU (sd, 0)->pending_nmi);
79 	  STATE_CPU (sd, 0)->pending_nmi =
80 	    sim_events_schedule (sd, 1, do_interrupt, data);
81 	  return;
82 	}
83       else
84 	{
85 	  /* NMI can be delivered.  Do not deschedule pending_nmi as
86              that, if still in the event queue, is a second NMI that
87              needs to be delivered later. */
88 	  FEPC = PC;
89 	  FEPSW = PSW;
90 	  /* Set the FECC part of the ECR. */
91 	  ECR &= 0x0000ffff;
92 	  ECR |= 0x10;
93 	  PSW |= PSW_NP;
94 	  PSW &= ~PSW_EP;
95 	  PSW |= PSW_ID;
96 	  PC = 0x10;
97 	  sim_engine_restart (sd, NULL, NULL, NULL_CIA);
98 	}
99     }
100 
101   /* deliver maskable interrupt when allowed */
102   if (inttype > int_nmi && inttype < num_int_types)
103     {
104       if ((PSW & PSW_NP) || (PSW & PSW_ID))
105 	{
106 	  /* Can't deliver this interrupt, reschedule it for later */
107 	  sim_events_schedule (sd, 1, do_interrupt, data);
108 	  return;
109 	}
110       else
111 	{
112 	  /* save context */
113 	  EIPC = PC;
114 	  EIPSW = PSW;
115 	  /* Disable further interrupts.  */
116 	  PSW |= PSW_ID;
117 	  /* Indicate that we're doing interrupt not exception processing.  */
118 	  PSW &= ~PSW_EP;
119 	  /* Clear the EICC part of the ECR, will set below. */
120 	  ECR &= 0xffff0000;
121 	  switch (inttype)
122 	    {
123 	    case int_intov1:
124 	      PC = 0x80;
125 	      ECR |= 0x80;
126 	      break;
127 	    case int_intp10:
128 	      PC = 0x90;
129 	      ECR |= 0x90;
130 	      break;
131 	    case int_intp11:
132 	      PC = 0xa0;
133 	      ECR |= 0xa0;
134 	      break;
135 	    case int_intp12:
136 	      PC = 0xb0;
137 	      ECR |= 0xb0;
138 	      break;
139 	    case int_intp13:
140 	      PC = 0xc0;
141 	      ECR |= 0xc0;
142 	      break;
143 	    case int_intcm4:
144 	      PC = 0xd0;
145 	      ECR |= 0xd0;
146 	      break;
147 	    default:
148 	      /* Should never be possible.  */
149 	      sim_engine_abort (sd, NULL, NULL_CIA,
150 				"do_interrupt - internal error - bad switch");
151 	      break;
152 	    }
153 	}
154       sim_engine_restart (sd, NULL, NULL, NULL_CIA);
155     }
156 
157   /* some other interrupt? */
158   sim_engine_abort (sd, NULL, NULL_CIA,
159 		    "do_interrupt - internal error - interrupt %d unknown",
160 		    inttype);
161 }
162 
163 /* Return name of an insn, used by insn profiling.  */
164 
165 static const char *
166 get_insn_name (sim_cpu *cpu, int i)
167 {
168   return itable[i].name;
169 }
170 
171 /* These default values correspond to expected usage for the chip.  */
172 
173 uint32_t OP[4];
174 
175 static sim_cia
176 v850_pc_get (sim_cpu *cpu)
177 {
178   return PC;
179 }
180 
181 static void
182 v850_pc_set (sim_cpu *cpu, sim_cia pc)
183 {
184   PC = pc;
185 }
186 
187 static int v850_reg_fetch (SIM_CPU *, int, void *, int);
188 static int v850_reg_store (SIM_CPU *, int, const void *, int);
189 
190 SIM_DESC
191 sim_open (SIM_OPEN_KIND    kind,
192 	  host_callback *  cb,
193 	  struct bfd *     abfd,
194 	  char * const *   argv)
195 {
196   int i;
197   SIM_DESC sd = sim_state_alloc (kind, cb);
198   int mach;
199 
200   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
201 
202   /* Set default options before parsing user options.  */
203   current_target_byte_order = BFD_ENDIAN_LITTLE;
204   cb->syscall_map = cb_v850_syscall_map;
205 
206   /* The cpu data is kept in a separately allocated chunk of memory.  */
207   if (sim_cpu_alloc_all (sd, 1) != SIM_RC_OK)
208     return 0;
209 
210   /* for compatibility */
211   simulator = sd;
212 
213   /* FIXME: should be better way of setting up interrupts */
214   STATE_WATCHPOINTS (sd)->interrupt_handler = do_interrupt;
215   STATE_WATCHPOINTS (sd)->interrupt_names = interrupt_names;
216 
217   /* Initialize the mechanism for doing insn profiling.  */
218   CPU_INSN_NAME (STATE_CPU (sd, 0)) = get_insn_name;
219   CPU_MAX_INSNS (STATE_CPU (sd, 0)) = nr_itable_entries;
220 
221   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
222     return 0;
223 
224   /* Allocate core managed memory */
225 
226   /* "Mirror" the ROM addresses below 1MB. */
227   sim_do_commandf (sd, "memory region 0,0x100000,0x%x", V850_ROM_SIZE);
228   /* Chunk of ram adjacent to rom */
229   sim_do_commandf (sd, "memory region 0x100000,0x%x", V850_LOW_END-0x100000);
230   /* peripheral I/O region - mirror 1K across 4k (0x1000) */
231   sim_do_command (sd, "memory region 0xfff000,0x1000,1024");
232   /* similarly if in the internal RAM region */
233   sim_do_command (sd, "memory region 0xffe000,0x1000,1024");
234 
235   /* The parser will print an error message for us, so we silently return.  */
236   if (sim_parse_args (sd, argv) != SIM_RC_OK)
237     {
238       /* Uninstall the modules to avoid memory leaks,
239 	 file descriptor leaks, etc.  */
240       sim_module_uninstall (sd);
241       return 0;
242     }
243 
244   /* check for/establish the a reference program image */
245   if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
246     {
247       sim_module_uninstall (sd);
248       return 0;
249     }
250 
251   /* establish any remaining configuration options */
252   if (sim_config (sd) != SIM_RC_OK)
253     {
254       sim_module_uninstall (sd);
255       return 0;
256     }
257 
258   if (sim_post_argv_init (sd) != SIM_RC_OK)
259     {
260       /* Uninstall the modules to avoid memory leaks,
261 	 file descriptor leaks, etc.  */
262       sim_module_uninstall (sd);
263       return 0;
264     }
265 
266 
267   /* determine the machine type */
268   if (STATE_ARCHITECTURE (sd) != NULL
269       && (STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850
270 	  || STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850_rh850))
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     case bfd_mach_v850e1:
281     case bfd_mach_v850e2:
282     case bfd_mach_v850e2v3:
283     case bfd_mach_v850e3v5:
284       STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT
285 				     | PSW_CY | PSW_OV | PSW_S | PSW_Z);
286       break;
287     }
288 
289   /* CPU specific initialization.  */
290   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
291     {
292       SIM_CPU *cpu = STATE_CPU (sd, i);
293 
294       CPU_REG_FETCH (cpu) = v850_reg_fetch;
295       CPU_REG_STORE (cpu) = v850_reg_store;
296       CPU_PC_FETCH (cpu) = v850_pc_get;
297       CPU_PC_STORE (cpu) = v850_pc_set;
298     }
299 
300   return sd;
301 }
302 
303 SIM_RC
304 sim_create_inferior (SIM_DESC      sd,
305 		     struct bfd *  prog_bfd,
306 		     char * const *argv,
307 		     char * const *env)
308 {
309   memset (&State, 0, sizeof (State));
310   if (prog_bfd != NULL)
311     PC = bfd_get_start_address (prog_bfd);
312   return SIM_RC_OK;
313 }
314 
315 static int
316 v850_reg_fetch (SIM_CPU *cpu, int rn, void *memory, int length)
317 {
318   *(uint32_t*)memory = H2T_4 (State.regs[rn]);
319   return -1;
320 }
321 
322 static int
323 v850_reg_store (SIM_CPU *cpu, int rn, const void *memory, int length)
324 {
325   State.regs[rn] = T2H_4 (*(uint32_t *) memory);
326   return length;
327 }
328