1# Simulator main loop for lm32. -*- C -*- 2# Contributed by Jon Beniston <jon@beniston.com> 3# 4# This file is part of the GNU Simulators. 5# 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 3, or (at your option) 9# any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License along 17# with this program; if not, see <http://www.gnu.org/licenses/>. 18 19# Syntax: 20# /bin/sh mainloop.in command 21# 22# Command is one of: 23# 24# init 25# support 26# extract-{simple,scache,pbb} 27# {full,fast}-exec-{simple,scache,pbb} 28# 29 30case "x$1" in 31 32xsupport) 33 34cat <<EOF 35 36static INLINE const IDESC * 37extract (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, 38 ARGBUF *abuf, int fast_p) 39{ 40 const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf); 41 42 @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p); 43 if (! fast_p) 44 { 45 int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc); 46 int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc); 47 @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p); 48 } 49 return id; 50} 51 52static INLINE SEM_PC 53execute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p) 54{ 55 SEM_PC vpc; 56 57 if (fast_p) 58 { 59#if ! WITH_SEM_SWITCH_FAST 60#if WITH_SCACHE 61 vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc); 62#else 63 vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, &sc->argbuf); 64#endif 65#else 66 abort (); 67#endif /* WITH_SEM_SWITCH_FAST */ 68 } 69 else 70 { 71#if ! WITH_SEM_SWITCH_FULL 72 ARGBUF *abuf = &sc->argbuf; 73 const IDESC *idesc = abuf->idesc; 74 const CGEN_INSN *idata = idesc->idata; 75#if WITH_SCACHE_PBB 76 int virtual_p = CGEN_INSN_ATTR_VALUE (idata, CGEN_INSN_VIRTUAL); 77#else 78 int virtual_p = 0; 79#endif 80 if (! virtual_p) 81 { 82 /* FIXME: call x-before */ 83 if (ARGBUF_PROFILE_P (abuf)) 84 PROFILE_COUNT_INSN (current_cpu, abuf->addr, idesc->num); 85 /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */ 86 if (PROFILE_MODEL_P (current_cpu) 87 && ARGBUF_PROFILE_P (abuf)) 88 @cpu@_model_insn_before (current_cpu, 1 /*first_p*/); 89 CGEN_TRACE_INSN_INIT (current_cpu, abuf, 1); 90 CGEN_TRACE_INSN (current_cpu, idata, 91 (const struct argbuf *) abuf, abuf->addr); 92 } 93#if WITH_SCACHE 94 vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc); 95#else 96 vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, abuf); 97#endif 98 if (! virtual_p) 99 { 100 /* FIXME: call x-after */ 101 if (PROFILE_MODEL_P (current_cpu) 102 && ARGBUF_PROFILE_P (abuf)) 103 { 104 int cycles; 105 106 cycles = (*idesc->timing->model_fn) (current_cpu, sc); 107 @cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles); 108 } 109 CGEN_TRACE_INSN_FINI (current_cpu, abuf, 1); 110 } 111#else 112 abort (); 113#endif /* WITH_SEM_SWITCH_FULL */ 114 } 115 116 return vpc; 117} 118 119EOF 120 121;; 122 123xinit) 124 125# Nothing needed. 126 127;; 128 129xextract-simple | xextract-scache) 130 131cat <<EOF 132{ 133 CGEN_INSN_INT insn = GETIMEMUSI (current_cpu, vpc); 134 extract (current_cpu, vpc, insn, SEM_ARGBUF (sc), FAST_P); 135} 136EOF 137 138;; 139 140xextract-pbb) 141 142# Inputs: current_cpu, pc, sc, max_insns, FAST_P 143# Outputs: sc, pc 144# sc must be left pointing past the last created entry. 145# pc must be left pointing past the last created entry. 146# If the pbb is terminated by a cti insn, SET_CTI_VPC(sc) must be called 147# to record the vpc of the cti insn. 148# SET_INSN_COUNT(n) must be called to record number of real insns. 149 150cat <<EOF 151{ 152 const IDESC *idesc; 153 int icount = 0; 154 155 while (max_insns > 0) 156 { 157 USI insn = GETIMEMUSI (current_cpu, pc); 158 159 idesc = extract (current_cpu, pc, insn, &sc->argbuf, FAST_P); 160 ++sc; 161 --max_insns; 162 ++icount; 163 pc += idesc->length; 164 165 if (IDESC_CTI_P (idesc)) 166 { 167 SET_CTI_VPC (sc - 1); 168 break; 169 } 170 } 171 172 Finish: 173 SET_INSN_COUNT (icount); 174} 175EOF 176 177;; 178 179xfull-exec-* | xfast-exec-*) 180 181# Inputs: current_cpu, vpc, FAST_P 182# Outputs: vpc 183 184cat <<EOF 185 /* Update cycle counter */ 186 SET_H_CSR (LM32_CSR_CC, GET_H_CSR (LM32_CSR_CC) + 1); 187#if (! FAST_P && WITH_SEM_SWITCH_FULL) || (FAST_P && WITH_SEM_SWITCH_FAST) 188#define DEFINE_SWITCH 189#include "sem-switch.c" 190#else 191 vpc = execute (current_cpu, vpc, FAST_P); 192#endif 193EOF 194 195;; 196 197*) 198 echo "Invalid argument to mainloop.in: $1" >&2 199 exit 1 200 ;; 201 202esac 203