166e63ce3Schristos# Simulator main loop for frv. -*- C -*- 2*1424dfb3Schristos# Copyright (C) 1998-2020 Free Software Foundation, Inc. 366e63ce3Schristos# Contributed by Red Hat. 466e63ce3Schristos# 566e63ce3Schristos# This file is part of the GNU Simulators. 666e63ce3Schristos# 766e63ce3Schristos# This program is free software; you can redistribute it and/or modify 866e63ce3Schristos# it under the terms of the GNU General Public License as published by 966e63ce3Schristos# the Free Software Foundation; either version 3 of the License, or 1066e63ce3Schristos# (at your option) any later version. 1166e63ce3Schristos# 1266e63ce3Schristos# This program is distributed in the hope that it will be useful, 1366e63ce3Schristos# but WITHOUT ANY WARRANTY; without even the implied warranty of 1466e63ce3Schristos# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1566e63ce3Schristos# GNU General Public License for more details. 1666e63ce3Schristos# 1766e63ce3Schristos# You should have received a copy of the GNU General Public License 1866e63ce3Schristos# along with this program. If not, see <http://www.gnu.org/licenses/>. 1966e63ce3Schristos 2066e63ce3Schristos# Syntax: 2166e63ce3Schristos# /bin/sh mainloop.in command 2266e63ce3Schristos# 2366e63ce3Schristos# Command is one of: 2466e63ce3Schristos# 2566e63ce3Schristos# init 2666e63ce3Schristos# support 2766e63ce3Schristos# extract-{simple,scache,pbb} 2866e63ce3Schristos# {full,fast}-exec-{simple,scache,pbb} 2966e63ce3Schristos# 3066e63ce3Schristos# A target need only provide a "full" version of one of simple,scache,pbb. 3166e63ce3Schristos# If the target wants it can also provide a fast version of same. 3266e63ce3Schristos# It can't provide more than this. 3366e63ce3Schristos 3466e63ce3Schristos# ??? After a few more ports are done, revisit. 3566e63ce3Schristos# Will eventually need to machine generate a lot of this. 3666e63ce3Schristos 3766e63ce3Schristoscase "x$1" in 3866e63ce3Schristos 3966e63ce3Schristosxsupport) 4066e63ce3Schristos 4166e63ce3Schristoscat <<EOF 4266e63ce3Schristos 4366e63ce3Schristosstatic INLINE const IDESC * 4466e63ce3Schristosextract (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, ARGBUF *abuf, 4566e63ce3Schristos int fast_p) 4666e63ce3Schristos{ 4766e63ce3Schristos const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf); 4866e63ce3Schristos @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p); 4966e63ce3Schristos if (! fast_p) 5066e63ce3Schristos { 5166e63ce3Schristos int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc); 5266e63ce3Schristos int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc); 5366e63ce3Schristos @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p); 5466e63ce3Schristos } 5566e63ce3Schristos return id; 5666e63ce3Schristos} 5766e63ce3Schristos 5866e63ce3Schristosstatic INLINE SEM_PC 5966e63ce3Schristosexecute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p) 6066e63ce3Schristos{ 6166e63ce3Schristos SEM_PC vpc; 6266e63ce3Schristos 6366e63ce3Schristos /* Force gr0 to zero before every insn. */ 6466e63ce3Schristos @cpu@_h_gr_set (current_cpu, 0, 0); 6566e63ce3Schristos 6666e63ce3Schristos if (fast_p) 6766e63ce3Schristos { 6866e63ce3Schristos vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc); 6966e63ce3Schristos } 7066e63ce3Schristos else 7166e63ce3Schristos { 7266e63ce3Schristos ARGBUF *abuf = &sc->argbuf; 7366e63ce3Schristos const IDESC *idesc = abuf->idesc; 7466e63ce3Schristos#if WITH_SCACHE_PBB 7566e63ce3Schristos int virtual_p = CGEN_ATTR_VALUE (NULL, idesc->attrs, CGEN_INSN_VIRTUAL); 7666e63ce3Schristos#else 7766e63ce3Schristos int virtual_p = 0; 7866e63ce3Schristos#endif 7966e63ce3Schristos 8066e63ce3Schristos if (! virtual_p) 8166e63ce3Schristos { 8266e63ce3Schristos /* FIXME: call x-before */ 8366e63ce3Schristos if (ARGBUF_PROFILE_P (abuf)) 8466e63ce3Schristos PROFILE_COUNT_INSN (current_cpu, abuf->addr, idesc->num); 8566e63ce3Schristos /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */ 8666e63ce3Schristos if (FRV_COUNT_CYCLES (current_cpu, ARGBUF_PROFILE_P (abuf))) 8766e63ce3Schristos { 8866e63ce3Schristos @cpu@_model_insn_before (current_cpu, sc->first_insn_p); 8966e63ce3Schristos model_insn = FRV_INSN_MODEL_PASS_1; 9066e63ce3Schristos if (idesc->timing->model_fn != NULL) 9166e63ce3Schristos (*idesc->timing->model_fn) (current_cpu, sc); 9266e63ce3Schristos } 9366e63ce3Schristos else 9466e63ce3Schristos model_insn = FRV_INSN_NO_MODELING; 95ed6a76a9Schristos CGEN_TRACE_INSN_INIT (current_cpu, abuf, 1); 96ed6a76a9Schristos CGEN_TRACE_INSN (current_cpu, idesc->idata, 9766e63ce3Schristos (const struct argbuf *) abuf, abuf->addr); 9866e63ce3Schristos } 9966e63ce3Schristos#if WITH_SCACHE 10066e63ce3Schristos vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc); 10166e63ce3Schristos#else 10266e63ce3Schristos vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, abuf); 10366e63ce3Schristos#endif 10466e63ce3Schristos if (! virtual_p) 10566e63ce3Schristos { 10666e63ce3Schristos /* FIXME: call x-after */ 10766e63ce3Schristos if (FRV_COUNT_CYCLES (current_cpu, ARGBUF_PROFILE_P (abuf))) 10866e63ce3Schristos { 10966e63ce3Schristos int cycles; 11066e63ce3Schristos if (idesc->timing->model_fn != NULL) 11166e63ce3Schristos { 11266e63ce3Schristos model_insn = FRV_INSN_MODEL_PASS_2; 11366e63ce3Schristos cycles = (*idesc->timing->model_fn) (current_cpu, sc); 11466e63ce3Schristos } 11566e63ce3Schristos else 11666e63ce3Schristos cycles = 1; 11766e63ce3Schristos @cpu@_model_insn_after (current_cpu, sc->last_insn_p, cycles); 11866e63ce3Schristos } 119ed6a76a9Schristos CGEN_TRACE_INSN_FINI (current_cpu, abuf, 1); 12066e63ce3Schristos } 12166e63ce3Schristos } 12266e63ce3Schristos 12366e63ce3Schristos return vpc; 12466e63ce3Schristos} 12566e63ce3Schristos 12666e63ce3Schristosstatic void 12766e63ce3Schristos@cpu@_parallel_write_init (SIM_CPU *current_cpu) 12866e63ce3Schristos{ 12966e63ce3Schristos CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu); 13066e63ce3Schristos CGEN_WRITE_QUEUE_CLEAR (q); 13166e63ce3Schristos previous_vliw_pc = CPU_PC_GET(current_cpu); 13266e63ce3Schristos frv_interrupt_state.f_ne_flags[0] = 0; 13366e63ce3Schristos frv_interrupt_state.f_ne_flags[1] = 0; 13466e63ce3Schristos frv_interrupt_state.imprecise_interrupt = NULL; 13566e63ce3Schristos} 13666e63ce3Schristos 13766e63ce3Schristosstatic void 13866e63ce3Schristos@cpu@_parallel_write_queued (SIM_CPU *current_cpu) 13966e63ce3Schristos{ 14066e63ce3Schristos int i; 14166e63ce3Schristos 14266e63ce3Schristos FRV_VLIW *vliw = CPU_VLIW (current_cpu); 14366e63ce3Schristos CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu); 14466e63ce3Schristos 14566e63ce3Schristos /* Loop over the queued writes, executing them. Set the pc to the address 14666e63ce3Schristos of the insn which queued each write for the proper context in case an 14766e63ce3Schristos interrupt is caused. Restore the proper pc after the writes are 14866e63ce3Schristos completed. */ 14966e63ce3Schristos IADDR save_pc = CPU_PC_GET (current_cpu); 15066e63ce3Schristos IADDR new_pc = save_pc; 15166e63ce3Schristos int branch_taken = 0; 15266e63ce3Schristos int limit = CGEN_WRITE_QUEUE_INDEX (q); 15366e63ce3Schristos frv_interrupt_state.data_written.length = 0; 15466e63ce3Schristos 15566e63ce3Schristos for (i = 0; i < limit; ++i) 15666e63ce3Schristos { 15766e63ce3Schristos CGEN_WRITE_QUEUE_ELEMENT *item = CGEN_WRITE_QUEUE_ELEMENT (q, i); 15866e63ce3Schristos 15966e63ce3Schristos /* If an imprecise interrupt was generated, then, check whether the 16066e63ce3Schristos result should still be written. */ 16166e63ce3Schristos if (frv_interrupt_state.imprecise_interrupt != NULL) 16266e63ce3Schristos { 16366e63ce3Schristos /* Only check writes by the insn causing the exception. */ 16466e63ce3Schristos if (CGEN_WRITE_QUEUE_ELEMENT_IADDR (item) 16566e63ce3Schristos == frv_interrupt_state.imprecise_interrupt->vpc) 16666e63ce3Schristos { 16766e63ce3Schristos /* Execute writes of floating point operations resulting in 16866e63ce3Schristos overflow, underflow or inexact. */ 16966e63ce3Schristos if (frv_interrupt_state.imprecise_interrupt->kind 17066e63ce3Schristos == FRV_FP_EXCEPTION) 17166e63ce3Schristos { 17266e63ce3Schristos if ((frv_interrupt_state.imprecise_interrupt 17366e63ce3Schristos ->u.fp_info.fsr_mask 17466e63ce3Schristos & ~(FSR_INEXACT | FSR_OVERFLOW | FSR_UNDERFLOW))) 17566e63ce3Schristos continue; /* Don't execute */ 17666e63ce3Schristos } 17766e63ce3Schristos /* Execute writes marked as 'forced'. */ 17866e63ce3Schristos else if (! (CGEN_WRITE_QUEUE_ELEMENT_FLAGS (item) 17966e63ce3Schristos & FRV_WRITE_QUEUE_FORCE_WRITE)) 18066e63ce3Schristos continue; /* Don't execute */ 18166e63ce3Schristos } 18266e63ce3Schristos } 18366e63ce3Schristos 18466e63ce3Schristos /* Only execute the first branch on the queue. */ 18566e63ce3Schristos if (CGEN_WRITE_QUEUE_ELEMENT_KIND (item) == CGEN_PC_WRITE 18666e63ce3Schristos || CGEN_WRITE_QUEUE_ELEMENT_KIND (item) == CGEN_FN_PC_WRITE) 18766e63ce3Schristos { 18866e63ce3Schristos if (branch_taken) 18966e63ce3Schristos continue; 19066e63ce3Schristos branch_taken = 1; 19166e63ce3Schristos if (CGEN_WRITE_QUEUE_ELEMENT_KIND (item) == CGEN_PC_WRITE) 19266e63ce3Schristos new_pc = item->kinds.pc_write.value; 19366e63ce3Schristos else 19466e63ce3Schristos new_pc = item->kinds.fn_pc_write.value; 19566e63ce3Schristos } 19666e63ce3Schristos 19766e63ce3Schristos CPU_PC_SET (current_cpu, CGEN_WRITE_QUEUE_ELEMENT_IADDR (item)); 19866e63ce3Schristos frv_save_data_written_for_interrupts (current_cpu, item); 19966e63ce3Schristos cgen_write_queue_element_execute (current_cpu, item); 20066e63ce3Schristos } 20166e63ce3Schristos 20266e63ce3Schristos /* Update the LR with the address of the next insn if the flag is set. 20366e63ce3Schristos This flag gets set in frvbf_set_write_next_vliw_to_LR by the JMPL, 20466e63ce3Schristos JMPIL and CALL insns. */ 20566e63ce3Schristos if (frvbf_write_next_vliw_addr_to_LR) 20666e63ce3Schristos { 20766e63ce3Schristos frvbf_h_spr_set_handler (current_cpu, H_SPR_LR, save_pc); 20866e63ce3Schristos frvbf_write_next_vliw_addr_to_LR = 0; 20966e63ce3Schristos } 21066e63ce3Schristos 21166e63ce3Schristos CPU_PC_SET (current_cpu, new_pc); 21266e63ce3Schristos CGEN_WRITE_QUEUE_CLEAR (q); 21366e63ce3Schristos} 21466e63ce3Schristos 21566e63ce3Schristosvoid 21666e63ce3Schristos@cpu@_perform_writeback (SIM_CPU *current_cpu) 21766e63ce3Schristos{ 21866e63ce3Schristos @cpu@_parallel_write_queued (current_cpu); 21966e63ce3Schristos} 22066e63ce3Schristos 22166e63ce3Schristosstatic unsigned cache_reqno = 0x80000000; /* Start value is for debugging. */ 22266e63ce3Schristos 22366e63ce3Schristos#if 0 /* experimental */ 22466e63ce3Schristos/* FR400 has single prefetch. */ 22566e63ce3Schristosstatic void 22666e63ce3Schristosfr400_simulate_insn_prefetch (SIM_CPU *current_cpu, IADDR vpc) 22766e63ce3Schristos{ 22866e63ce3Schristos int cur_ix; 22966e63ce3Schristos FRV_CACHE *cache; 23066e63ce3Schristos 23166e63ce3Schristos/* The cpu receives 8 bytes worth of insn data for each fetch aligned 23266e63ce3Schristos on 8 byte boundary. */ 23366e63ce3Schristos#define FR400_FETCH_SIZE 8 23466e63ce3Schristos 23566e63ce3Schristos cur_ix = LS; 23666e63ce3Schristos vpc &= ~(FR400_FETCH_SIZE - 1); 23766e63ce3Schristos cache = CPU_INSN_CACHE (current_cpu); 23866e63ce3Schristos 23966e63ce3Schristos /* Request a load of the current address buffer, if necessary. */ 24066e63ce3Schristos if (frv_insn_fetch_buffer[cur_ix].address != vpc) 24166e63ce3Schristos { 24266e63ce3Schristos frv_insn_fetch_buffer[cur_ix].address = vpc; 24366e63ce3Schristos frv_insn_fetch_buffer[cur_ix].reqno = cache_reqno++; 24466e63ce3Schristos if (FRV_COUNT_CYCLES (current_cpu, 1)) 24566e63ce3Schristos frv_cache_request_load (cache, frv_insn_fetch_buffer[cur_ix].reqno, 24666e63ce3Schristos frv_insn_fetch_buffer[cur_ix].address, 24766e63ce3Schristos UNIT_I0 + cur_ix); 24866e63ce3Schristos } 24966e63ce3Schristos 25066e63ce3Schristos /* Wait for the current address buffer to be loaded, if necessary. */ 25166e63ce3Schristos if (FRV_COUNT_CYCLES (current_cpu, 1)) 25266e63ce3Schristos { 25366e63ce3Schristos FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu); 25466e63ce3Schristos int wait; 25566e63ce3Schristos 25666e63ce3Schristos /* Account for any branch penalty. */ 25766e63ce3Schristos if (ps->branch_penalty > 0 && ! ps->past_first_p) 25866e63ce3Schristos { 25966e63ce3Schristos frv_model_advance_cycles (current_cpu, ps->branch_penalty); 26066e63ce3Schristos frv_model_trace_wait_cycles (current_cpu, ps->branch_penalty, 26166e63ce3Schristos "Branch penalty:"); 26266e63ce3Schristos ps->branch_penalty = 0; 26366e63ce3Schristos } 26466e63ce3Schristos 26566e63ce3Schristos /* Account for insn fetch latency. */ 26666e63ce3Schristos wait = 0; 26766e63ce3Schristos while (frv_insn_fetch_buffer[cur_ix].reqno != NO_REQNO) 26866e63ce3Schristos { 26966e63ce3Schristos frv_model_advance_cycles (current_cpu, 1); 27066e63ce3Schristos ++wait; 27166e63ce3Schristos } 27266e63ce3Schristos frv_model_trace_wait_cycles (current_cpu, wait, "Insn fetch:"); 27366e63ce3Schristos return; 27466e63ce3Schristos } 27566e63ce3Schristos 27666e63ce3Schristos /* Otherwise just load the insns directly from the cache. 27766e63ce3Schristos */ 27866e63ce3Schristos if (frv_insn_fetch_buffer[cur_ix].reqno != NO_REQNO) 27966e63ce3Schristos { 28066e63ce3Schristos frv_cache_read (cache, cur_ix, vpc); 28166e63ce3Schristos frv_insn_fetch_buffer[cur_ix].reqno = NO_REQNO; 28266e63ce3Schristos } 28366e63ce3Schristos} 28466e63ce3Schristos#endif /* experimental */ 28566e63ce3Schristos 28666e63ce3Schristos/* FR500 has dual prefetch. */ 28766e63ce3Schristosstatic void 28866e63ce3Schristossimulate_dual_insn_prefetch (SIM_CPU *current_cpu, IADDR vpc, int fetch_size) 28966e63ce3Schristos{ 29066e63ce3Schristos int i; 29166e63ce3Schristos int cur_ix, pre_ix; 29266e63ce3Schristos SI pre_address; 29366e63ce3Schristos FRV_CACHE *cache; 29466e63ce3Schristos 29566e63ce3Schristos /* See if the pc is within the addresses specified by either of the 29666e63ce3Schristos fetch buffers. If so, that will be the current buffer. Otherwise, 29766e63ce3Schristos arbitrarily select the LD buffer as the current one since it gets 29866e63ce3Schristos priority in the case of interfering load requests. */ 29966e63ce3Schristos cur_ix = LD; 30066e63ce3Schristos vpc &= ~(fetch_size - 1); 30166e63ce3Schristos for (i = LS; i < FRV_CACHE_PIPELINES; ++i) 30266e63ce3Schristos { 30366e63ce3Schristos if (frv_insn_fetch_buffer[i].address == vpc) 30466e63ce3Schristos { 30566e63ce3Schristos cur_ix = i; 30666e63ce3Schristos break; 30766e63ce3Schristos } 30866e63ce3Schristos } 30966e63ce3Schristos cache = CPU_INSN_CACHE (current_cpu); 31066e63ce3Schristos 31166e63ce3Schristos /* Request a load of the current address buffer, if necessary. */ 31266e63ce3Schristos if (frv_insn_fetch_buffer[cur_ix].address != vpc) 31366e63ce3Schristos { 31466e63ce3Schristos frv_insn_fetch_buffer[cur_ix].address = vpc; 31566e63ce3Schristos frv_insn_fetch_buffer[cur_ix].reqno = cache_reqno++; 31666e63ce3Schristos if (FRV_COUNT_CYCLES (current_cpu, 1)) 31766e63ce3Schristos frv_cache_request_load (cache, frv_insn_fetch_buffer[cur_ix].reqno, 31866e63ce3Schristos frv_insn_fetch_buffer[cur_ix].address, 31966e63ce3Schristos UNIT_I0 + cur_ix); 32066e63ce3Schristos } 32166e63ce3Schristos 32266e63ce3Schristos /* If the prefetch buffer does not represent the next sequential address, then 32366e63ce3Schristos request a load of the next sequential address. */ 32466e63ce3Schristos pre_ix = (cur_ix + 1) % FRV_CACHE_PIPELINES; 32566e63ce3Schristos pre_address = vpc + fetch_size; 32666e63ce3Schristos if (frv_insn_fetch_buffer[pre_ix].address != pre_address) 32766e63ce3Schristos { 32866e63ce3Schristos frv_insn_fetch_buffer[pre_ix].address = pre_address; 32966e63ce3Schristos frv_insn_fetch_buffer[pre_ix].reqno = cache_reqno++; 33066e63ce3Schristos if (FRV_COUNT_CYCLES (current_cpu, 1)) 33166e63ce3Schristos frv_cache_request_load (cache, frv_insn_fetch_buffer[pre_ix].reqno, 33266e63ce3Schristos frv_insn_fetch_buffer[pre_ix].address, 33366e63ce3Schristos UNIT_I0 + pre_ix); 33466e63ce3Schristos } 33566e63ce3Schristos 33666e63ce3Schristos /* If counting cycles, account for any branch penalty and/or insn fetch 33766e63ce3Schristos latency here. */ 33866e63ce3Schristos if (FRV_COUNT_CYCLES (current_cpu, 1)) 33966e63ce3Schristos { 34066e63ce3Schristos FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu); 34166e63ce3Schristos int wait; 34266e63ce3Schristos 34366e63ce3Schristos /* Account for any branch penalty. */ 34466e63ce3Schristos if (ps->branch_penalty > 0 && ! ps->past_first_p) 34566e63ce3Schristos { 34666e63ce3Schristos frv_model_advance_cycles (current_cpu, ps->branch_penalty); 34766e63ce3Schristos frv_model_trace_wait_cycles (current_cpu, ps->branch_penalty, 34866e63ce3Schristos "Branch penalty:"); 34966e63ce3Schristos ps->branch_penalty = 0; 35066e63ce3Schristos } 35166e63ce3Schristos 35266e63ce3Schristos /* Account for insn fetch latency. */ 35366e63ce3Schristos wait = 0; 35466e63ce3Schristos while (frv_insn_fetch_buffer[cur_ix].reqno != NO_REQNO) 35566e63ce3Schristos { 35666e63ce3Schristos frv_model_advance_cycles (current_cpu, 1); 35766e63ce3Schristos ++wait; 35866e63ce3Schristos } 35966e63ce3Schristos frv_model_trace_wait_cycles (current_cpu, wait, "Insn fetch:"); 36066e63ce3Schristos return; 36166e63ce3Schristos } 36266e63ce3Schristos 36366e63ce3Schristos /* Otherwise just load the insns directly from the cache. 36466e63ce3Schristos */ 36566e63ce3Schristos if (frv_insn_fetch_buffer[cur_ix].reqno != NO_REQNO) 36666e63ce3Schristos { 36766e63ce3Schristos frv_cache_read (cache, cur_ix, vpc); 36866e63ce3Schristos frv_insn_fetch_buffer[cur_ix].reqno = NO_REQNO; 36966e63ce3Schristos } 37066e63ce3Schristos if (frv_insn_fetch_buffer[pre_ix].reqno != NO_REQNO) 37166e63ce3Schristos { 37266e63ce3Schristos frv_cache_read (cache, pre_ix, pre_address); 37366e63ce3Schristos frv_insn_fetch_buffer[pre_ix].reqno = NO_REQNO; 37466e63ce3Schristos } 37566e63ce3Schristos} 37666e63ce3Schristos 37766e63ce3Schristosstatic void 37866e63ce3Schristos@cpu@_simulate_insn_prefetch (SIM_CPU *current_cpu, IADDR vpc) 37966e63ce3Schristos{ 38066e63ce3Schristos SI hsr0; 38166e63ce3Schristos SIM_DESC sd; 38266e63ce3Schristos 38366e63ce3Schristos /* Nothing to do if not counting cycles and the cache is not enabled. */ 38466e63ce3Schristos hsr0 = GET_HSR0 (); 38566e63ce3Schristos if (! GET_HSR0_ICE (hsr0) && ! FRV_COUNT_CYCLES (current_cpu, 1)) 38666e63ce3Schristos return; 38766e63ce3Schristos 38866e63ce3Schristos /* Different machines handle prefetch defferently. */ 38966e63ce3Schristos sd = CPU_STATE (current_cpu); 39066e63ce3Schristos switch (STATE_ARCHITECTURE (sd)->mach) 39166e63ce3Schristos { 39266e63ce3Schristos case bfd_mach_fr400: 39366e63ce3Schristos case bfd_mach_fr450: 39466e63ce3Schristos simulate_dual_insn_prefetch (current_cpu, vpc, 8); 39566e63ce3Schristos break; 39666e63ce3Schristos case bfd_mach_frvtomcat: 39766e63ce3Schristos case bfd_mach_fr500: 39866e63ce3Schristos case bfd_mach_fr550: 39966e63ce3Schristos case bfd_mach_frv: 40066e63ce3Schristos simulate_dual_insn_prefetch (current_cpu, vpc, 16); 40166e63ce3Schristos break; 40266e63ce3Schristos default: 40366e63ce3Schristos break; 40466e63ce3Schristos } 40566e63ce3Schristos} 40666e63ce3Schristos 40766e63ce3Schristosint frv_save_profile_model_p; 40866e63ce3SchristosEOF 40966e63ce3Schristos 41066e63ce3Schristos;; 41166e63ce3Schristos 41266e63ce3Schristosxinit) 41366e63ce3Schristos 41466e63ce3Schristoscat <<EOF 41566e63ce3Schristos/*xxxinit*/ 41666e63ce3Schristos /* If the timer is enabled, then we will enable model profiling during 41766e63ce3Schristos execution. This is because the timer needs accurate cycles counts to 41866e63ce3Schristos work properly. Save the original setting of model profiling. */ 41966e63ce3Schristos if (frv_interrupt_state.timer.enabled) 42066e63ce3Schristos frv_save_profile_model_p = PROFILE_MODEL_P (current_cpu); 42166e63ce3SchristosEOF 42266e63ce3Schristos 42366e63ce3Schristos;; 42466e63ce3Schristos 42566e63ce3Schristosxextract-simple | xextract-scache) 42666e63ce3Schristos 42766e63ce3Schristos# Inputs: current_cpu, vpc, sc, FAST_P 42866e63ce3Schristos# Outputs: sc filled in 42966e63ce3Schristos# SET_LAST_INSN_P(last_p) called to indicate whether insn is last one 43066e63ce3Schristos 43166e63ce3Schristoscat <<EOF 43266e63ce3Schristos{ 43366e63ce3Schristos CGEN_INSN_INT insn = frvbf_read_imem_USI (current_cpu, vpc); 43466e63ce3Schristos extract (current_cpu, vpc, insn, SEM_ARGBUF (sc), FAST_P); 43566e63ce3Schristos SET_LAST_INSN_P ((insn & 0x80000000) != 0); 43666e63ce3Schristos} 43766e63ce3SchristosEOF 43866e63ce3Schristos 43966e63ce3Schristos;; 44066e63ce3Schristos 44166e63ce3Schristosxfull-exec-* | xfast-exec-*) 44266e63ce3Schristos 44366e63ce3Schristos# Inputs: current_cpu, vpc, FAST_P 44466e63ce3Schristos# Outputs: 44566e63ce3Schristos# vpc contains the address of the next insn to execute 44666e63ce3Schristos# pc of current_cpu must be up to date (=vpc) upon exit 44766e63ce3Schristos# CPU_INSN_COUNT (current_cpu) must be updated by number of insns executed 44866e63ce3Schristos# 44966e63ce3Schristos# Unlike the non-parallel case, this version is responsible for doing the 45066e63ce3Schristos# scache lookup. 45166e63ce3Schristos 45266e63ce3Schristoscat <<EOF 45366e63ce3Schristos{ 45466e63ce3Schristos FRV_VLIW *vliw; 45566e63ce3Schristos int first_insn_p = 1; 45666e63ce3Schristos int last_insn_p = 0; 45766e63ce3Schristos int ninsns; 45866e63ce3Schristos CGEN_ATTR_VALUE_ENUM_TYPE slot; 45966e63ce3Schristos 46066e63ce3Schristos /* If the timer is enabled, then enable model profiling. This is because 46166e63ce3Schristos the timer needs accurate cycles counts to work properly. */ 46266e63ce3Schristos if (frv_interrupt_state.timer.enabled && ! frv_save_profile_model_p) 46366e63ce3Schristos sim_profile_set_option (current_state, "-model", PROFILE_MODEL_IDX, "1"); 46466e63ce3Schristos 46566e63ce3Schristos /* Init parallel-write queue and vliw. */ 46666e63ce3Schristos @cpu@_parallel_write_init (current_cpu); 46766e63ce3Schristos vliw = CPU_VLIW (current_cpu); 46866e63ce3Schristos frv_vliw_reset (vliw, STATE_ARCHITECTURE (CPU_STATE (current_cpu))->mach, 46966e63ce3Schristos CPU_ELF_FLAGS (current_cpu)); 47066e63ce3Schristos frv_current_fm_slot = UNIT_NIL; 47166e63ce3Schristos 47266e63ce3Schristos for (ninsns = 0; ! last_insn_p && ninsns < FRV_VLIW_SIZE; ++ninsns) 47366e63ce3Schristos { 47466e63ce3Schristos SCACHE *sc; 47566e63ce3Schristos const CGEN_INSN *insn; 47666e63ce3Schristos int error; 47766e63ce3Schristos /* Go through the motions of finding the insns in the cache. */ 47866e63ce3Schristos @cpu@_simulate_insn_prefetch (current_cpu, vpc); 47966e63ce3Schristos 48066e63ce3Schristos sc = @cpu@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P); 48166e63ce3Schristos sc->first_insn_p = first_insn_p; 48266e63ce3Schristos last_insn_p = sc->last_insn_p; 48366e63ce3Schristos 48466e63ce3Schristos /* Add the insn to the vliw and set up the interrupt state. */ 48566e63ce3Schristos insn = sc->argbuf.idesc->idata; 48666e63ce3Schristos error = frv_vliw_add_insn (vliw, insn); 48766e63ce3Schristos if (! error) 48866e63ce3Schristos frv_vliw_setup_insn (current_cpu, insn); 48966e63ce3Schristos frv_detect_insn_access_interrupts (current_cpu, sc); 49066e63ce3Schristos slot = (*vliw->current_vliw)[vliw->next_slot - 1]; 49166e63ce3Schristos if (slot >= UNIT_FM0 && slot <= UNIT_FM3) 49266e63ce3Schristos frv_current_fm_slot = slot; 49366e63ce3Schristos 49466e63ce3Schristos vpc = execute (current_cpu, sc, FAST_P); 49566e63ce3Schristos 49666e63ce3Schristos SET_H_PC (vpc); /* needed for interrupt handling */ 49766e63ce3Schristos first_insn_p = 0; 49866e63ce3Schristos } 49966e63ce3Schristos 50066e63ce3Schristos /* If the timer is enabled, and model profiling was not originally enabled, 50166e63ce3Schristos then turn it off again. This is the only place we can currently gain 50266e63ce3Schristos control to do this. */ 50366e63ce3Schristos if (frv_interrupt_state.timer.enabled && ! frv_save_profile_model_p) 50466e63ce3Schristos sim_profile_set_option (current_state, "-model", PROFILE_MODEL_IDX, "0"); 50566e63ce3Schristos 50666e63ce3Schristos /* Check for interrupts. Also handles writeback if necessary. */ 50766e63ce3Schristos frv_process_interrupts (current_cpu); 50866e63ce3Schristos 50966e63ce3Schristos CPU_INSN_COUNT (current_cpu) += ninsns; 51066e63ce3Schristos} 51166e63ce3SchristosEOF 51266e63ce3Schristos 51366e63ce3Schristos;; 51466e63ce3Schristos 51566e63ce3Schristos*) 51666e63ce3Schristos echo "Invalid argument to mainloop.in: $1" >&2 51766e63ce3Schristos exit 1 51866e63ce3Schristos ;; 51966e63ce3Schristos 52066e63ce3Schristosesac 521