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#line $LINENO "$0" 36#include <stdlib.h> 37 38static INLINE const IDESC * 39extract (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, 40 ARGBUF *abuf, int fast_p) 41{ 42 const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf); 43 44 @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p); 45 if (! fast_p) 46 { 47 int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc); 48 int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc); 49 @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p); 50 } 51 return id; 52} 53 54static INLINE SEM_PC 55execute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p) 56{ 57 SEM_PC vpc; 58 59 if (fast_p) 60 { 61#if ! WITH_SEM_SWITCH_FAST 62#if WITH_SCACHE 63 vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc); 64#else 65 vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, &sc->argbuf); 66#endif 67#else 68 abort (); 69#endif /* WITH_SEM_SWITCH_FAST */ 70 } 71 else 72 { 73#if ! WITH_SEM_SWITCH_FULL 74 ARGBUF *abuf = &sc->argbuf; 75 const IDESC *idesc = abuf->idesc; 76 const CGEN_INSN *idata = idesc->idata; 77#if WITH_SCACHE_PBB 78 int virtual_p = CGEN_INSN_ATTR_VALUE (idata, CGEN_INSN_VIRTUAL); 79#else 80 int virtual_p = 0; 81#endif 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 (PROFILE_MODEL_P (current_cpu) 89 && ARGBUF_PROFILE_P (abuf)) 90 @cpu@_model_insn_before (current_cpu, 1 /*first_p*/); 91 CGEN_TRACE_INSN_INIT (current_cpu, abuf, 1); 92 CGEN_TRACE_INSN (current_cpu, idata, 93 (const struct argbuf *) abuf, abuf->addr); 94 } 95#if WITH_SCACHE 96 vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc); 97#else 98 vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, abuf); 99#endif 100 if (! virtual_p) 101 { 102 /* FIXME: call x-after */ 103 if (PROFILE_MODEL_P (current_cpu) 104 && ARGBUF_PROFILE_P (abuf)) 105 { 106 int cycles; 107 108 cycles = (*idesc->timing->model_fn) (current_cpu, sc); 109 @cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles); 110 } 111 CGEN_TRACE_INSN_FINI (current_cpu, abuf, 1); 112 } 113#else 114 abort (); 115#endif /* WITH_SEM_SWITCH_FULL */ 116 } 117 118 return vpc; 119} 120 121EOF 122 123;; 124 125xinit) 126 127# Nothing needed. 128 129;; 130 131xextract-simple | xextract-scache) 132 133cat <<EOF 134#line $LINENO "$0" 135{ 136 CGEN_INSN_INT insn = GETIMEMUSI (current_cpu, vpc); 137 extract (current_cpu, vpc, insn, SEM_ARGBUF (sc), FAST_P); 138} 139EOF 140 141;; 142 143xextract-pbb) 144 145# Inputs: current_cpu, pc, sc, max_insns, FAST_P 146# Outputs: sc, pc 147# sc must be left pointing past the last created entry. 148# pc must be left pointing past the last created entry. 149# If the pbb is terminated by a cti insn, SET_CTI_VPC(sc) must be called 150# to record the vpc of the cti insn. 151# SET_INSN_COUNT(n) must be called to record number of real insns. 152 153cat <<EOF 154#line $LINENO "$0" 155{ 156 const IDESC *idesc; 157 int icount = 0; 158 159 while (max_insns > 0) 160 { 161 USI insn = GETIMEMUSI (current_cpu, pc); 162 163 idesc = extract (current_cpu, pc, insn, &sc->argbuf, FAST_P); 164 ++sc; 165 --max_insns; 166 ++icount; 167 pc += idesc->length; 168 169 if (IDESC_CTI_P (idesc)) 170 { 171 SET_CTI_VPC (sc - 1); 172 break; 173 } 174 } 175 176 Finish: 177 SET_INSN_COUNT (icount); 178} 179EOF 180 181;; 182 183xfull-exec-* | xfast-exec-*) 184 185# Inputs: current_cpu, vpc, FAST_P 186# Outputs: vpc 187 188cat <<EOF 189#line $LINENO "$0" 190 /* Update cycle counter */ 191 SET_H_CSR (LM32_CSR_CC, GET_H_CSR (LM32_CSR_CC) + 1); 192#if (! FAST_P && WITH_SEM_SWITCH_FULL) || (FAST_P && WITH_SEM_SWITCH_FAST) 193#define DEFINE_SWITCH 194#include "sem-switch.c" 195#else 196 vpc = execute (current_cpu, vpc, FAST_P); 197#endif 198EOF 199 200;; 201 202*) 203 echo "Invalid argument to mainloop.in: $1" >&2 204 exit 1 205 ;; 206 207esac 208