1 /* Simulator header for cgen scache support. 2 Copyright (C) 1998-2017 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 #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 30 typedef struct { 31 IADDR pc; 32 SCACHE *sc; 33 } SCACHE_MAP; 34 35 typedef 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. */ 113 MODULE_INSTALL_FN scache_install; 114 115 /* Lookup a PC value in the scache [compilation only]. */ 116 extern SCACHE * scache_lookup (SIM_CPU *, IADDR); 117 /* Return a pointer to at least N buffers. */ 118 extern SCACHE *scache_lookup_or_alloc (SIM_CPU *, IADDR, int, SCACHE **); 119 /* Flush all cpu's scaches. */ 120 extern void scache_flush (SIM_DESC); 121 /* Flush a cpu's scache. */ 122 extern void scache_flush_cpu (SIM_CPU *); 123 124 /* Scache profiling support. */ 125 126 /* Print summary scache usage information. */ 127 extern void scache_print_profile (SIM_CPU *cpu, int verbose); 128 129 #if WITH_PROFILE_SCACHE_P 130 131 #define PROFILE_COUNT_SCACHE_HIT(cpu) \ 132 do { \ 133 if (CPU_PROFILE_FLAGS (cpu) [PROFILE_SCACHE_IDX]) \ 134 ++ CPU_SCACHE_HITS (cpu); \ 135 } while (0) 136 #define PROFILE_COUNT_SCACHE_MISS(cpu) \ 137 do { \ 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) \ 142 do { \ 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) \ 147 do { \ 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