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