1/* Engine header for Cpu tools GENerated simulators. 2 Copyright (C) 1998, 1999, 2007 Free Software Foundation, Inc. 3 Contributed by Cygnus Support. 4 5This file is part of GDB, the GNU debugger. 6 7This program is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3 of the License, or 10(at your option) any later version. 11 12This program is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20/* This file must be included after eng.h and before ${cpu}.h. 21 ??? A lot of this could be moved to genmloop.sh to be put in eng.h 22 and thus remove some conditional compilation. Worth it? */ 23 24/* Semantic functions come in six versions on two axes: 25 fast/full-featured, and using one of the simple/scache/compilation engines. 26 A full featured simulator is always provided. --enable-sim-fast includes 27 support for fast execution by duplicating the semantic code but leaving 28 out all features like tracing and profiling. 29 Using the scache is selected with --enable-sim-scache. */ 30/* FIXME: --enable-sim-fast not implemented yet. */ 31/* FIXME: undecided how to handle WITH_SCACHE_PBB. */ 32 33/* There are several styles of engines, all generally supported by the 34 same code: 35 36 WITH_SCACHE && WITH_SCACHE_PBB - pseudo-basic-block scaching 37 WITH_SCACHE && !WITH_SCACHE_PBB - scaching on an insn by insn basis 38 !WITH_SCACHE - simple engine: fetch an insn, execute an insn 39 40 The !WITH_SCACHE case can also be broken up into two flavours: 41 extract the fields of the insn into an ARGBUF struct, or defer the 42 extraction to the semantic handler. The former can be viewed as the 43 WITH_SCACHE case with a cache size of 1 (thus there's no need for a 44 WITH_EXTRACTION macro). The WITH_SCACHE case always extracts the fields 45 into an ARGBUF struct. */ 46 47#ifndef CGEN_ENGINE_H 48#define CGEN_ENGINE_H 49 50/* Instruction field support macros. */ 51 52#define EXTRACT_MSB0_INT(val, total, start, length) \ 53(((INT) (val) << ((sizeof (INT) * 8) - (total) + (start))) \ 54 >> ((sizeof (INT) * 8) - (length))) 55#define EXTRACT_MSB0_UINT(val, total, start, length) \ 56(((UINT) (val) << ((sizeof (UINT) * 8) - (total) + (start))) \ 57 >> ((sizeof (UINT) * 8) - (length))) 58 59#define EXTRACT_LSB0_INT(val, total, start, length) \ 60(((INT) (val) << ((sizeof (INT) * 8) - (start) - 1)) \ 61 >> ((sizeof (INT) * 8) - (length))) 62#define EXTRACT_LSB0_UINT(val, total, start, length) \ 63(((UINT) (val) << ((sizeof (UINT) * 8) - (start) - 1)) \ 64 >> ((sizeof (UINT) * 8) - (length))) 65 66/* Semantic routines. */ 67 68/* Type of the machine generated extraction fns. */ 69/* ??? No longer used. */ 70typedef void (EXTRACT_FN) (SIM_CPU *, IADDR, CGEN_INSN_INT, ARGBUF *); 71 72/* Type of the machine generated semantic fns. */ 73 74#if WITH_SCACHE 75 76/* Instruction fields are extracted into ARGBUF before calling the 77 semantic routine. */ 78#if HAVE_PARALLEL_INSNS && ! WITH_PARALLEL_GENWRITE 79typedef SEM_PC (SEMANTIC_FN) (SIM_CPU *, SEM_ARG, PAREXEC *); 80#else 81typedef SEM_PC (SEMANTIC_FN) (SIM_CPU *, SEM_ARG); 82#endif 83 84#else 85 86/* Result of semantic routines is a status indicator (wip). */ 87typedef unsigned int SEM_STATUS; 88 89/* Instruction fields are extracted by the semantic routine. 90 ??? TODO: multi word insns. */ 91#if HAVE_PARALLEL_INSNS && ! WITH_PARALLEL_GENWRITE 92typedef SEM_STATUS (SEMANTIC_FN) (SIM_CPU *, SEM_ARG, PAREXEC *, CGEN_INSN_INT); 93#else 94typedef SEM_STATUS (SEMANTIC_FN) (SIM_CPU *, SEM_ARG, CGEN_INSN_INT); 95#endif 96 97#endif 98 99/* In the ARGBUF struct, a pointer to the semantic routine for the insn. */ 100 101union sem { 102#if ! WITH_SEM_SWITCH_FULL 103 SEMANTIC_FN *sem_full; 104#endif 105#if ! WITH_SEM_SWITCH_FAST 106 SEMANTIC_FN *sem_fast; 107#endif 108#if WITH_SEM_SWITCH_FULL || WITH_SEM_SWITCH_FAST 109#ifdef __GNUC__ 110 void *sem_case; 111#else 112 int sem_case; 113#endif 114#endif 115}; 116 117/* Set the appropriate semantic handler in ABUF. */ 118 119#if WITH_SEM_SWITCH_FULL 120#ifdef __GNUC__ 121#define SEM_SET_FULL_CODE(abuf, idesc) \ 122 do { (abuf)->semantic.sem_case = (idesc)->sem_full_lab; } while (0) 123#else 124#define SEM_SET_FULL_CODE(abuf, idesc) \ 125 do { (abuf)->semantic.sem_case = (idesc)->num; } while (0) 126#endif 127#else 128#define SEM_SET_FULL_CODE(abuf, idesc) \ 129 do { (abuf)->semantic.sem_full = (idesc)->sem_full; } while (0) 130#endif 131 132#if WITH_SEM_SWITCH_FAST 133#ifdef __GNUC__ 134#define SEM_SET_FAST_CODE(abuf, idesc) \ 135 do { (abuf)->semantic.sem_case = (idesc)->sem_fast_lab; } while (0) 136#else 137#define SEM_SET_FAST_CODE(abuf, idesc) \ 138 do { (abuf)->semantic.sem_case = (idesc)->num; } while (0) 139#endif 140#else 141#define SEM_SET_FAST_CODE(abuf, idesc) \ 142 do { (abuf)->semantic.sem_fast = (idesc)->sem_fast; } while (0) 143#endif 144 145#define SEM_SET_CODE(abuf, idesc, fast_p) \ 146do { \ 147 if (fast_p) \ 148 SEM_SET_FAST_CODE ((abuf), (idesc)); \ 149 else \ 150 SEM_SET_FULL_CODE ((abuf), (idesc)); \ 151} while (0) 152 153/* Return non-zero if IDESC is a conditional or unconditional CTI. */ 154 155#define IDESC_CTI_P(idesc) \ 156 ((CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) \ 157 & (CGEN_ATTR_MASK (CGEN_INSN_COND_CTI) \ 158 | CGEN_ATTR_MASK (CGEN_INSN_UNCOND_CTI))) \ 159 != 0) 160 161/* Return non-zero if IDESC is a skip insn. */ 162 163#define IDESC_SKIP_P(idesc) \ 164 ((CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) \ 165 & CGEN_ATTR_MASK (CGEN_INSN_SKIP_CTI)) \ 166 != 0) 167 168/* Return pointer to ARGBUF given ptr to SCACHE. */ 169#define SEM_ARGBUF(sem_arg) (& (sem_arg) -> argbuf) 170 171/* There are several styles of engines, all generally supported by the 172 same code: 173 174 WITH_SCACHE && WITH_SCACHE_PBB - pseudo-basic-block scaching 175 WITH_SCACHE && !WITH_SCACHE_PBB - scaching on an insn by insn basis 176 !WITH_SCACHE - simple engine: fetch an insn, execute an insn 177 178 ??? The !WITH_SCACHE case can also be broken up into two flavours: 179 extract the fields of the insn into an ARGBUF struct, or defer the 180 extraction to the semantic handler. The WITH_SCACHE case always 181 extracts the fields into an ARGBUF struct. */ 182 183#if WITH_SCACHE 184 185#define CIA_ADDR(cia) (cia) 186 187#if WITH_SCACHE_PBB 188 189/* Return the scache pointer of the current insn. */ 190#define SEM_SEM_ARG(vpc, sc) (vpc) 191 192/* Return the virtual pc of the next insn to execute 193 (assuming this isn't a cti or the branch isn't taken). */ 194#define SEM_NEXT_VPC(sem_arg, pc, len) ((sem_arg) + 1) 195 196/* Update the instruction counter. */ 197#define PBB_UPDATE_INSN_COUNT(cpu,sc) \ 198 (CPU_INSN_COUNT (cpu) += SEM_ARGBUF (sc) -> fields.chain.insn_count) 199 200/* Do not append a `;' to invocations of this. 201 npc,br_type are for communication between the cti insn and cti-chain. */ 202#define SEM_BRANCH_INIT \ 203 IADDR npc = 0; /* assign a value for -Wall */ \ 204 SEM_BRANCH_TYPE br_type = SEM_BRANCH_UNTAKEN; 205 206/* SEM_IN_SWITCH is defined at the top of the mainloop.c files 207 generated by genmloop.sh. It exists so generated semantic code needn't 208 care whether it's being put in a switch or in a function. */ 209#ifdef SEM_IN_SWITCH 210#define SEM_BRANCH_FINI(pcvar) \ 211do { \ 212 pbb_br_npc = npc; \ 213 pbb_br_type = br_type; \ 214} while (0) 215#else /* 1 semantic function per instruction */ 216#define SEM_BRANCH_FINI(pcvar) \ 217do { \ 218 CPU_PBB_BR_NPC (current_cpu) = npc; \ 219 CPU_PBB_BR_TYPE (current_cpu) = br_type; \ 220} while (0) 221#endif 222 223#define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar) \ 224do { \ 225 npc = (newval); \ 226 br_type = SEM_BRANCH_CACHEABLE; \ 227} while (0) 228 229#define SEM_BRANCH_VIA_ADDR(cpu, sc, newval, pcvar) \ 230do { \ 231 npc = (newval); \ 232 br_type = SEM_BRANCH_UNCACHEABLE; \ 233} while (0) 234 235#define SEM_SKIP_COMPILE(cpu, sc, skip) \ 236do { \ 237 SEM_ARGBUF (sc) -> skip_count = (skip); \ 238} while (0) 239 240#define SEM_SKIP_INSN(cpu, sc, vpcvar) \ 241do { \ 242 (vpcvar) += SEM_ARGBUF (sc) -> skip_count; \ 243} while (0) 244 245#else /* ! WITH_SCACHE_PBB */ 246 247#define SEM_SEM_ARG(vpc, sc) (sc) 248 249#define SEM_NEXT_VPC(sem_arg, pc, len) ((pc) + (len)) 250 251/* ??? May wish to move taken_p out of here and make it explicit. */ 252#define SEM_BRANCH_INIT \ 253 int taken_p = 0; 254 255#ifndef TARGET_SEM_BRANCH_FINI 256#define TARGET_SEM_BRANCH_FINI(pcvar, taken_p) 257#endif 258#define SEM_BRANCH_FINI(pcvar) \ 259 do { TARGET_SEM_BRANCH_FINI (pcvar, taken_p); } while (0) 260 261#define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar) \ 262do { \ 263 (pcvar) = (newval); \ 264 taken_p = 1; \ 265} while (0) 266 267#define SEM_BRANCH_VIA_ADDR(cpu, sc, newval, pcvar) \ 268do { \ 269 (pcvar) = (newval); \ 270 taken_p = 1; \ 271} while (0) 272 273#endif /* ! WITH_SCACHE_PBB */ 274 275#else /* ! WITH_SCACHE */ 276 277/* This is the "simple" engine case. */ 278 279#define CIA_ADDR(cia) (cia) 280 281#define SEM_SEM_ARG(vpc, sc) (sc) 282 283#define SEM_NEXT_VPC(sem_arg, pc, len) ((pc) + (len)) 284 285#define SEM_BRANCH_INIT \ 286 int taken_p = 0; 287 288#define SEM_BRANCH_VIA_CACHE(cpu, abuf, newval, pcvar) \ 289do { \ 290 (pcvar) = (newval); \ 291 taken_p = 1; \ 292} while (0) 293 294#define SEM_BRANCH_VIA_ADDR(cpu, abuf, newval, pcvar) \ 295do { \ 296 (pcvar) = (newval); \ 297 taken_p = 1; \ 298} while (0) 299 300/* Finish off branch insns. 301 The target must define TARGET_SEM_BRANCH_FINI. 302 ??? This can probably go away when define-execute is finished. */ 303#define SEM_BRANCH_FINI(pcvar, bool_attrs) \ 304 do { TARGET_SEM_BRANCH_FINI ((pcvar), (bool_attrs), taken_p); } while (0) 305 306/* Finish off non-branch insns. 307 The target must define TARGET_SEM_NBRANCH_FINI. 308 ??? This can probably go away when define-execute is finished. */ 309#define SEM_NBRANCH_FINI(pcvar, bool_attrs) \ 310 do { TARGET_SEM_NBRANCH_FINI ((pcvar), (bool_attrs)); } while (0) 311 312#endif /* ! WITH_SCACHE */ 313 314/* Instruction information. */ 315 316/* Sanity check, at most one of these may be true. */ 317#if WITH_PARALLEL_READ + WITH_PARALLEL_WRITE + WITH_PARALLEL_GENWRITE > 1 318#error "At most one of WITH_PARALLEL_{READ,WRITE,GENWRITE} can be true." 319#endif 320 321/* Compile time computable instruction data. */ 322 323struct insn_sem { 324 /* The instruction type (a number that identifies each insn over the 325 entire architecture). */ 326 CGEN_INSN_TYPE type; 327 328 /* Index in IDESC table. */ 329 int index; 330 331 /* Semantic format number. */ 332 int sfmt; 333 334#if HAVE_PARALLEL_INSNS && ! WITH_PARALLEL_ONLY 335 /* Index in IDESC table of parallel handler. */ 336 int par_index; 337#endif 338 339#if WITH_PARALLEL_READ 340 /* Index in IDESC table of read handler. */ 341 int read_index; 342#endif 343 344#if WITH_PARALLEL_WRITE 345 /* Index in IDESC table of writeback handler. */ 346 int write_index; 347#endif 348}; 349 350/* Entry in semantic function table. 351 This information is copied to the insn descriptor table at run-time. */ 352 353struct sem_fn_desc { 354 /* Index in IDESC table. */ 355 int index; 356 357 /* Function to perform the semantics of the insn. */ 358 SEMANTIC_FN *fn; 359}; 360 361/* Run-time computed instruction descriptor. */ 362 363struct idesc { 364#if WITH_SEM_SWITCH_FAST 365#ifdef __GNUC__ 366 void *sem_fast_lab; 367#else 368 /* nothing needed, switch's on `num' member */ 369#endif 370#else 371 SEMANTIC_FN *sem_fast; 372#endif 373 374#if WITH_SEM_SWITCH_FULL 375#ifdef __GNUC__ 376 void *sem_full_lab; 377#else 378 /* nothing needed, switch's on `num' member */ 379#endif 380#else 381 SEMANTIC_FN *sem_full; 382#endif 383 384 /* Parallel support. */ 385#if HAVE_PARALLEL_INSNS && (! WITH_PARALLEL_ONLY || (WITH_PARALLEL_ONLY && ! WITH_PARALLEL_GENWRITE)) 386 /* Pointer to parallel handler if serial insn. 387 Pointer to readahead/writeback handler if parallel insn. */ 388 struct idesc *par_idesc; 389#endif 390 391 /* Instruction number (index in IDESC table, profile table). 392 Also used to switch on in non-gcc semantic switches. */ 393 int num; 394 395 /* Semantic format id. */ 396 int sfmt; 397 398 /* instruction data (name, attributes, size, etc.) */ 399 const CGEN_INSN *idata; 400 401 /* instruction attributes, copied from `idata' for speed */ 402 const CGEN_INSN_ATTR_TYPE *attrs; 403 404 /* instruction length in bytes, copied from `idata' for speed */ 405 int length; 406 407 /* profiling/modelling support */ 408 const INSN_TIMING *timing; 409}; 410 411/* Tracing/profiling. */ 412 413/* Return non-zero if a before/after handler is needed. 414 When tracing/profiling a selected range there's no need to slow 415 down simulation of the other insns (except to get more accurate data!). 416 417 ??? May wish to profile all insns if doing insn tracing, or to 418 get more accurate cycle data. 419 420 First test ANY_P so we avoid a potentially expensive HIT_P call 421 [if there are lots of address ranges]. */ 422 423#define PC_IN_TRACE_RANGE_P(cpu, pc) \ 424 (TRACE_ANY_P (cpu) \ 425 && ADDR_RANGE_HIT_P (TRACE_RANGE (CPU_TRACE_DATA (cpu)), (pc))) 426#define PC_IN_PROFILE_RANGE_P(cpu, pc) \ 427 (PROFILE_ANY_P (cpu) \ 428 && ADDR_RANGE_HIT_P (PROFILE_RANGE (CPU_PROFILE_DATA (cpu)), (pc))) 429 430#endif /* CGEN_ENGINE_H */ 431