* sim-base.h (sim_state_base): Move `magic' to end of struct.
[external/binutils.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