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