1/* Simulator header for cgen scache support. 2 Copyright (C) 1998-2020 Free Software Foundation, Inc. 3 Contributed by Cygnus Solutions. 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#ifndef CGEN_SCACHE_H 21#define CGEN_SCACHE_H 22 23#ifndef WITH_SCACHE 24#define WITH_SCACHE 0 25#endif 26 27/* When caching bb's, instructions are extracted into "chains". 28 SCACHE_MAP is a hash table into these chains. */ 29 30typedef struct { 31 IADDR pc; 32 SCACHE *sc; 33} SCACHE_MAP; 34 35typedef struct cpu_scache { 36 /* Simulator cache size. Must be a power of 2. 37 This is the number of elements in the `cache' member. */ 38 unsigned int size; 39#define CPU_SCACHE_SIZE(cpu) ((cpu) -> cgen_cpu.scache.size) 40 /* The cache. */ 41 SCACHE *cache; 42#define CPU_SCACHE_CACHE(cpu) ((cpu) -> cgen_cpu.scache.cache) 43 44#if WITH_SCACHE_PBB 45 /* Number of hash chains. Must be a power of 2. */ 46 unsigned int num_hash_chains; 47#define CPU_SCACHE_NUM_HASH_CHAINS(cpu) ((cpu) -> cgen_cpu.scache.num_hash_chains) 48 /* Number of entries in each hash chain. 49 The hash table is a statically allocated NxM array where 50 N = num_hash_chains 51 M = num_hash_chain_entries. */ 52 unsigned int num_hash_chain_entries; 53#define CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES(cpu) ((cpu) -> cgen_cpu.scache.num_hash_chain_entries) 54 /* Maximum number of instructions in a chain. 55 ??? This just let's us set a static size of chain_lengths table. 56 In a simulation that handles more than just the cpu, this might also be 57 used to keep too many instructions from being executed before checking 58 for events (or some such). */ 59 unsigned int max_chain_length; 60#define CPU_SCACHE_MAX_CHAIN_LENGTH(cpu) ((cpu) -> cgen_cpu.scache.max_chain_length) 61 /* Special scache entry for (re)starting bb extraction. */ 62 SCACHE *pbb_begin; 63#define CPU_SCACHE_PBB_BEGIN(cpu) ((cpu) -> cgen_cpu.scache.pbb_begin) 64 /* Hash table into cached chains. */ 65 SCACHE_MAP *hash_table; 66#define CPU_SCACHE_HASH_TABLE(cpu) ((cpu) -> cgen_cpu.scache.hash_table) 67 /* Next free entry in cache. */ 68 SCACHE *next_free; 69#define CPU_SCACHE_NEXT_FREE(cpu) ((cpu) -> cgen_cpu.scache.next_free) 70 71 /* Kind of branch being taken. 72 Only used by functional semantics, not switch form. */ 73 SEM_BRANCH_TYPE pbb_br_type; 74#define CPU_PBB_BR_TYPE(cpu) ((cpu) -> cgen_cpu.scache.pbb_br_type) 75 /* Target's branch address. */ 76 IADDR pbb_br_npc; 77#define CPU_PBB_BR_NPC(cpu) ((cpu) -> cgen_cpu.scache.pbb_br_npc) 78#endif /* WITH_SCACHE_PBB */ 79 80#if WITH_PROFILE_SCACHE_P 81 /* Cache hits, misses. */ 82 unsigned long hits, misses; 83#define CPU_SCACHE_HITS(cpu) ((cpu) -> cgen_cpu.scache.hits) 84#define CPU_SCACHE_MISSES(cpu) ((cpu) -> cgen_cpu.scache.misses) 85 86#if WITH_SCACHE_PBB 87 /* Chain length counts. 88 Each element is a count of the number of chains created with that 89 length. */ 90 unsigned long *chain_lengths; 91#define CPU_SCACHE_CHAIN_LENGTHS(cpu) ((cpu) -> cgen_cpu.scache.chain_lengths) 92 /* Number of times cache was flushed due to its being full. */ 93 unsigned long full_flushes; 94#define CPU_SCACHE_FULL_FLUSHES(cpu) ((cpu) -> cgen_cpu.scache.full_flushes) 95#endif 96#endif 97} CPU_SCACHE; 98 99/* Hash a PC value. 100 This is split into two parts to help with moving as much of the 101 computation out of the main loop. */ 102#define CPU_SCACHE_HASH_MASK(cpu) (CPU_SCACHE_SIZE (cpu) - 1) 103#define SCACHE_HASH_PC(pc, mask) \ 104((CGEN_MIN_INSN_SIZE == 2 ? ((pc) >> 1) \ 105 : CGEN_MIN_INSN_SIZE == 4 ? ((pc) >> 2) \ 106 : (pc)) \ 107 & (mask)) 108 109/* Non-zero if cache is in use. */ 110#define USING_SCACHE_P(sd) (STATE_SCACHE_SIZE (sd) > 0) 111 112/* Install the simulator cache into the simulator. */ 113MODULE_INSTALL_FN scache_install; 114 115/* Lookup a PC value in the scache [compilation only]. */ 116extern SCACHE * scache_lookup (SIM_CPU *, IADDR); 117/* Return a pointer to at least N buffers. */ 118extern SCACHE *scache_lookup_or_alloc (SIM_CPU *, IADDR, int, SCACHE **); 119/* Flush all cpu's scaches. */ 120extern void scache_flush (SIM_DESC); 121/* Flush a cpu's scache. */ 122extern void scache_flush_cpu (SIM_CPU *); 123 124/* Scache profiling support. */ 125 126/* Print summary scache usage information. */ 127extern void scache_print_profile (SIM_CPU *cpu, int verbose); 128 129#if WITH_PROFILE_SCACHE_P 130 131#define PROFILE_COUNT_SCACHE_HIT(cpu) \ 132do { \ 133 if (CPU_PROFILE_FLAGS (cpu) [PROFILE_SCACHE_IDX]) \ 134 ++ CPU_SCACHE_HITS (cpu); \ 135} while (0) 136#define PROFILE_COUNT_SCACHE_MISS(cpu) \ 137do { \ 138 if (CPU_PROFILE_FLAGS (cpu) [PROFILE_SCACHE_IDX]) \ 139 ++ CPU_SCACHE_MISSES (cpu); \ 140} while (0) 141#define PROFILE_COUNT_SCACHE_CHAIN_LENGTH(cpu,length) \ 142do { \ 143 if (CPU_PROFILE_FLAGS (cpu) [PROFILE_SCACHE_IDX]) \ 144 ++ CPU_SCACHE_CHAIN_LENGTHS (cpu) [length]; \ 145} while (0) 146#define PROFILE_COUNT_SCACHE_FULL_FLUSH(cpu) \ 147do { \ 148 if (CPU_PROFILE_FLAGS (cpu) [PROFILE_SCACHE_IDX]) \ 149 ++ CPU_SCACHE_FULL_FLUSHES (cpu); \ 150} while (0) 151 152#else 153 154#define PROFILE_COUNT_SCACHE_HIT(cpu) 155#define PROFILE_COUNT_SCACHE_MISS(cpu) 156#define PROFILE_COUNT_SCACHE_CHAIN_LENGTH(cpu,length) 157#define PROFILE_COUNT_SCACHE_FULL_FLUSH(cpu) 158 159#endif 160 161#endif /* CGEN_SCACHE_H */ 162