* sim-base.h (sim_state_base): Move `magic' to end of struct.
[binutils-gdb.git] / sim / common / sim-n-core.h
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21
22 #ifndef N
23 #error "N must be #defined"
24 #endif
25 #ifndef M
26 #define M N
27 #endif
28
29 #include "sim-xcat.h"
30
31 /* NOTE: see end of file for #undef of these macros */
32
33 #define unsigned_M XCONCAT2(unsigned_,M)
34
35 #define T2H_M XCONCAT2(T2H_,M)
36 #define H2T_M XCONCAT2(H2T_,M)
37 #define SWAP_M XCONCAT2(SWAP_,M)
38
39 #define sim_core_read_aligned_N XCONCAT2(sim_core_read_aligned_,N)
40 #define sim_core_read_unaligned_N XCONCAT2(sim_core_read_unaligned_,N)
41 #define sim_core_read_misaligned_N XCONCAT2(sim_core_read_misaligned_,N)
42 #define sim_core_write_aligned_N XCONCAT2(sim_core_write_aligned_,N)
43 #define sim_core_write_unaligned_N XCONCAT2(sim_core_write_unaligned_,N)
44 #define sim_core_write_misaligned_N XCONCAT2(sim_core_write_misaligned_,N)
45 #define sim_core_trace_M XCONCAT2(sim_core_trace_,M)
46
47
48 /* TAGS: sim_core_trace_1 sim_core_trace_2 */
49 /* TAGS: sim_core_trace_4 sim_core_trace_8 */
50 /* TAGS: sim_core_trace_16 */
51
52 #if (M == N)
53 STATIC_SIM_CORE(void)
54 sim_core_trace_M (sim_cpu *cpu,
55 sim_cia cia,
56 int line_nr,
57 transfer_type type,
58 sim_core_maps map,
59 address_word addr,
60 unsigned_M val,
61 int nr_bytes)
62 {
63 char *transfer = (type == read_transfer ? "read" : "write");
64 char *direction = (type == read_transfer ? "->" : "<-");
65
66 if (TRACE_DEBUG_P (cpu))
67 trace_printf (CPU_STATE (cpu), cpu, "sim-n-core.h:%d: ", line_nr);
68
69 #if (M == 16)
70 trace_printf (CPU_STATE (cpu), cpu,
71 "%s-%d %s:0x%08lx %s 0x%08lx%08lx%08lx%08lx\n",
72 transfer, nr_bytes,
73 sim_core_map_to_str (map),
74 (unsigned long) addr,
75 direction,
76 (unsigned long) V4_16 (val, 0),
77 (unsigned long) V4_16 (val, 1),
78 (unsigned long) V4_16 (val, 2),
79 (unsigned long) V4_16 (val, 3));
80 #endif
81 #if (M == 8)
82 trace_printf (CPU_STATE (cpu), cpu,
83 "%s-%d %s:0x%08lx %s 0x%08lx%08lx\n",
84 transfer, nr_bytes,
85 sim_core_map_to_str (map),
86 (unsigned long) addr,
87 direction,
88 (unsigned long) V4_8 (val, 0),
89 (unsigned long) V4_8 (val, 1));
90 #endif
91 #if (M == 4)
92 trace_printf (CPU_STATE (cpu), cpu,
93 "%s-%d %s:0x%08lx %s 0x%08lx\n",
94 transfer,
95 nr_bytes,
96 sim_core_map_to_str (map),
97 (unsigned long) addr,
98 direction,
99 (unsigned long) val);
100 #endif
101 #if (M == 2)
102 trace_printf (CPU_STATE (cpu), cpu,
103 "%s-%d %s:0x%08lx %s 0x%04lx\n",
104 transfer,
105 nr_bytes,
106 sim_core_map_to_str (map),
107 (unsigned long) addr,
108 direction,
109 (unsigned long) val);
110 #endif
111 #if (M == 1)
112 trace_printf (CPU_STATE (cpu), cpu,
113 "%s-%d %s:0x%08lx %s 0x%02lx\n",
114 transfer,
115 nr_bytes,
116 sim_core_map_to_str (map),
117 (unsigned long) addr,
118 direction,
119 (unsigned long) val);
120 #endif
121 }
122 #endif
123
124
125 /* TAGS: sim_core_read_aligned_1 sim_core_read_aligned_2 */
126 /* TAGS: sim_core_read_aligned_4 sim_core_read_aligned_8 */
127 /* TAGS: sim_core_read_aligned_16 */
128
129 #if (M == N)
130 INLINE_SIM_CORE(unsigned_M)
131 sim_core_read_aligned_N(sim_cpu *cpu,
132 sim_cia cia,
133 sim_core_maps map,
134 address_word xaddr)
135 {
136 sim_cpu_core *cpu_core = CPU_CORE (cpu);
137 sim_core_common *core = &cpu_core->common;
138 unsigned_M val;
139 sim_core_mapping *mapping;
140 address_word addr;
141 #if WITH_XOR_ENDIAN != 0
142 if (WITH_XOR_ENDIAN)
143 addr = xaddr ^ cpu_core->xor[(N - 1) % WITH_XOR_ENDIAN];
144 else
145 #endif
146 addr = xaddr;
147 mapping = sim_core_find_mapping (core, map, addr, N, read_transfer, 1 /*abort*/, cpu, cia);
148 #if (WITH_DEVICES)
149 if (WITH_CALLBACK_MEMORY && mapping->device != NULL) {
150 unsigned_M data;
151 if (device_io_read_buffer (mapping->device, &data, mapping->space, addr, N) != N)
152 device_error (mapping->device, "internal error - %s - io_read_buffer should not fail",
153 XSTRING (sim_core_read_aligned_N));
154 val = T2H_M (data);
155 }
156 else
157 #endif
158 val = T2H_M (*(unsigned_M*) sim_core_translate (mapping, addr));
159 PROFILE_COUNT_CORE (cpu, addr, N, map);
160 if (TRACE_P (cpu, TRACE_CORE_IDX))
161 sim_core_trace_M (cpu, cia, __LINE__, read_transfer, map, addr, val, N);
162 return val;
163 }
164 #endif
165
166 /* TAGS: sim_core_read_unaligned_1 sim_core_read_unaligned_2 */
167 /* TAGS: sim_core_read_unaligned_4 sim_core_read_unaligned_8 */
168 /* TAGS: sim_core_read_unaligned_16 */
169
170 #if (M == N && N > 1)
171 INLINE_SIM_CORE(unsigned_M)
172 sim_core_read_unaligned_N(sim_cpu *cpu,
173 sim_cia cia,
174 sim_core_maps map,
175 address_word addr)
176 {
177 int alignment = N - 1;
178 /* if hardwired to forced alignment just do it */
179 if (WITH_ALIGNMENT == FORCED_ALIGNMENT)
180 return sim_core_read_aligned_N (cpu, cia, map, addr & ~alignment);
181 else if ((addr & alignment) == 0)
182 return sim_core_read_aligned_N (cpu, cia, map, addr);
183 else
184 switch (CURRENT_ALIGNMENT)
185 {
186 case STRICT_ALIGNMENT:
187 SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
188 read_transfer, sim_core_unaligned_signal);
189 case NONSTRICT_ALIGNMENT:
190 {
191 unsigned_M val;
192 if (sim_core_xor_read_buffer (CPU_STATE (cpu), cpu, map, &val, addr, N) != N)
193 SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
194 read_transfer, sim_core_unaligned_signal);
195 val = T2H_M(val);
196 PROFILE_COUNT_CORE (cpu, addr, N, map);
197 if (TRACE_P (cpu, TRACE_CORE_IDX))
198 sim_core_trace_M (cpu, cia, __LINE__, read_transfer, map, addr, val, N);
199 return val;
200 }
201 case FORCED_ALIGNMENT:
202 return sim_core_read_aligned_N (cpu, cia, map, addr & ~alignment);
203 case MIXED_ALIGNMENT:
204 sim_engine_abort (CPU_STATE (cpu), cpu, cia,
205 "internal error - %s - mixed alignment",
206 XSTRING (sim_core_read_unaligned_N));
207 default:
208 sim_engine_abort (CPU_STATE (cpu), cpu, cia,
209 "internal error - %s - bad switch",
210 XSTRING (sim_core_read_unaligned_N));
211 /* to keep some compilers happy, we return a dummy */
212 {
213 unsigned_M val[1] = { 0 };
214 return val[0];
215 }
216 }
217 }
218 #endif
219
220 /* TAGS: sim_core_read_misaligned_3 sim_core_read_misaligned_5 */
221 /* TAGS: sim_core_read_misaligned_6 sim_core_read_misaligned_7 */
222
223 #if (M != N)
224 INLINE_SIM_CORE(unsigned_M)
225 sim_core_read_misaligned_N(sim_cpu *cpu,
226 sim_cia cia,
227 sim_core_maps map,
228 address_word addr)
229 {
230 unsigned_M val = 0;
231 if (sim_core_xor_read_buffer (CPU_STATE (cpu), cpu, map, &val, addr, N) != N)
232 SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
233 read_transfer, sim_core_unaligned_signal);
234 if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
235 val = SWAP_M (val);
236 if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
237 val >>= (M - N) * 8;
238 PROFILE_COUNT_CORE (cpu, addr, N, map);
239 if (TRACE_P (cpu, TRACE_CORE_IDX))
240 sim_core_trace_M (cpu, cia, __LINE__, read_transfer, map, addr, val, N);
241 return val;
242 }
243 #endif
244
245 /* TAGS: sim_core_write_aligned_1 sim_core_write_aligned_2 */
246 /* TAGS: sim_core_write_aligned_4 sim_core_write_aligned_8 */
247 /* TAGS: sim_core_write_aligned_16 */
248
249 #if (M == N)
250 INLINE_SIM_CORE(void)
251 sim_core_write_aligned_N(sim_cpu *cpu,
252 sim_cia cia,
253 sim_core_maps map,
254 address_word xaddr,
255 unsigned_M val)
256 {
257 sim_cpu_core *cpu_core = CPU_CORE (cpu);
258 sim_core_common *core = &cpu_core->common;
259 sim_core_mapping *mapping;
260 address_word addr;
261 #if WITH_XOR_ENDIAN != 0
262 if (WITH_XOR_ENDIAN)
263 addr = xaddr ^ cpu_core->xor[(N - 1) % WITH_XOR_ENDIAN];
264 else
265 #endif
266 addr = xaddr;
267 mapping = sim_core_find_mapping (core, map, addr, N, write_transfer, 1 /*abort*/, cpu, cia);
268 #if (WITH_DEVICES)
269 if (WITH_CALLBACK_MEMORY && mapping->device != NULL) {
270 unsigned_M data = H2T_M (val);
271 if (device_io_write_buffer (mapping->device, &data, mapping->space, addr, N, cpu, cia) != N)
272 device_error (mapping->device, "internal error - %s - io_write_buffer should not fail",
273 XSTRING (sim_core_write_aligned_N));
274 }
275 else
276 #endif
277 *(unsigned_M*) sim_core_translate (mapping, addr) = H2T_M (val);
278 PROFILE_COUNT_CORE (cpu, addr, N, map);
279 if (TRACE_P (cpu, TRACE_CORE_IDX))
280 sim_core_trace_M (cpu, cia, __LINE__, write_transfer, map, addr, val, N);
281 }
282 #endif
283
284 /* TAGS: sim_core_write_unaligned_1 sim_core_write_unaligned_2 */
285 /* TAGS: sim_core_write_unaligned_4 sim_core_write_unaligned_8 */
286 /* TAGS: sim_core_write_unaligned_16 */
287
288 #if (M == N && N > 1)
289 INLINE_SIM_CORE(void)
290 sim_core_write_unaligned_N(sim_cpu *cpu,
291 sim_cia cia,
292 sim_core_maps map,
293 address_word addr,
294 unsigned_M val)
295 {
296 int alignment = N - 1;
297 /* if hardwired to forced alignment just do it */
298 if (WITH_ALIGNMENT == FORCED_ALIGNMENT)
299 sim_core_write_aligned_N (cpu, cia, map, addr & ~alignment, val);
300 else if ((addr & alignment) == 0)
301 sim_core_write_aligned_N (cpu, cia, map, addr, val);
302 else
303 switch (CURRENT_ALIGNMENT)
304 {
305 case STRICT_ALIGNMENT:
306 SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
307 write_transfer, sim_core_unaligned_signal);
308 break;
309 case NONSTRICT_ALIGNMENT:
310 {
311 unsigned_M data = H2T_M (val);
312 if (sim_core_xor_write_buffer (CPU_STATE (cpu), cpu, map, &data, addr, N) != N)
313 SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
314 write_transfer, sim_core_unaligned_signal);
315 PROFILE_COUNT_CORE (cpu, addr, N, map);
316 if (TRACE_P (cpu, TRACE_CORE_IDX))
317 sim_core_trace_M (cpu, cia, __LINE__, write_transfer, map, addr, val, N);
318 break;
319 }
320 case FORCED_ALIGNMENT:
321 sim_core_write_aligned_N (cpu, cia, map, addr & ~alignment, val);
322 break;
323 case MIXED_ALIGNMENT:
324 sim_engine_abort (CPU_STATE (cpu), cpu, cia,
325 "internal error - %s - mixed alignment",
326 XSTRING (sim_core_write_unaligned_N));
327 break;
328 default:
329 sim_engine_abort (CPU_STATE (cpu), cpu, cia,
330 "internal error - %s - bad switch",
331 XSTRING (sim_core_write_unaligned_N));
332 break;
333 }
334 }
335 #endif
336
337 /* TAGS: sim_core_write_misaligned_3 sim_core_write_misaligned_5 */
338 /* TAGS: sim_core_write_misaligned_6 sim_core_write_misaligned_7 */
339
340 #if (M != N)
341 INLINE_SIM_CORE(void)
342 sim_core_write_misaligned_N(sim_cpu *cpu,
343 sim_cia cia,
344 sim_core_maps map,
345 address_word addr,
346 unsigned_M val)
347 {
348 unsigned_M data = val;
349 if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
350 data <<= (M - N) * 8;
351 if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
352 data = SWAP_M (data);
353 if (sim_core_xor_write_buffer (CPU_STATE (cpu), cpu, map, &data, addr, N) != N)
354 SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
355 write_transfer, sim_core_unaligned_signal);
356 PROFILE_COUNT_CORE (cpu, addr, N, map);
357 if (TRACE_P (cpu, TRACE_CORE_IDX))
358 sim_core_trace_M (cpu, cia, __LINE__, write_transfer, map, addr, val, N);
359 }
360 #endif
361
362
363 /* NOTE: see start of file for #define of these macros */
364 #undef unsigned_M
365 #undef T2H_M
366 #undef H2T_M
367 #undef SWAP_M
368 #undef sim_core_read_aligned_N
369 #undef sim_core_read_unaligned_N
370 #undef sim_core_read_misaligned_N
371 #undef sim_core_write_aligned_N
372 #undef sim_core_write_unaligned_N
373 #undef sim_core_write_misaligned_N
374 #undef sim_core_trace_M
375 #undef M
376 #undef N