]>
Commit | Line | Data |
---|---|---|
b34f6357 | 1 | # Simulator main loop for frv. -*- C -*- |
6aba47ca DJ |
2 | # Copyright (C) 1998, 1999, 2000, 2001, 2003, 2007 |
3 | Free Software Foundation, Inc. | |
b34f6357 DB |
4 | # Contributed by Red Hat. |
5 | # | |
6 | # This file is part of the GNU Simulators. | |
7 | # | |
8 | # This program is free software; you can redistribute it and/or modify | |
9 | # it under the terms of the GNU General Public License as published by | |
10 | # the Free Software Foundation; either version 2, or (at your option) | |
11 | # any later version. | |
12 | # | |
13 | # This program is distributed in the hope that it will be useful, | |
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | # GNU General Public License for more details. | |
17 | # | |
18 | # You should have received a copy of the GNU General Public License along | |
19 | # with this program; if not, write to the Free Software Foundation, Inc., | |
20 | # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
21 | ||
22 | # Syntax: | |
23 | # /bin/sh mainloop.in command | |
24 | # | |
25 | # Command is one of: | |
26 | # | |
27 | # init | |
28 | # support | |
29 | # extract-{simple,scache,pbb} | |
30 | # {full,fast}-exec-{simple,scache,pbb} | |
31 | # | |
32 | # A target need only provide a "full" version of one of simple,scache,pbb. | |
33 | # If the target wants it can also provide a fast version of same. | |
34 | # It can't provide more than this. | |
35 | ||
36 | # ??? After a few more ports are done, revisit. | |
37 | # Will eventually need to machine generate a lot of this. | |
38 | ||
39 | case "x$1" in | |
40 | ||
41 | xsupport) | |
42 | ||
43 | cat <<EOF | |
44 | ||
45 | static INLINE const IDESC * | |
46 | extract (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, ARGBUF *abuf, | |
47 | int fast_p) | |
48 | { | |
49 | const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf); | |
50 | @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p); | |
51 | if (! fast_p) | |
52 | { | |
53 | int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc); | |
54 | int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc); | |
55 | @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p); | |
56 | } | |
57 | return id; | |
58 | } | |
59 | ||
60 | static INLINE SEM_PC | |
61 | execute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p) | |
62 | { | |
63 | SEM_PC vpc; | |
64 | ||
65 | /* Force gr0 to zero before every insn. */ | |
66 | @cpu@_h_gr_set (current_cpu, 0, 0); | |
67 | ||
68 | if (fast_p) | |
69 | { | |
70 | vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc); | |
71 | } | |
72 | else | |
73 | { | |
74 | ARGBUF *abuf = &sc->argbuf; | |
75 | const IDESC *idesc = abuf->idesc; | |
76 | #if WITH_SCACHE_PBB | |
77 | int virtual_p = CGEN_ATTR_VALUE (NULL, idesc->attrs, CGEN_INSN_VIRTUAL); | |
78 | #else | |
79 | int virtual_p = 0; | |
80 | #endif | |
81 | ||
82 | if (! virtual_p) | |
83 | { | |
84 | /* FIXME: call x-before */ | |
85 | if (ARGBUF_PROFILE_P (abuf)) | |
86 | PROFILE_COUNT_INSN (current_cpu, abuf->addr, idesc->num); | |
87 | /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */ | |
88 | if (FRV_COUNT_CYCLES (current_cpu, ARGBUF_PROFILE_P (abuf))) | |
89 | { | |
90 | @cpu@_model_insn_before (current_cpu, sc->first_insn_p); | |
91 | model_insn = FRV_INSN_MODEL_PASS_1; | |
92 | if (idesc->timing->model_fn != NULL) | |
93 | (*idesc->timing->model_fn) (current_cpu, sc); | |
94 | } | |
95 | else | |
96 | model_insn = FRV_INSN_NO_MODELING; | |
97 | TRACE_INSN_INIT (current_cpu, abuf, 1); | |
98 | TRACE_INSN (current_cpu, idesc->idata, | |
99 | (const struct argbuf *) abuf, abuf->addr); | |
100 | } | |
101 | #if WITH_SCACHE | |
102 | vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc); | |
103 | #else | |
104 | vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, abuf); | |
105 | #endif | |
106 | if (! virtual_p) | |
107 | { | |
108 | /* FIXME: call x-after */ | |
109 | if (FRV_COUNT_CYCLES (current_cpu, ARGBUF_PROFILE_P (abuf))) | |
110 | { | |
111 | int cycles; | |
112 | if (idesc->timing->model_fn != NULL) | |
113 | { | |
114 | model_insn = FRV_INSN_MODEL_PASS_2; | |
115 | cycles = (*idesc->timing->model_fn) (current_cpu, sc); | |
116 | } | |
117 | else | |
118 | cycles = 1; | |
119 | @cpu@_model_insn_after (current_cpu, sc->last_insn_p, cycles); | |
120 | } | |
121 | TRACE_INSN_FINI (current_cpu, abuf, 1); | |
122 | } | |
123 | } | |
124 | ||
125 | return vpc; | |
126 | } | |
127 | ||
128 | static void | |
129 | @cpu@_parallel_write_init (SIM_CPU *current_cpu) | |
130 | { | |
131 | CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu); | |
132 | CGEN_WRITE_QUEUE_CLEAR (q); | |
133 | previous_vliw_pc = CPU_PC_GET(current_cpu); | |
134 | frv_interrupt_state.f_ne_flags[0] = 0; | |
135 | frv_interrupt_state.f_ne_flags[1] = 0; | |
136 | frv_interrupt_state.imprecise_interrupt = NULL; | |
137 | } | |
138 | ||
139 | static void | |
140 | @cpu@_parallel_write_queued (SIM_CPU *current_cpu) | |
141 | { | |
142 | int i; | |
143 | ||
144 | FRV_VLIW *vliw = CPU_VLIW (current_cpu); | |
145 | CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu); | |
146 | ||
147 | /* Loop over the queued writes, executing them. Set the pc to the address | |
148 | of the insn which queued each write for the proper context in case an | |
149 | interrupt is caused. Restore the proper pc after the writes are | |
150 | completed. */ | |
151 | IADDR save_pc = CPU_PC_GET (current_cpu); | |
152 | IADDR new_pc = save_pc; | |
153 | int branch_taken = 0; | |
154 | int limit = CGEN_WRITE_QUEUE_INDEX (q); | |
155 | frv_interrupt_state.data_written.length = 0; | |
156 | ||
157 | for (i = 0; i < limit; ++i) | |
158 | { | |
159 | CGEN_WRITE_QUEUE_ELEMENT *item = CGEN_WRITE_QUEUE_ELEMENT (q, i); | |
160 | ||
161 | /* If an imprecise interrupt was generated, then, check whether the | |
162 | result should still be written. */ | |
163 | if (frv_interrupt_state.imprecise_interrupt != NULL) | |
164 | { | |
165 | /* Only check writes by the insn causing the exception. */ | |
166 | if (CGEN_WRITE_QUEUE_ELEMENT_IADDR (item) | |
167 | == frv_interrupt_state.imprecise_interrupt->vpc) | |
168 | { | |
169 | /* Execute writes of floating point operations resulting in | |
170 | overflow, underflow or inexact. */ | |
171 | if (frv_interrupt_state.imprecise_interrupt->kind | |
172 | == FRV_FP_EXCEPTION) | |
173 | { | |
174 | if ((frv_interrupt_state.imprecise_interrupt | |
175 | ->u.fp_info.fsr_mask | |
176 | & ~(FSR_INEXACT | FSR_OVERFLOW | FSR_UNDERFLOW))) | |
177 | continue; /* Don't execute */ | |
178 | } | |
179 | /* Execute writes marked as 'forced'. */ | |
180 | else if (! (CGEN_WRITE_QUEUE_ELEMENT_FLAGS (item) | |
181 | & FRV_WRITE_QUEUE_FORCE_WRITE)) | |
182 | continue; /* Don't execute */ | |
183 | } | |
184 | } | |
185 | ||
186 | /* Only execute the first branch on the queue. */ | |
187 | if (CGEN_WRITE_QUEUE_ELEMENT_KIND (item) == CGEN_PC_WRITE | |
188 | || CGEN_WRITE_QUEUE_ELEMENT_KIND (item) == CGEN_FN_PC_WRITE) | |
189 | { | |
190 | if (branch_taken) | |
191 | continue; | |
192 | branch_taken = 1; | |
193 | if (CGEN_WRITE_QUEUE_ELEMENT_KIND (item) == CGEN_PC_WRITE) | |
194 | new_pc = item->kinds.pc_write.value; | |
195 | else | |
196 | new_pc = item->kinds.fn_pc_write.value; | |
197 | } | |
198 | ||
199 | CPU_PC_SET (current_cpu, CGEN_WRITE_QUEUE_ELEMENT_IADDR (item)); | |
200 | frv_save_data_written_for_interrupts (current_cpu, item); | |
201 | cgen_write_queue_element_execute (current_cpu, item); | |
202 | } | |
203 | ||
204 | /* Update the LR with the address of the next insn if the flag is set. | |
205 | This flag gets set in frvbf_set_write_next_vliw_to_LR by the JMPL, | |
206 | JMPIL and CALL insns. */ | |
207 | if (frvbf_write_next_vliw_addr_to_LR) | |
208 | { | |
209 | frvbf_h_spr_set_handler (current_cpu, H_SPR_LR, save_pc); | |
210 | frvbf_write_next_vliw_addr_to_LR = 0; | |
211 | } | |
212 | ||
213 | CPU_PC_SET (current_cpu, new_pc); | |
214 | CGEN_WRITE_QUEUE_CLEAR (q); | |
215 | } | |
216 | ||
217 | void | |
218 | @cpu@_perform_writeback (SIM_CPU *current_cpu) | |
219 | { | |
220 | @cpu@_parallel_write_queued (current_cpu); | |
221 | } | |
222 | ||
223 | static unsigned cache_reqno = 0x80000000; /* Start value is for debugging. */ | |
224 | ||
225 | #if 0 /* experimental */ | |
226 | /* FR400 has single prefetch. */ | |
227 | static void | |
228 | fr400_simulate_insn_prefetch (SIM_CPU *current_cpu, IADDR vpc) | |
229 | { | |
230 | int cur_ix; | |
231 | FRV_CACHE *cache; | |
232 | ||
233 | /* The cpu receives 8 bytes worth of insn data for each fetch aligned | |
234 | on 8 byte boundary. */ | |
235 | #define FR400_FETCH_SIZE 8 | |
236 | ||
237 | cur_ix = LS; | |
238 | vpc &= ~(FR400_FETCH_SIZE - 1); | |
239 | cache = CPU_INSN_CACHE (current_cpu); | |
240 | ||
241 | /* Request a load of the current address buffer, if necessary. */ | |
242 | if (frv_insn_fetch_buffer[cur_ix].address != vpc) | |
243 | { | |
244 | frv_insn_fetch_buffer[cur_ix].address = vpc; | |
245 | frv_insn_fetch_buffer[cur_ix].reqno = cache_reqno++; | |
246 | if (FRV_COUNT_CYCLES (current_cpu, 1)) | |
247 | frv_cache_request_load (cache, frv_insn_fetch_buffer[cur_ix].reqno, | |
248 | frv_insn_fetch_buffer[cur_ix].address, | |
249 | UNIT_I0 + cur_ix); | |
250 | } | |
251 | ||
252 | /* Wait for the current address buffer to be loaded, if necessary. */ | |
253 | if (FRV_COUNT_CYCLES (current_cpu, 1)) | |
254 | { | |
255 | FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu); | |
256 | int wait; | |
257 | ||
258 | /* Account for any branch penalty. */ | |
259 | if (ps->branch_penalty > 0 && ! ps->past_first_p) | |
260 | { | |
261 | frv_model_advance_cycles (current_cpu, ps->branch_penalty); | |
262 | frv_model_trace_wait_cycles (current_cpu, ps->branch_penalty, | |
263 | "Branch penalty:"); | |
264 | ps->branch_penalty = 0; | |
265 | } | |
266 | ||
267 | /* Account for insn fetch latency. */ | |
268 | wait = 0; | |
269 | while (frv_insn_fetch_buffer[cur_ix].reqno != NO_REQNO) | |
270 | { | |
271 | frv_model_advance_cycles (current_cpu, 1); | |
272 | ++wait; | |
273 | } | |
274 | frv_model_trace_wait_cycles (current_cpu, wait, "Insn fetch:"); | |
275 | return; | |
276 | } | |
277 | ||
278 | /* Otherwise just load the insns directly from the cache. | |
279 | */ | |
280 | if (frv_insn_fetch_buffer[cur_ix].reqno != NO_REQNO) | |
281 | { | |
282 | frv_cache_read (cache, cur_ix, vpc); | |
283 | frv_insn_fetch_buffer[cur_ix].reqno = NO_REQNO; | |
284 | } | |
285 | } | |
286 | #endif /* experimental */ | |
287 | ||
288 | /* FR500 has dual prefetch. */ | |
289 | static void | |
290 | simulate_dual_insn_prefetch (SIM_CPU *current_cpu, IADDR vpc, int fetch_size) | |
291 | { | |
292 | int i; | |
293 | int cur_ix, pre_ix; | |
294 | SI pre_address; | |
295 | FRV_CACHE *cache; | |
296 | ||
297 | /* See if the pc is within the addresses specified by either of the | |
298 | fetch buffers. If so, that will be the current buffer. Otherwise, | |
299 | arbitrarily select the LD buffer as the current one since it gets | |
300 | priority in the case of interfering load requests. */ | |
301 | cur_ix = LD; | |
302 | vpc &= ~(fetch_size - 1); | |
303 | for (i = LS; i < FRV_CACHE_PIPELINES; ++i) | |
304 | { | |
305 | if (frv_insn_fetch_buffer[i].address == vpc) | |
306 | { | |
307 | cur_ix = i; | |
308 | break; | |
309 | } | |
310 | } | |
311 | cache = CPU_INSN_CACHE (current_cpu); | |
312 | ||
313 | /* Request a load of the current address buffer, if necessary. */ | |
314 | if (frv_insn_fetch_buffer[cur_ix].address != vpc) | |
315 | { | |
316 | frv_insn_fetch_buffer[cur_ix].address = vpc; | |
317 | frv_insn_fetch_buffer[cur_ix].reqno = cache_reqno++; | |
318 | if (FRV_COUNT_CYCLES (current_cpu, 1)) | |
319 | frv_cache_request_load (cache, frv_insn_fetch_buffer[cur_ix].reqno, | |
320 | frv_insn_fetch_buffer[cur_ix].address, | |
321 | UNIT_I0 + cur_ix); | |
322 | } | |
323 | ||
324 | /* If the prefetch buffer does not represent the next sequential address, then | |
325 | request a load of the next sequential address. */ | |
326 | pre_ix = (cur_ix + 1) % FRV_CACHE_PIPELINES; | |
327 | pre_address = vpc + fetch_size; | |
328 | if (frv_insn_fetch_buffer[pre_ix].address != pre_address) | |
329 | { | |
330 | frv_insn_fetch_buffer[pre_ix].address = pre_address; | |
331 | frv_insn_fetch_buffer[pre_ix].reqno = cache_reqno++; | |
332 | if (FRV_COUNT_CYCLES (current_cpu, 1)) | |
333 | frv_cache_request_load (cache, frv_insn_fetch_buffer[pre_ix].reqno, | |
334 | frv_insn_fetch_buffer[pre_ix].address, | |
335 | UNIT_I0 + pre_ix); | |
336 | } | |
337 | ||
338 | /* If counting cycles, account for any branch penalty and/or insn fetch | |
339 | latency here. */ | |
340 | if (FRV_COUNT_CYCLES (current_cpu, 1)) | |
341 | { | |
342 | FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu); | |
343 | int wait; | |
344 | ||
345 | /* Account for any branch penalty. */ | |
346 | if (ps->branch_penalty > 0 && ! ps->past_first_p) | |
347 | { | |
348 | frv_model_advance_cycles (current_cpu, ps->branch_penalty); | |
349 | frv_model_trace_wait_cycles (current_cpu, ps->branch_penalty, | |
350 | "Branch penalty:"); | |
351 | ps->branch_penalty = 0; | |
352 | } | |
353 | ||
354 | /* Account for insn fetch latency. */ | |
355 | wait = 0; | |
356 | while (frv_insn_fetch_buffer[cur_ix].reqno != NO_REQNO) | |
357 | { | |
358 | frv_model_advance_cycles (current_cpu, 1); | |
359 | ++wait; | |
360 | } | |
361 | frv_model_trace_wait_cycles (current_cpu, wait, "Insn fetch:"); | |
362 | return; | |
363 | } | |
364 | ||
365 | /* Otherwise just load the insns directly from the cache. | |
366 | */ | |
367 | if (frv_insn_fetch_buffer[cur_ix].reqno != NO_REQNO) | |
368 | { | |
369 | frv_cache_read (cache, cur_ix, vpc); | |
370 | frv_insn_fetch_buffer[cur_ix].reqno = NO_REQNO; | |
371 | } | |
372 | if (frv_insn_fetch_buffer[pre_ix].reqno != NO_REQNO) | |
373 | { | |
374 | frv_cache_read (cache, pre_ix, pre_address); | |
375 | frv_insn_fetch_buffer[pre_ix].reqno = NO_REQNO; | |
376 | } | |
377 | } | |
378 | ||
379 | static void | |
380 | @cpu@_simulate_insn_prefetch (SIM_CPU *current_cpu, IADDR vpc) | |
381 | { | |
382 | SI hsr0; | |
383 | SIM_DESC sd; | |
384 | ||
385 | /* Nothing to do if not counting cycles and the cache is not enabled. */ | |
386 | hsr0 = GET_HSR0 (); | |
387 | if (! GET_HSR0_ICE (hsr0) && ! FRV_COUNT_CYCLES (current_cpu, 1)) | |
388 | return; | |
389 | ||
390 | /* Different machines handle prefetch defferently. */ | |
391 | sd = CPU_STATE (current_cpu); | |
392 | switch (STATE_ARCHITECTURE (sd)->mach) | |
393 | { | |
394 | case bfd_mach_fr400: | |
676a64f4 | 395 | case bfd_mach_fr450: |
b34f6357 DB |
396 | simulate_dual_insn_prefetch (current_cpu, vpc, 8); |
397 | break; | |
398 | case bfd_mach_frvtomcat: | |
399 | case bfd_mach_fr500: | |
e930b1f5 | 400 | case bfd_mach_fr550: |
b34f6357 DB |
401 | case bfd_mach_frv: |
402 | simulate_dual_insn_prefetch (current_cpu, vpc, 16); | |
403 | break; | |
404 | default: | |
405 | break; | |
406 | } | |
407 | } | |
408 | ||
409 | int frv_save_profile_model_p; | |
410 | EOF | |
411 | ||
412 | ;; | |
413 | ||
414 | xinit) | |
415 | ||
416 | cat <<EOF | |
417 | /*xxxinit*/ | |
418 | /* If the timer is enabled, then we will enable model profiling during | |
419 | execution. This is because the timer needs accurate cycles counts to | |
420 | work properly. Save the original setting of model profiling. */ | |
421 | if (frv_interrupt_state.timer.enabled) | |
422 | frv_save_profile_model_p = PROFILE_MODEL_P (current_cpu); | |
423 | EOF | |
424 | ||
425 | ;; | |
426 | ||
427 | xextract-simple | xextract-scache) | |
428 | ||
429 | # Inputs: current_cpu, vpc, sc, FAST_P | |
430 | # Outputs: sc filled in | |
431 | # SET_LAST_INSN_P(last_p) called to indicate whether insn is last one | |
432 | ||
433 | cat <<EOF | |
434 | { | |
435 | CGEN_INSN_INT insn = frvbf_read_imem_USI (current_cpu, vpc); | |
436 | extract (current_cpu, vpc, insn, SEM_ARGBUF (sc), FAST_P); | |
437 | SET_LAST_INSN_P ((insn & 0x80000000) != 0); | |
438 | } | |
439 | EOF | |
440 | ||
441 | ;; | |
442 | ||
443 | xfull-exec-* | xfast-exec-*) | |
444 | ||
445 | # Inputs: current_cpu, vpc, FAST_P | |
446 | # Outputs: | |
447 | # vpc contains the address of the next insn to execute | |
448 | # pc of current_cpu must be up to date (=vpc) upon exit | |
449 | # CPU_INSN_COUNT (current_cpu) must be updated by number of insns executed | |
450 | # | |
451 | # Unlike the non-parallel case, this version is responsible for doing the | |
452 | # scache lookup. | |
453 | ||
454 | cat <<EOF | |
455 | { | |
456 | FRV_VLIW *vliw; | |
457 | int first_insn_p = 1; | |
458 | int last_insn_p = 0; | |
459 | int ninsns; | |
79e59fe6 | 460 | CGEN_ATTR_VALUE_ENUM_TYPE slot; |
b34f6357 DB |
461 | |
462 | /* If the timer is enabled, then enable model profiling. This is because | |
463 | the timer needs accurate cycles counts to work properly. */ | |
464 | if (frv_interrupt_state.timer.enabled && ! frv_save_profile_model_p) | |
465 | sim_profile_set_option (current_state, "-model", PROFILE_MODEL_IDX, "1"); | |
466 | ||
467 | /* Init parallel-write queue and vliw. */ | |
468 | @cpu@_parallel_write_init (current_cpu); | |
469 | vliw = CPU_VLIW (current_cpu); | |
470 | frv_vliw_reset (vliw, STATE_ARCHITECTURE (CPU_STATE (current_cpu))->mach, | |
471 | CPU_ELF_FLAGS (current_cpu)); | |
e930b1f5 | 472 | frv_current_fm_slot = UNIT_NIL; |
b34f6357 DB |
473 | |
474 | for (ninsns = 0; ! last_insn_p && ninsns < FRV_VLIW_SIZE; ++ninsns) | |
475 | { | |
476 | SCACHE *sc; | |
477 | const CGEN_INSN *insn; | |
478 | int error; | |
479 | /* Go through the motions of finding the insns in the cache. */ | |
480 | @cpu@_simulate_insn_prefetch (current_cpu, vpc); | |
481 | ||
482 | sc = @cpu@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P); | |
483 | sc->first_insn_p = first_insn_p; | |
484 | last_insn_p = sc->last_insn_p; | |
485 | ||
486 | /* Add the insn to the vliw and set up the interrupt state. */ | |
487 | insn = sc->argbuf.idesc->idata; | |
488 | error = frv_vliw_add_insn (vliw, insn); | |
489 | if (! error) | |
490 | frv_vliw_setup_insn (current_cpu, insn); | |
491 | frv_detect_insn_access_interrupts (current_cpu, sc); | |
e930b1f5 DB |
492 | slot = (*vliw->current_vliw)[vliw->next_slot - 1]; |
493 | if (slot >= UNIT_FM0 && slot <= UNIT_FM3) | |
494 | frv_current_fm_slot = slot; | |
b34f6357 DB |
495 | |
496 | vpc = execute (current_cpu, sc, FAST_P); | |
497 | ||
498 | SET_H_PC (vpc); /* needed for interrupt handling */ | |
499 | first_insn_p = 0; | |
500 | } | |
501 | ||
502 | /* If the timer is enabled, and model profiling was not originally enabled, | |
503 | then turn it off again. This is the only place we can currently gain | |
504 | control to do this. */ | |
505 | if (frv_interrupt_state.timer.enabled && ! frv_save_profile_model_p) | |
506 | sim_profile_set_option (current_state, "-model", PROFILE_MODEL_IDX, "0"); | |
507 | ||
508 | /* Check for interrupts. Also handles writeback if necessary. */ | |
509 | frv_process_interrupts (current_cpu); | |
510 | ||
511 | CPU_INSN_COUNT (current_cpu) += ninsns; | |
512 | } | |
513 | EOF | |
514 | ||
515 | ;; | |
516 | ||
517 | *) | |
518 | echo "Invalid argument to mainloop.in: $1" >&2 | |
519 | exit 1 | |
520 | ;; | |
521 | ||
522 | esac |