1 # Simulator main loop for lm32. -*- C -*- 2 # Contributed by Jon Beniston <jon (a] 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 30 case "x$1" in 31 32 xsupport) 33 34 cat <<EOF 35 #line $LINENO "$0" 36 #include <stdlib.h> 37 38 static INLINE const IDESC * 39 extract (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 54 static INLINE SEM_PC 55 execute (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 121 EOF 122 123 ;; 124 125 xinit) 126 127 # Nothing needed. 128 129 ;; 130 131 xextract-simple | xextract-scache) 132 133 cat <<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 } 139 EOF 140 141 ;; 142 143 xextract-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 153 cat <<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 } 179 EOF 180 181 ;; 182 183 xfull-exec-* | xfast-exec-*) 184 185 # Inputs: current_cpu, vpc, FAST_P 186 # Outputs: vpc 187 188 cat <<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 198 EOF 199 200 ;; 201 202 *) 203 echo "Invalid argument to mainloop.in: $1" >&2 204 exit 1 205 ;; 206 207 esac 208