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