1# Simulator main loop for m32r. -*- C -*- 2# 3# Copyright (C) 1996-2024 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#line $LINENO "$0" 46#include <stdlib.h> 47 48static INLINE const IDESC * 49extract16 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, 50 ARGBUF *abuf, int fast_p) 51{ 52 const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf); 53 54 @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p); 55 if (! fast_p) 56 { 57 int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc); 58 int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc); 59 @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p); 60 } 61 return id; 62} 63 64static INLINE const IDESC * 65extract32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, 66 ARGBUF *abuf, int fast_p) 67{ 68 const IDESC *id = @cpu@_decode (current_cpu, pc, (USI) insn >> 16, insn, abuf); 69 70 @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p); 71 if (! fast_p) 72 { 73 int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc); 74 int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc); 75 @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p); 76 } 77 return id; 78} 79 80static INLINE SEM_PC 81execute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p) 82{ 83 SEM_PC vpc; 84 85 if (fast_p) 86 { 87#if ! WITH_SEM_SWITCH_FAST 88#if WITH_SCACHE 89 vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc); 90#else 91 vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, &sc->argbuf); 92#endif 93#else 94 abort (); 95#endif /* WITH_SEM_SWITCH_FAST */ 96 } 97 else 98 { 99#if ! WITH_SEM_SWITCH_FULL 100 ARGBUF *abuf = &sc->argbuf; 101 const IDESC *idesc = abuf->idesc; 102 const CGEN_INSN *idata = idesc->idata; 103#if WITH_SCACHE_PBB 104 int virtual_p = CGEN_INSN_ATTR_VALUE (idata, CGEN_INSN_VIRTUAL); 105#else 106 int virtual_p = 0; 107#endif 108 109 if (! virtual_p) 110 { 111 /* FIXME: call x-before */ 112 if (ARGBUF_PROFILE_P (abuf)) 113 PROFILE_COUNT_INSN (current_cpu, abuf->addr, idesc->num); 114 /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */ 115 if (PROFILE_MODEL_P (current_cpu) 116 && ARGBUF_PROFILE_P (abuf)) 117 @cpu@_model_insn_before (current_cpu, 1 /*first_p*/); 118 CGEN_TRACE_INSN_INIT (current_cpu, abuf, 1); 119 CGEN_TRACE_INSN (current_cpu, idata, 120 (const struct argbuf *) abuf, abuf->addr); 121 } 122#if WITH_SCACHE 123 vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc); 124#else 125 vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, abuf); 126#endif 127 if (! virtual_p) 128 { 129 /* FIXME: call x-after */ 130 if (PROFILE_MODEL_P (current_cpu) 131 && ARGBUF_PROFILE_P (abuf)) 132 { 133 int cycles; 134 135 cycles = (*idesc->timing->model_fn) (current_cpu, sc); 136 @cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles); 137 } 138 CGEN_TRACE_INSN_FINI (current_cpu, abuf, 1); 139 } 140#else 141 abort (); 142#endif /* WITH_SEM_SWITCH_FULL */ 143 } 144 145 return vpc; 146} 147 148EOF 149 150;; 151 152xinit) 153 154# Nothing needed. 155 156;; 157 158xextract-simple | xextract-scache) 159 160cat <<EOF 161#line $LINENO "$0" 162{ 163 if ((pc & 3) != 0) 164 { 165 /* This only occurs when single stepping. 166 The test is unnecessary otherwise, but the cost is teensy, 167 compared with decoding/extraction. */ 168 UHI insn = GETIMEMUHI (current_cpu, pc); 169 extract16 (current_cpu, pc, insn & 0x7fff, sc, FAST_P); 170 } 171 else 172 { 173 USI insn = GETIMEMUSI (current_cpu, pc); 174 if ((SI) insn < 0) 175 { 176 extract32 (current_cpu, pc, insn, sc, FAST_P); 177 } 178 else 179 { 180 extract16 (current_cpu, pc, insn >> 16, sc, FAST_P); 181 extract16 (current_cpu, pc + 2, insn & 0x7fff, sc + 1, FAST_P); 182 /* The m32r doesn't support parallel execution. */ 183 if ((insn & 0x8000) != 0 184 && (insn & 0x7fff) != 0x7000) /* parallel nops are ok */ 185 sim_engine_illegal_insn (current_cpu, pc); 186 } 187 } 188} 189EOF 190 191;; 192 193xextract-pbb) 194 195# Inputs: current_cpu, pc, sc, max_insns, FAST_P 196# Outputs: sc, pc 197# sc must be left pointing past the last created entry. 198# pc must be left pointing past the last created entry. 199# If the pbb is terminated by a cti insn, SET_CTI_VPC(sc) must be called 200# to record the vpc of the cti insn. 201# SET_INSN_COUNT(n) must be called to record number of real insns. 202 203cat <<EOF 204#line $LINENO "$0" 205{ 206 const IDESC *idesc; 207 int icount = 0; 208 209 if ((pc & 3) != 0) 210 { 211 /* This only occurs when single stepping. 212 The test is unnecessary otherwise, but the cost is teensy, 213 compared with decoding/extraction. */ 214 UHI insn = GETIMEMUHI (current_cpu, pc); 215 idesc = extract16 (current_cpu, pc, insn & 0x7fff, &sc->argbuf, FAST_P); 216 ++sc; 217 --max_insns; 218 ++icount; 219 pc += 2; 220 if (IDESC_CTI_P (idesc)) 221 { 222 SET_CTI_VPC (sc - 1); 223 goto Finish; 224 } 225 } 226 227 while (max_insns > 0) 228 { 229 USI insn = GETIMEMUSI (current_cpu, pc); 230 if ((SI) insn < 0) 231 { 232 idesc = extract32 (current_cpu, pc, insn, &sc->argbuf, FAST_P); 233 ++sc; 234 --max_insns; 235 ++icount; 236 pc += 4; 237 if (IDESC_CTI_P (idesc)) 238 { 239 SET_CTI_VPC (sc - 1); 240 break; 241 } 242 } 243 else 244 { 245 idesc = extract16 (current_cpu, pc, insn >> 16, &sc->argbuf, FAST_P); 246 ++sc; 247 --max_insns; 248 ++icount; 249 pc += 2; 250 if (IDESC_CTI_P (idesc)) 251 { 252 SET_CTI_VPC (sc - 1); 253 break; 254 } 255 /* The m32r doesn't support parallel execution. */ 256 if ((insn & 0x8000) != 0) 257 { 258 /* ??? Defer signalling to execution. */ 259 if ((insn & 0x7fff) != 0x7000) /* parallel nops are ok */ 260 sim_engine_invalid_insn (current_cpu, pc - 2, 0); 261 /* There's no point in processing parallel nops in fast mode. 262 We might as well do this test since we've already tested 263 that we have a parallel nop. */ 264 if (0 && FAST_P) 265 { 266 pc += 2; 267 continue; 268 } 269 } 270 else 271 { 272 /* Non-parallel case. 273 While we're guaranteed that there's room to extract the 274 insn, when single stepping we can't; the pbb must stop 275 after the first insn. */ 276 if (max_insns == 0) 277 break; 278 } 279 /* We're guaranteed that we can always process 16 bit insns in 280 pairs. */ 281 idesc = extract16 (current_cpu, pc, insn & 0x7fff, &sc->argbuf, FAST_P); 282 ++sc; 283 --max_insns; 284 ++icount; 285 pc += 2; 286 if (IDESC_CTI_P (idesc)) 287 { 288 SET_CTI_VPC (sc - 1); 289 break; 290 } 291 } 292 } 293 294 Finish: 295 SET_INSN_COUNT (icount); 296} 297EOF 298 299;; 300 301xfull-exec-* | xfast-exec-*) 302 303# Inputs: current_cpu, vpc, FAST_P 304# Outputs: vpc 305# vpc is the virtual program counter. 306 307cat <<EOF 308#line $LINENO "$0" 309#if (! FAST_P && WITH_SEM_SWITCH_FULL) || (FAST_P && WITH_SEM_SWITCH_FAST) 310#define DEFINE_SWITCH 311#include "sem-switch.c" 312#else 313 vpc = execute (current_cpu, vpc, FAST_P); 314#endif 315EOF 316 317;; 318 319*) 320 echo "Invalid argument to mainloop.in: $1" >&2 321 exit 1 322 ;; 323 324esac 325