Commit | Line | Data |
---|---|---|
d4df1e30 DE |
1 | /* Simulator header for the cgen engine. |
2 | Copyright (C) 1998 Free Software Foundation, Inc. | |
3 | Contributed by Cygnus Support. | |
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 2, or (at your option) | |
10 | 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 along | |
18 | with this program; if not, write to the Free Software Foundation, Inc., | |
19 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
20 | ||
8c7dc9ff | 21 | /* This file must be included after eng.h and ${cpu}.h have been included. */ |
d4df1e30 DE |
22 | |
23 | #ifndef CGEN_ENGINE_H | |
24 | #define CGEN_ENGINE_H | |
25 | ||
d4df1e30 DE |
26 | /* Semantic functions come in six versions on two axes: |
27 | fast/full-featured, and using one of the simple/scache/compilation engines. | |
28 | A full featured simulator is always provided. --enable-sim-fast includes | |
29 | support for fast execution by duplicating the semantic code but leaving | |
30 | out all features like tracing and profiling. | |
31 | Using the scache is selected with --enable-sim-scache. */ | |
32 | /* FIXME: --enable-sim-fast not implemented yet. */ | |
33 | /* FIXME: undecided how to handle WITH_SCACHE_PBB. */ | |
34 | ||
35 | /* Types of the machine generated extract and semantic fns. */ | |
36 | typedef void (EXTRACT_FN) (SIM_CPU *, PCADDR, insn_t, ARGBUF *); | |
8c7dc9ff | 37 | #if HAVE_PARALLEL_INSNS |
d4df1e30 DE |
38 | typedef SEM_PC (SEMANTIC_FN) (SIM_CPU *, SEM_ARG, PAREXEC *); |
39 | #else | |
40 | typedef SEM_PC (SEMANTIC_FN) (SIM_CPU *, SEM_ARG); | |
41 | #endif | |
42 | ||
43 | union sem { | |
44 | #if ! WITH_SEM_SWITCH_FULL | |
45 | SEMANTIC_FN *sem_full; | |
46 | #endif | |
47 | #if ! WITH_SEM_SWITCH_FAST | |
48 | SEMANTIC_FN *sem_fast; | |
49 | #endif | |
50 | #if WITH_SEM_SWITCH_FULL || WITH_SEM_SWITCH_FAST | |
51 | #ifdef __GNUC__ | |
52 | void *sem_case; | |
53 | #else | |
54 | int sem_case; | |
55 | #endif | |
56 | #endif | |
57 | }; | |
58 | ||
59 | /* Set the appropriate semantic handler in ABUF. */ | |
60 | ||
61 | #if WITH_SEM_SWITCH_FULL | |
62 | #ifdef __GNUC__ | |
63 | #define SEM_SET_FULL_CODE(abuf, idesc) \ | |
64 | do { (abuf)->semantic.sem_case = (idesc)->sem_full_lab; } while (0) | |
65 | #else | |
66 | #define SEM_SET_FULL_CODE(abuf, idesc) \ | |
67 | do { (abuf)->semantic.sem_case = (idesc)->num; } while (0) | |
68 | #endif | |
69 | #else | |
70 | #define SEM_SET_FULL_CODE(abuf, idesc) \ | |
71 | do { (abuf)->semantic.sem_full = (idesc)->sem_full; } while (0) | |
72 | #endif | |
73 | ||
74 | #if WITH_SEM_SWITCH_FAST | |
75 | #ifdef __GNUC__ | |
76 | #define SEM_SET_FAST_CODE(abuf, idesc) \ | |
77 | do { (abuf)->semantic.sem_case = (idesc)->sem_fast_lab; } while (0) | |
78 | #else | |
79 | #define SEM_SET_FAST_CODE(abuf, idesc) \ | |
80 | do { (abuf)->semantic.sem_case = (idesc)->num; } while (0) | |
81 | #endif | |
82 | #else | |
83 | #define SEM_SET_FAST_CODE(abuf, idesc) \ | |
84 | do { (abuf)->semantic.sem_fast = (idesc)->sem_fast; } while (0) | |
85 | #endif | |
86 | ||
87 | #define SEM_SET_CODE(abuf, idesc, fast_p) \ | |
88 | do { \ | |
89 | if (fast_p) \ | |
90 | SEM_SET_FAST_CODE ((abuf), (idesc)); \ | |
91 | else \ | |
92 | SEM_SET_FULL_CODE ((abuf), (idesc)); \ | |
93 | } while (0) | |
94 | ||
95 | #define IDESC_CTI_P(idesc) \ | |
96 | ((CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->opcode)) \ | |
97 | & (CGEN_ATTR_MASK (CGEN_INSN_COND_CTI) \ | |
98 | | CGEN_ATTR_MASK (CGEN_INSN_UNCOND_CTI))) \ | |
99 | != 0) | |
100 | #define IDESC_SKIP_P(idesc) \ | |
101 | ((CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->opcode)) \ | |
102 | & CGEN_ATTR_MASK (CGEN_INSN_SKIP_CTI)) \ | |
103 | != 0) | |
d4df1e30 DE |
104 | |
105 | /* These are used so that we can compile two copies of the semantic code, | |
106 | one with full feature support and one without that runs fast(er). */ | |
107 | /* FIXME: Eventually delete extraction if not using scache. */ | |
108 | #define EX_FN_NAME(cpu,fn) XCONCAT3 (cpu,_ex_,fn) | |
109 | #define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_sem_,fn) | |
110 | #define SEMF_FN_NAME(cpu,fn) XCONCAT3 (cpu,_semf_,fn) | |
111 | ||
112 | #if WITH_SCACHE | |
113 | ||
114 | #define CIA_ADDR(cia) (cia) | |
115 | ||
116 | /* semantics.c support */ | |
117 | #define SEM_ARGBUF(sem_arg) (& (sem_arg) -> argbuf) | |
118 | #define SEM_INSN(sem_arg) shouldnt_be_used | |
119 | #define SEM_NEXT_VPC(sc, len) ((sc) + 1) | |
120 | ||
121 | #if WITH_SCACHE_PBB | |
122 | ||
123 | /* Update the instruction counter. */ | |
124 | #define PBB_UPDATE_INSN_COUNT(cpu,sc) \ | |
125 | (CPU_INSN_COUNT (cpu) += SEM_ARGBUF (sc) -> fields.chain.insn_count) | |
126 | ||
127 | /* Value for br_addr_ptr indicating branch wasn't taken. */ | |
128 | #define SEM_BRANCH_UNTAKEN ((SEM_PC *) 0) | |
129 | /* Value for br_addr_ptr indicating branch was taken to uncacheable | |
130 | address (e.g. j reg). */ | |
131 | #define SEM_BRANCH_UNCACHEABLE ((SEM_PC *) 1) | |
132 | ||
133 | /* ??? Only necessary if SEM_BRANCH_VIA_CACHE will be used, | |
134 | but for simplicity it's done this way. */ | |
135 | #define SEM_BRANCH_INIT_EXTRACT(abuf) \ | |
136 | do { (abuf)->fields.cti.addr_cache = 0; } while (0) | |
137 | ||
138 | /* Do not append a `;' to invocations of this. | |
139 | npc,npc_ptr are for communication between the cti insn and cti-chain. */ | |
140 | #define SEM_BRANCH_INIT \ | |
141 | PCADDR npc = 0; /* assign a value for -Wall */ \ | |
142 | SEM_PC *npc_ptr = SEM_BRANCH_UNTAKEN; | |
143 | /* SEM_IN_SWITCH is defined at the top of the mainloop.c files | |
144 | generated by genmloop.sh. It exists so generated semantic code needn't | |
145 | care whether it's being put in a switch or in a function. */ | |
146 | #ifdef SEM_IN_SWITCH | |
147 | /* Do not append a `;' to invocations of this. | |
148 | ??? Unnecessary here, but for consistency with ..._INIT. */ | |
149 | #define SEM_BRANCH_FINI \ | |
150 | { \ | |
151 | pbb_br_npc = npc; \ | |
152 | pbb_br_npc_ptr = npc_ptr; \ | |
153 | } | |
154 | #else /* 1 semantic function per instruction */ | |
155 | /* Do not append a `;' to invocations of this. | |
156 | ??? Unnecessary here, but for consistency with ..._INIT. */ | |
157 | #define SEM_BRANCH_FINI \ | |
158 | { \ | |
159 | CPU_PBB_BR_NPC (current_cpu) = npc; \ | |
160 | CPU_PBB_BR_NPC_PTR (current_cpu) = npc_ptr; \ | |
161 | } | |
162 | #endif | |
163 | ||
164 | /* Return address of cached branch address value. */ | |
165 | #define SEM_BRANCH_ADDR_CACHE(sem_arg) \ | |
166 | (& SEM_ARGBUF (sem_arg)->fields.cti.addr_cache) | |
167 | #define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar, cachevarptr) \ | |
168 | do { \ | |
169 | npc = (newval); \ | |
170 | npc_ptr = (cachevarptr); \ | |
171 | } while (0) | |
172 | #define SEM_BRANCH_VIA_ADDR(cpu, sc, newval, pcvar) \ | |
173 | do { \ | |
174 | npc = (newval); \ | |
175 | npc_ptr = SEM_BRANCH_UNCACHEABLE; \ | |
176 | } while (0) | |
177 | ||
178 | #else /* ! WITH_SCACHE_PBB */ | |
179 | ||
180 | #define SEM_BRANCH_INIT | |
181 | #define SEM_BRANCH_FINI | |
182 | ||
183 | #define SEM_BRANCH_ADDR_CACHE(sem_arg) shouldnt_be_used | |
184 | #define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar, cachevar) \ | |
185 | do { \ | |
186 | (pcvar) = (newval); \ | |
187 | } while (0) | |
188 | #define SEM_BRANCH_VIA_ADDR(cpu, sc, newval, pcvar) \ | |
189 | do { \ | |
190 | (pcvar) = (newval); \ | |
191 | } while (0) | |
192 | ||
193 | #endif /* ! WITH_SCACHE_PBB */ | |
194 | ||
195 | /* Return address a branch insn will branch to. | |
196 | This is only used during tracing. */ | |
197 | #define SEM_NEW_PC_ADDR(new_pc) (new_pc) | |
198 | ||
199 | #else /* ! WITH_SCACHE */ | |
200 | ||
201 | #define CIA_ADDR(cia) (cia) | |
202 | ||
203 | /* semantics.c support */ | |
204 | #define SEM_ARGBUF(sem_arg) (sem_arg) | |
205 | #define SEM_INSN(sem_arg) (SEM_ARGBUF (sem_arg) -> insn) | |
206 | /* FIXME:wip */ | |
207 | #define SEM_NEXT_VPC(abuf, len) ((abuf) -> addr + (abuf) -> length) | |
208 | ||
209 | #define SEM_BRANCH_INIT | |
210 | #define SEM_BRANCH_FINI | |
211 | ||
212 | #define SEM_BRANCH_ADDR_CACHE(sem_arg) shouldnt_be_used | |
213 | #define SEM_BRANCH_VIA_CACHE(cpu, abuf, newval, pcvar, cachevar) \ | |
214 | do { \ | |
215 | (pcvar) = (newval); \ | |
216 | } while (0) | |
217 | #define SEM_BRANCH_VIA_ADDR(cpu, abuf, newval, pcvar) \ | |
218 | do { \ | |
219 | (pcvar) = (newval); \ | |
220 | } while (0) | |
221 | ||
222 | #define SEM_NEW_PC_ADDR(new_pc) (new_pc) | |
223 | ||
224 | #endif /* ! WITH_SCACHE */ | |
225 | ||
226 | #endif /* CGEN_ENGINE_H */ |