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