diff options
Diffstat (limited to 'sim/sh64/mloop-compact.c')
-rw-r--r-- | sim/sh64/mloop-compact.c | 635 |
1 files changed, 0 insertions, 635 deletions
diff --git a/sim/sh64/mloop-compact.c b/sim/sh64/mloop-compact.c deleted file mode 100644 index 16d6e63..0000000 --- a/sim/sh64/mloop-compact.c +++ /dev/null @@ -1,635 +0,0 @@ -/* This file is generated by the genmloop script. DO NOT EDIT! */ - -/* Enable switch() support in cgen headers. */ -#define SEM_IN_SWITCH - -#define WANT_CPU sh64 -#define WANT_CPU_SH64 - -#include "sim-main.h" -#include "bfd.h" -#include "cgen-mem.h" -#include "cgen-ops.h" -#include "sim-assert.h" - -/* Fill in the administrative ARGBUF fields required by all insns, - virtual and real. */ - -static INLINE void -sh64_compact_fill_argbuf (const SIM_CPU *cpu, ARGBUF *abuf, const IDESC *idesc, - PCADDR pc, int fast_p) -{ -#if WITH_SCACHE - SEM_SET_CODE (abuf, idesc, fast_p); - ARGBUF_ADDR (abuf) = pc; -#endif - ARGBUF_IDESC (abuf) = idesc; -} - -/* Fill in tracing/profiling fields of an ARGBUF. */ - -static INLINE void -sh64_compact_fill_argbuf_tp (const SIM_CPU *cpu, ARGBUF *abuf, - int trace_p, int profile_p) -{ - ARGBUF_TRACE_P (abuf) = trace_p; - ARGBUF_PROFILE_P (abuf) = profile_p; -} - -#if WITH_SCACHE_PBB - -/* Emit the "x-before" handler. - x-before is emitted before each insn (serial or parallel). - This is as opposed to x-after which is only emitted at the end of a group - of parallel insns. */ - -static INLINE void -sh64_compact_emit_before (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc, int first_p) -{ - ARGBUF *abuf = &sc[0].argbuf; - const IDESC *id = & CPU_IDESC (current_cpu) [SH64_COMPACT_INSN_X_BEFORE]; - - abuf->fields.before.first_p = first_p; - sh64_compact_fill_argbuf (current_cpu, abuf, id, pc, 0); - /* no need to set trace_p,profile_p */ -} - -/* Emit the "x-after" handler. - x-after is emitted after a serial insn or at the end of a group of - parallel insns. */ - -static INLINE void -sh64_compact_emit_after (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc) -{ - ARGBUF *abuf = &sc[0].argbuf; - const IDESC *id = & CPU_IDESC (current_cpu) [SH64_COMPACT_INSN_X_AFTER]; - - sh64_compact_fill_argbuf (current_cpu, abuf, id, pc, 0); - /* no need to set trace_p,profile_p */ -} - -#endif /* WITH_SCACHE_PBB */ - - -static INLINE const IDESC * -extract (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, ARGBUF *abuf, - int fast_p) -{ - const IDESC *id = sh64_compact_decode (current_cpu, pc, insn, insn, abuf); - - sh64_compact_fill_argbuf (current_cpu, abuf, id, pc, fast_p); - if (! fast_p) - { - int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc); - int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc); - sh64_compact_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p); - } - return id; -} - -static INLINE SEM_PC -execute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p) -{ - SEM_PC vpc; - - if (fast_p) - { -#if ! WITH_SEM_SWITCH_FAST -#if WITH_SCACHE - vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc); -#else - vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, &sc->argbuf); -#endif -#else - abort (); -#endif /* WITH_SEM_SWITCH_FAST */ - } - else - { -#if ! WITH_SEM_SWITCH_FULL - ARGBUF *abuf = &sc->argbuf; - const IDESC *idesc = abuf->idesc; -#if WITH_SCACHE_PBB - int virtual_p = CGEN_ATTR_VALUE (NULL, idesc->attrs, CGEN_INSN_VIRTUAL); -#else - int virtual_p = 0; -#endif - - if (! virtual_p) - { - /* FIXME: call x-before */ - if (ARGBUF_PROFILE_P (abuf)) - PROFILE_COUNT_INSN (current_cpu, abuf->addr, idesc->num); - /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */ - if (PROFILE_MODEL_P (current_cpu) - && ARGBUF_PROFILE_P (abuf)) - sh64_compact_model_insn_before (current_cpu, 1 /*first_p*/); - CGEN_TRACE_INSN_INIT (current_cpu, abuf, 1); - CGEN_TRACE_INSN (current_cpu, idesc->idata, - (const struct argbuf *) abuf, abuf->addr); - } -#if WITH_SCACHE - vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc); -#else - vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, abuf); -#endif - if (! virtual_p) - { - /* FIXME: call x-after */ - if (PROFILE_MODEL_P (current_cpu) - && ARGBUF_PROFILE_P (abuf)) - { - int cycles; - - cycles = (*idesc->timing->model_fn) (current_cpu, sc); - sh64_compact_model_insn_after (current_cpu, 1 /*last_p*/, cycles); - } - CGEN_TRACE_INSN_FINI (current_cpu, abuf, 1); - } -#else - abort (); -#endif /* WITH_SEM_SWITCH_FULL */ - } - - return vpc; -} - - -/* Record address of cti terminating a pbb. */ -#define SET_CTI_VPC(sc) do { _cti_sc = (sc); } while (0) -/* Record number of [real] insns in pbb. */ -#define SET_INSN_COUNT(n) do { _insn_count = (n); } while (0) - -/* Fetch and extract a pseudo-basic-block. - FAST_P is non-zero if no tracing/profiling/etc. is wanted. */ - -INLINE SEM_PC -sh64_compact_pbb_begin (SIM_CPU *current_cpu, int FAST_P) -{ - SEM_PC new_vpc; - PCADDR pc; - SCACHE *sc; - int max_insns = CPU_SCACHE_MAX_CHAIN_LENGTH (current_cpu); - - pc = GET_H_PC (); - - new_vpc = scache_lookup_or_alloc (current_cpu, pc, max_insns, &sc); - if (! new_vpc) - { - /* Leading '_' to avoid collision with mainloop.in. */ - int _insn_count = 0; - SCACHE *orig_sc = sc; - SCACHE *_cti_sc = NULL; - int slice_insns = CPU_MAX_SLICE_INSNS (current_cpu); - - /* First figure out how many instructions to compile. - MAX_INSNS is the size of the allocated buffer, which includes space - for before/after handlers if they're being used. - SLICE_INSNS is the maxinum number of real insns that can be - executed. Zero means "as many as we want". */ - /* ??? max_insns is serving two incompatible roles. - 1) Number of slots available in scache buffer. - 2) Number of real insns to execute. - They're incompatible because there are virtual insns emitted too - (chain,cti-chain,before,after handlers). */ - - if (slice_insns == 1) - { - /* No need to worry about extra slots required for virtual insns - and parallel exec support because MAX_CHAIN_LENGTH is - guaranteed to be big enough to execute at least 1 insn! */ - max_insns = 1; - } - else - { - /* Allow enough slop so that while compiling insns, if max_insns > 0 - then there's guaranteed to be enough space to emit one real insn. - MAX_CHAIN_LENGTH is typically much longer than - the normal number of insns between cti's anyway. */ - max_insns -= (1 /* one for the trailing chain insn */ - + (FAST_P - ? 0 - : (1 + MAX_PARALLEL_INSNS) /* before+after */) - + (MAX_PARALLEL_INSNS > 1 - ? (MAX_PARALLEL_INSNS * 2) - : 0)); - - /* Account for before/after handlers. */ - if (! FAST_P) - slice_insns *= 3; - - if (slice_insns > 0 - && slice_insns < max_insns) - max_insns = slice_insns; - } - - new_vpc = sc; - - /* SC,PC must be updated to point passed the last entry used. - SET_CTI_VPC must be called if pbb is terminated by a cti. - SET_INSN_COUNT must be called to record number of real insns in - pbb [could be computed by us of course, extra cpu but perhaps - negligible enough]. */ - -/* begin extract-pbb */ -{ - const IDESC *idesc; - int icount = 0; - - while (max_insns > 0) - { - UHI insn = GETIMEMUHI (current_cpu, pc); - - idesc = extract (current_cpu, pc, insn, &sc->argbuf, FAST_P); - SEM_SKIP_COMPILE (current_cpu, sc, 1); - ++sc; - --max_insns; - ++icount; - pc += idesc->length; - - if (IDESC_CTI_P (idesc)) - { - SET_CTI_VPC (sc - 1); - - if (CGEN_ATTR_VALUE (NULL, idesc->attrs, CGEN_INSN_DELAY_SLOT)) - { - USI insn = GETIMEMUHI (current_cpu, pc); - idesc = extract (current_cpu, pc, insn, &sc->argbuf, FAST_P); - - if (IDESC_CTI_P (idesc) || - CGEN_ATTR_VALUE (NULL, idesc->attrs, CGEN_INSN_ILLSLOT)) - { - SIM_DESC sd = CPU_STATE (current_cpu); - sim_io_eprintf (CPU_STATE (current_cpu), - "malformed program, `%s' insn in delay slot\n", - CGEN_INSN_NAME (idesc->idata)); - sim_engine_halt (sd, current_cpu, NULL, pc, - sim_stopped, SIM_SIGILL); - } - else - { - ++sc; - --max_insns; - ++icount; - pc += idesc->length; - } - } - break; - } - } - - Finish: - SET_INSN_COUNT (icount); -} -/* end extract-pbb */ - - /* The last one is a pseudo-insn to link to the next chain. - It is also used to record the insn count for this chain. */ - { - const IDESC *id; - - /* Was pbb terminated by a cti? */ - if (_cti_sc) - { - id = & CPU_IDESC (current_cpu) [SH64_COMPACT_INSN_X_CTI_CHAIN]; - } - else - { - id = & CPU_IDESC (current_cpu) [SH64_COMPACT_INSN_X_CHAIN]; - } - SEM_SET_CODE (&sc->argbuf, id, FAST_P); - sc->argbuf.idesc = id; - sc->argbuf.addr = pc; - sc->argbuf.fields.chain.insn_count = _insn_count; - sc->argbuf.fields.chain.next = 0; - sc->argbuf.fields.chain.branch_target = 0; - ++sc; - } - - /* Update the pointer to the next free entry, may not have used as - many entries as was asked for. */ - CPU_SCACHE_NEXT_FREE (current_cpu) = sc; - /* Record length of chain if profiling. - This includes virtual insns since they count against - max_insns too. */ - if (! FAST_P) - PROFILE_COUNT_SCACHE_CHAIN_LENGTH (current_cpu, sc - orig_sc); - } - - return new_vpc; -} - -/* Chain to the next block from a non-cti terminated previous block. */ - -INLINE SEM_PC -sh64_compact_pbb_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg) -{ - ARGBUF *abuf = SEM_ARGBUF (sem_arg); - - PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg); - - SET_H_PC (abuf->addr); - - - /* If not running forever, exit back to main loop. */ - if (CPU_MAX_SLICE_INSNS (current_cpu) != 0 - /* Also exit back to main loop if there's an event. - Note that if CPU_MAX_SLICE_INSNS != 1, events won't get processed - at the "right" time, but then that was what was asked for. - There is no silver bullet for simulator engines. - ??? Clearly this needs a cleaner interface. - At present it's just so Ctrl-C works. */ - || STATE_EVENTS (CPU_STATE (current_cpu))->work_pending) - CPU_RUNNING_P (current_cpu) = 0; - - /* If chained to next block, go straight to it. */ - if (abuf->fields.chain.next) - return abuf->fields.chain.next; - /* See if next block has already been compiled. */ - abuf->fields.chain.next = scache_lookup (current_cpu, abuf->addr); - if (abuf->fields.chain.next) - return abuf->fields.chain.next; - /* Nope, so next insn is a virtual insn to invoke the compiler - (begin a pbb). */ - return CPU_SCACHE_PBB_BEGIN (current_cpu); -} - -/* Chain to the next block from a cti terminated previous block. - BR_TYPE indicates whether the branch was taken and whether we can cache - the vpc of the branch target. - NEW_PC is the target's branch address, and is only valid if - BR_TYPE != SEM_BRANCH_UNTAKEN. */ - -INLINE SEM_PC -sh64_compact_pbb_cti_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg, - SEM_BRANCH_TYPE br_type, PCADDR new_pc) -{ - SEM_PC *new_vpc_ptr; - - PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg); - - /* If we have switched ISAs, exit back to main loop. - Set idesc to 0 to cause the engine to point to the right insn table. */ - if (new_pc & 1) - { - /* Switch to SHmedia. */ - CPU_IDESC_SEM_INIT_P (current_cpu) = 0; - CPU_RUNNING_P (current_cpu) = 0; - } - - /* If not running forever, exit back to main loop. */ - if (CPU_MAX_SLICE_INSNS (current_cpu) != 0 - /* Also exit back to main loop if there's an event. - Note that if CPU_MAX_SLICE_INSNS != 1, events won't get processed - at the "right" time, but then that was what was asked for. - There is no silver bullet for simulator engines. - ??? Clearly this needs a cleaner interface. - At present it's just so Ctrl-C works. */ - || STATE_EVENTS (CPU_STATE (current_cpu))->work_pending) - CPU_RUNNING_P (current_cpu) = 0; - - /* Restart compiler if we branched to an uncacheable address - (e.g. "j reg"). */ - if (br_type == SEM_BRANCH_UNCACHEABLE) - { - SET_H_PC (new_pc); - return CPU_SCACHE_PBB_BEGIN (current_cpu); - } - - /* If branch wasn't taken, update the pc and set BR_ADDR_PTR to our - next chain ptr. */ - if (br_type == SEM_BRANCH_UNTAKEN) - { - ARGBUF *abuf = SEM_ARGBUF (sem_arg); - new_pc = abuf->addr; - SET_H_PC (new_pc); - new_vpc_ptr = &abuf->fields.chain.next; - } - else - { - ARGBUF *abuf = SEM_ARGBUF (sem_arg); - SET_H_PC (new_pc); - new_vpc_ptr = &abuf->fields.chain.branch_target; - } - - /* If chained to next block, go straight to it. */ - if (*new_vpc_ptr) - return *new_vpc_ptr; - /* See if next block has already been compiled. */ - *new_vpc_ptr = scache_lookup (current_cpu, new_pc); - if (*new_vpc_ptr) - return *new_vpc_ptr; - /* Nope, so next insn is a virtual insn to invoke the compiler - (begin a pbb). */ - return CPU_SCACHE_PBB_BEGIN (current_cpu); -} - -/* x-before handler. - This is called before each insn. */ - -void -sh64_compact_pbb_before (SIM_CPU *current_cpu, SCACHE *sc) -{ - SEM_ARG sem_arg = sc; - const ARGBUF *abuf = SEM_ARGBUF (sem_arg); - int first_p = abuf->fields.before.first_p; - const ARGBUF *cur_abuf = SEM_ARGBUF (sc + 1); - const IDESC *cur_idesc = cur_abuf->idesc; - PCADDR pc = cur_abuf->addr; - - if (ARGBUF_PROFILE_P (cur_abuf)) - PROFILE_COUNT_INSN (current_cpu, pc, cur_idesc->num); - - /* If this isn't the first insn, finish up the previous one. */ - - if (! first_p) - { - if (PROFILE_MODEL_P (current_cpu)) - { - const SEM_ARG prev_sem_arg = sc - 1; - const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg); - const IDESC *prev_idesc = prev_abuf->idesc; - int cycles; - - /* ??? May want to measure all insns if doing insn tracing. */ - if (ARGBUF_PROFILE_P (prev_abuf)) - { - cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg); - sh64_compact_model_insn_after (current_cpu, 0 /*last_p*/, cycles); - } - } - - CGEN_TRACE_INSN_FINI (current_cpu, cur_abuf, 0 /*last_p*/); - } - - /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */ - if (PROFILE_MODEL_P (current_cpu) - && ARGBUF_PROFILE_P (cur_abuf)) - sh64_compact_model_insn_before (current_cpu, first_p); - - CGEN_TRACE_INSN_INIT (current_cpu, cur_abuf, first_p); - CGEN_TRACE_INSN (current_cpu, cur_idesc->idata, cur_abuf, pc); -} - -/* x-after handler. - This is called after a serial insn or at the end of a group of parallel - insns. */ - -void -sh64_compact_pbb_after (SIM_CPU *current_cpu, SCACHE *sc) -{ - SEM_ARG sem_arg = sc; - const ARGBUF *abuf = SEM_ARGBUF (sem_arg); - const SEM_ARG prev_sem_arg = sc - 1; - const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg); - - /* ??? May want to measure all insns if doing insn tracing. */ - if (PROFILE_MODEL_P (current_cpu) - && ARGBUF_PROFILE_P (prev_abuf)) - { - const IDESC *prev_idesc = prev_abuf->idesc; - int cycles; - - cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg); - sh64_compact_model_insn_after (current_cpu, 1 /*last_p*/, cycles); - } - CGEN_TRACE_INSN_FINI (current_cpu, prev_abuf, 1 /*last_p*/); -} - -#define FAST_P 0 - -void -sh64_compact_engine_run_full (SIM_CPU *current_cpu) -{ - SIM_DESC current_state = CPU_STATE (current_cpu); - SCACHE *scache = CPU_SCACHE_CACHE (current_cpu); - /* virtual program counter */ - SEM_PC vpc; -#if WITH_SEM_SWITCH_FULL - /* For communication between cti's and cti-chain. */ - SEM_BRANCH_TYPE pbb_br_type; - PCADDR pbb_br_npc; -#endif - - - if (! CPU_IDESC_SEM_INIT_P (current_cpu)) - { - /* ??? 'twould be nice to move this up a level and only call it once. - On the other hand, in the "let's go fast" case the test is only done - once per pbb (since we only return to the main loop at the end of - a pbb). And in the "let's run until we're done" case we don't return - until the program exits. */ - -#if WITH_SEM_SWITCH_FULL -#if defined (__GNUC__) -/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */ -#define DEFINE_LABELS -#include "sem-compact-switch.c" -#endif -#else - sh64_compact_sem_init_idesc_table (current_cpu); -#endif - - /* Initialize the "begin (compile) a pbb" virtual insn. */ - vpc = CPU_SCACHE_PBB_BEGIN (current_cpu); - SEM_SET_FULL_CODE (SEM_ARGBUF (vpc), - & CPU_IDESC (current_cpu) [SH64_COMPACT_INSN_X_BEGIN]); - vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [SH64_COMPACT_INSN_X_BEGIN]; - - CPU_IDESC_SEM_INIT_P (current_cpu) = 1; - } - - CPU_RUNNING_P (current_cpu) = 1; - /* ??? In the case where we're returning to the main loop after every - pbb we don't want to call pbb_begin each time (which hashes on the pc - and does a table lookup). A way to speed this up is to save vpc - between calls. */ - vpc = sh64_compact_pbb_begin (current_cpu, FAST_P); - - do - { -/* begin full-exec-pbb */ -{ -#if (! FAST_P && WITH_SEM_SWITCH_FULL) || (FAST_P && WITH_SEM_SWITCH_FAST) -#define DEFINE_SWITCH -#include "sem-compact-switch.c" -#else - vpc = execute (current_cpu, vpc, FAST_P); -#endif -} -/* end full-exec-pbb */ - } - while (CPU_RUNNING_P (current_cpu)); -} - -#undef FAST_P - - -#define FAST_P 1 - -void -sh64_compact_engine_run_fast (SIM_CPU *current_cpu) -{ - SIM_DESC current_state = CPU_STATE (current_cpu); - SCACHE *scache = CPU_SCACHE_CACHE (current_cpu); - /* virtual program counter */ - SEM_PC vpc; -#if WITH_SEM_SWITCH_FAST - /* For communication between cti's and cti-chain. */ - SEM_BRANCH_TYPE pbb_br_type; - PCADDR pbb_br_npc; -#endif - - - if (! CPU_IDESC_SEM_INIT_P (current_cpu)) - { - /* ??? 'twould be nice to move this up a level and only call it once. - On the other hand, in the "let's go fast" case the test is only done - once per pbb (since we only return to the main loop at the end of - a pbb). And in the "let's run until we're done" case we don't return - until the program exits. */ - -#if WITH_SEM_SWITCH_FAST -#if defined (__GNUC__) -/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */ -#define DEFINE_LABELS -#include "sem-compact-switch.c" -#endif -#else - sh64_compact_semf_init_idesc_table (current_cpu); -#endif - - /* Initialize the "begin (compile) a pbb" virtual insn. */ - vpc = CPU_SCACHE_PBB_BEGIN (current_cpu); - SEM_SET_FAST_CODE (SEM_ARGBUF (vpc), - & CPU_IDESC (current_cpu) [SH64_COMPACT_INSN_X_BEGIN]); - vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [SH64_COMPACT_INSN_X_BEGIN]; - - CPU_IDESC_SEM_INIT_P (current_cpu) = 1; - } - - CPU_RUNNING_P (current_cpu) = 1; - /* ??? In the case where we're returning to the main loop after every - pbb we don't want to call pbb_begin each time (which hashes on the pc - and does a table lookup). A way to speed this up is to save vpc - between calls. */ - vpc = sh64_compact_pbb_begin (current_cpu, FAST_P); - - do - { -/* begin fast-exec-pbb */ -{ -#if (! FAST_P && WITH_SEM_SWITCH_FULL) || (FAST_P && WITH_SEM_SWITCH_FAST) -#define DEFINE_SWITCH -#include "sem-compact-switch.c" -#else - vpc = execute (current_cpu, vpc, FAST_P); -#endif -} -/* end fast-exec-pbb */ - } - while (CPU_RUNNING_P (current_cpu)); -} - -#undef FAST_P - |