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