1# Simulator main loop for m32r. -*- C -*- 2# 3# Copyright (C) 1996-2016 Free Software Foundation, Inc. 4# 5# This file is part of the GNU Simulators. 6# 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 3 of the License, or 10# (at your option) any later version. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program. If not, see <http://www.gnu.org/licenses/>. 19 20# Syntax: 21# /bin/sh mainloop.in command 22# 23# Command is one of: 24# 25# init 26# support 27# extract-{simple,scache,pbb} 28# {full,fast}-exec-{simple,scache,pbb} 29# 30# A target need only provide a "full" version of one of simple,scache,pbb. 31# If the target wants it can also provide a fast version of same, or if 32# the slow (full featured) version is `simple', then the fast version can be 33# one of scache/pbb. 34# A target can't provide more than this. 35# However for illustration's sake this file provides examples of all. 36 37# ??? After a few more ports are done, revisit. 38# Will eventually need to machine generate a lot of this. 39 40case "x$1" in 41 42xsupport) 43 44cat <<EOF 45 46static INLINE const IDESC * 47extract16 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, 48 ARGBUF *abuf, int fast_p) 49{ 50 const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf); 51 52 @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p); 53 if (! fast_p) 54 { 55 int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc); 56 int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc); 57 @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p); 58 } 59 return id; 60} 61 62static INLINE const IDESC * 63extract32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, 64 ARGBUF *abuf, int fast_p) 65{ 66 const IDESC *id = @cpu@_decode (current_cpu, pc, (USI) insn >> 16, insn, abuf); 67 68 @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p); 69 if (! fast_p) 70 { 71 int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc); 72 int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc); 73 @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p); 74 } 75 return id; 76} 77 78static INLINE SEM_PC 79execute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p) 80{ 81 SEM_PC vpc; 82 83 if (fast_p) 84 { 85#if ! WITH_SEM_SWITCH_FAST 86#if WITH_SCACHE 87 vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc); 88#else 89 vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, &sc->argbuf); 90#endif 91#else 92 abort (); 93#endif /* WITH_SEM_SWITCH_FAST */ 94 } 95 else 96 { 97#if ! WITH_SEM_SWITCH_FULL 98 ARGBUF *abuf = &sc->argbuf; 99 const IDESC *idesc = abuf->idesc; 100 const CGEN_INSN *idata = idesc->idata; 101#if WITH_SCACHE_PBB 102 int virtual_p = CGEN_INSN_ATTR_VALUE (idata, CGEN_INSN_VIRTUAL); 103#else 104 int virtual_p = 0; 105#endif 106 107 if (! virtual_p) 108 { 109 /* FIXME: call x-before */ 110 if (ARGBUF_PROFILE_P (abuf)) 111 PROFILE_COUNT_INSN (current_cpu, abuf->addr, idesc->num); 112 /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */ 113 if (PROFILE_MODEL_P (current_cpu) 114 && ARGBUF_PROFILE_P (abuf)) 115 @cpu@_model_insn_before (current_cpu, 1 /*first_p*/); 116 CGEN_TRACE_INSN_INIT (current_cpu, abuf, 1); 117 CGEN_TRACE_INSN (current_cpu, idata, 118 (const struct argbuf *) abuf, abuf->addr); 119 } 120#if WITH_SCACHE 121 vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc); 122#else 123 vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, abuf); 124#endif 125 if (! virtual_p) 126 { 127 /* FIXME: call x-after */ 128 if (PROFILE_MODEL_P (current_cpu) 129 && ARGBUF_PROFILE_P (abuf)) 130 { 131 int cycles; 132 133 cycles = (*idesc->timing->model_fn) (current_cpu, sc); 134 @cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles); 135 } 136 CGEN_TRACE_INSN_FINI (current_cpu, abuf, 1); 137 } 138#else 139 abort (); 140#endif /* WITH_SEM_SWITCH_FULL */ 141 } 142 143 return vpc; 144} 145 146EOF 147 148;; 149 150xinit) 151 152# Nothing needed. 153 154;; 155 156xextract-simple | xextract-scache) 157 158cat <<EOF 159{ 160 if ((pc & 3) != 0) 161 { 162 /* This only occurs when single stepping. 163 The test is unnecessary otherwise, but the cost is teensy, 164 compared with decoding/extraction. */ 165 UHI insn = GETIMEMUHI (current_cpu, pc); 166 extract16 (current_cpu, pc, insn & 0x7fff, sc, FAST_P); 167 } 168 else 169 { 170 USI insn = GETIMEMUSI (current_cpu, pc); 171 if ((SI) insn < 0) 172 { 173 extract32 (current_cpu, pc, insn, sc, FAST_P); 174 } 175 else 176 { 177 extract16 (current_cpu, pc, insn >> 16, sc, FAST_P); 178 extract16 (current_cpu, pc + 2, insn & 0x7fff, sc + 1, FAST_P); 179 /* The m32r doesn't support parallel execution. */ 180 if ((insn & 0x8000) != 0 181 && (insn & 0x7fff) != 0x7000) /* parallel nops are ok */ 182 sim_engine_illegal_insn (current_cpu, pc); 183 } 184 } 185} 186EOF 187 188;; 189 190xextract-pbb) 191 192# Inputs: current_cpu, pc, sc, max_insns, FAST_P 193# Outputs: sc, pc 194# sc must be left pointing past the last created entry. 195# pc must be left pointing past the last created entry. 196# If the pbb is terminated by a cti insn, SET_CTI_VPC(sc) must be called 197# to record the vpc of the cti insn. 198# SET_INSN_COUNT(n) must be called to record number of real insns. 199 200cat <<EOF 201{ 202 const IDESC *idesc; 203 int icount = 0; 204 205 if ((pc & 3) != 0) 206 { 207 /* This only occurs when single stepping. 208 The test is unnecessary otherwise, but the cost is teensy, 209 compared with decoding/extraction. */ 210 UHI insn = GETIMEMUHI (current_cpu, pc); 211 idesc = extract16 (current_cpu, pc, insn & 0x7fff, &sc->argbuf, FAST_P); 212 ++sc; 213 --max_insns; 214 ++icount; 215 pc += 2; 216 if (IDESC_CTI_P (idesc)) 217 { 218 SET_CTI_VPC (sc - 1); 219 goto Finish; 220 } 221 } 222 223 while (max_insns > 0) 224 { 225 USI insn = GETIMEMUSI (current_cpu, pc); 226 if ((SI) insn < 0) 227 { 228 idesc = extract32 (current_cpu, pc, insn, &sc->argbuf, FAST_P); 229 ++sc; 230 --max_insns; 231 ++icount; 232 pc += 4; 233 if (IDESC_CTI_P (idesc)) 234 { 235 SET_CTI_VPC (sc - 1); 236 break; 237 } 238 } 239 else 240 { 241 idesc = extract16 (current_cpu, pc, insn >> 16, &sc->argbuf, FAST_P); 242 ++sc; 243 --max_insns; 244 ++icount; 245 pc += 2; 246 if (IDESC_CTI_P (idesc)) 247 { 248 SET_CTI_VPC (sc - 1); 249 break; 250 } 251 /* The m32r doesn't support parallel execution. */ 252 if ((insn & 0x8000) != 0) 253 { 254 /* ??? Defer signalling to execution. */ 255 if ((insn & 0x7fff) != 0x7000) /* parallel nops are ok */ 256 sim_engine_invalid_insn (current_cpu, pc - 2, 0); 257 /* There's no point in processing parallel nops in fast mode. 258 We might as well do this test since we've already tested 259 that we have a parallel nop. */ 260 if (0 && FAST_P) 261 { 262 pc += 2; 263 continue; 264 } 265 } 266 else 267 { 268 /* Non-parallel case. 269 While we're guaranteed that there's room to extract the 270 insn, when single stepping we can't; the pbb must stop 271 after the first insn. */ 272 if (max_insns == 0) 273 break; 274 } 275 /* We're guaranteed that we can always process 16 bit insns in 276 pairs. */ 277 idesc = extract16 (current_cpu, pc, insn & 0x7fff, &sc->argbuf, FAST_P); 278 ++sc; 279 --max_insns; 280 ++icount; 281 pc += 2; 282 if (IDESC_CTI_P (idesc)) 283 { 284 SET_CTI_VPC (sc - 1); 285 break; 286 } 287 } 288 } 289 290 Finish: 291 SET_INSN_COUNT (icount); 292} 293EOF 294 295;; 296 297xfull-exec-* | xfast-exec-*) 298 299# Inputs: current_cpu, vpc, FAST_P 300# Outputs: vpc 301# vpc is the virtual program counter. 302 303cat <<EOF 304#if (! FAST_P && WITH_SEM_SWITCH_FULL) || (FAST_P && WITH_SEM_SWITCH_FAST) 305#define DEFINE_SWITCH 306#include "sem-switch.c" 307#else 308 vpc = execute (current_cpu, vpc, FAST_P); 309#endif 310EOF 311 312;; 313 314*) 315 echo "Invalid argument to mainloop.in: $1" >&2 316 exit 1 317 ;; 318 319esac 320