Rewrite the MIPS simulator's memory model so that it uses the generic
[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 #if (M == 16)
66   trace_printf (CPU_STATE (cpu), cpu,
67                 "sim-n-core.h:%d: %s-%d %s:0x%08lx %s 0x%08lx%08lx%08lx%08lx\n",
68                 line_nr,
69                 transfer, nr_bytes,
70                 sim_core_map_to_str (map),
71                 (unsigned long) addr,
72                 direction,
73                 (unsigned long) V4_16 (val, 0),
74                 (unsigned long) V4_16 (val, 1),
75                 (unsigned long) V4_16 (val, 2),
76                 (unsigned long) V4_16 (val, 3));
77 #endif
78 #if (M == 8)
79   trace_printf (CPU_STATE (cpu), cpu,
80                 "sim-n-core.h:%d: %s-%d %s:0x%08lx %s 0x%08lx%08lx\n",
81                 line_nr,
82                 transfer, nr_bytes,
83                 sim_core_map_to_str (map),
84                 (unsigned long) addr,
85                 direction,
86                 (unsigned long) V4_8 (val, 0),
87                 (unsigned long) V4_8 (val, 1));
88 #endif
89 #if (M == 4)
90   trace_printf (CPU_STATE (cpu), cpu,
91                 "sim-n-core.h:%d: %s-%d %s:0x%08lx %s 0x%08lx\n",
92                 line_nr,
93                 transfer,
94                 nr_bytes,
95                 sim_core_map_to_str (map),
96                 (unsigned long) addr,
97                 direction,
98                 (unsigned long) val);
99 #endif
100 #if (M == 2)
101   trace_printf (CPU_STATE (cpu), cpu,
102                 "sim-n-core.h:%d: %s-%d %s:0x%08lx %s 0x%04lx\n",
103                 line_nr,
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                 "sim-n-core.h:%d: %s-%d %s:0x%08lx %s 0x%02lx\n",
114                 line_nr,
115                 transfer,
116                 nr_bytes,
117                 sim_core_map_to_str (map),
118                 (unsigned long) addr,
119                 direction,
120                 (unsigned long) val);
121 #endif
122 }
123 #endif
124
125   
126 /* TAGS: sim_core_read_aligned_1 sim_core_read_aligned_2 */
127 /* TAGS: sim_core_read_aligned_4 sim_core_read_aligned_8 */
128 /* TAGS: sim_core_read_aligned_16 */
129
130 #if (M == N)
131 INLINE_SIM_CORE(unsigned_M)
132 sim_core_read_aligned_N(sim_cpu *cpu,
133                         sim_cia cia,
134                         sim_core_maps map,
135                         address_word xaddr)
136 {
137   sim_cpu_core *cpu_core = CPU_CORE (cpu);
138   sim_core_common *core = &cpu_core->common;
139   unsigned_M val;
140   sim_core_mapping *mapping;
141   address_word addr;
142 #if WITH_XOR_ENDIAN != 0
143   if (WITH_XOR_ENDIAN)
144     addr = xaddr ^ cpu_core->xor[(N - 1) % WITH_XOR_ENDIAN];
145   else
146 #endif
147     addr = xaddr;
148   mapping = sim_core_find_mapping (core, map, addr, N, read_transfer, 1 /*abort*/, cpu, cia);
149 #if (WITH_DEVICES)
150   if (WITH_CALLBACK_MEMORY && mapping->device != NULL) {
151     unsigned_M data;
152     if (device_io_read_buffer (mapping->device, &data, mapping->space, addr, N) != N)
153       device_error (mapping->device, "internal error - %s - io_read_buffer should not fail",
154                     XSTRING (sim_core_read_aligned_N));
155     val = T2H_M (data);
156   }
157   else
158 #endif
159     val = T2H_M (*(unsigned_M*) sim_core_translate (mapping, addr));
160   PROFILE_COUNT_CORE (cpu, addr, N, map);
161   if (TRACE_P (cpu, TRACE_CORE_IDX))
162     sim_core_trace_M (cpu, cia, __LINE__, read_transfer, map, addr, val, N);
163   return val;
164 }
165 #endif
166
167 /* TAGS: sim_core_read_unaligned_1 sim_core_read_unaligned_2 */
168 /* TAGS: sim_core_read_unaligned_4 sim_core_read_unaligned_8 */
169 /* TAGS: sim_core_read_unaligned_16 */
170
171 #if (M == N && N > 1)
172 INLINE_SIM_CORE(unsigned_M)
173 sim_core_read_unaligned_N(sim_cpu *cpu,
174                           sim_cia cia,
175                           sim_core_maps map,
176                           address_word addr)
177 {
178   int alignment = N - 1;
179   /* if hardwired to forced alignment just do it */
180   if (WITH_ALIGNMENT == FORCED_ALIGNMENT)
181     return sim_core_read_aligned_N (cpu, cia, map, addr & ~alignment);
182   else if ((addr & alignment) == 0)
183     return sim_core_read_aligned_N (cpu, cia, map, addr);
184   else
185     switch (CURRENT_ALIGNMENT)
186       {
187       case STRICT_ALIGNMENT:
188         SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
189                          read_transfer, sim_core_unaligned_signal);
190       case NONSTRICT_ALIGNMENT:
191         {
192           unsigned_M val;
193           if (sim_core_xor_read_buffer (CPU_STATE (cpu), cpu, map, &val, addr, N) != N)
194             SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
195                              read_transfer, sim_core_unaligned_signal);
196           val = T2H_M(val);
197           PROFILE_COUNT_CORE (cpu, addr, N, map);
198           if (TRACE_P (cpu, TRACE_CORE_IDX))
199             sim_core_trace_M (cpu, cia, __LINE__, read_transfer, map, addr, val, N);
200           return val;
201         }
202       case FORCED_ALIGNMENT:
203         return sim_core_read_aligned_N (cpu, cia, map, addr & ~alignment);
204       case MIXED_ALIGNMENT:
205         sim_engine_abort (CPU_STATE (cpu), cpu, cia,
206                           "internal error - %s - mixed alignment",
207                           XSTRING (sim_core_read_unaligned_N));
208       default:
209         sim_engine_abort (CPU_STATE (cpu), cpu, cia,
210                           "internal error - %s - bad switch",
211                           XSTRING (sim_core_read_unaligned_N));
212         /* to keep some compilers happy, we return a dummy */
213         {
214           unsigned_M val[1] = { };
215           return val[0];
216         }
217       }
218 }
219 #endif
220
221 /* TAGS: sim_core_read_misaligned_3 sim_core_read_misaligned_5 */
222 /* TAGS: sim_core_read_misaligned_6 sim_core_read_misaligned_7 */
223
224 #if (M != N)
225 INLINE_SIM_CORE(unsigned_M)
226 sim_core_read_misaligned_N(sim_cpu *cpu,
227                           sim_cia cia,
228                           sim_core_maps map,
229                           address_word addr)
230 {
231   unsigned_M val = 0;
232   if (sim_core_xor_read_buffer (CPU_STATE (cpu), cpu, map, &val, addr, N) != N)
233     SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
234                      read_transfer, sim_core_unaligned_signal);
235   if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
236     val = SWAP_M (val);
237   if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
238     val >>= (M - N) * 8;
239   PROFILE_COUNT_CORE (cpu, addr, N, map);
240   if (TRACE_P (cpu, TRACE_CORE_IDX))
241     sim_core_trace_M (cpu, cia, __LINE__, read_transfer, map, addr, val, N);
242   return val;
243 }
244 #endif
245
246 /* TAGS: sim_core_write_aligned_1 sim_core_write_aligned_2 */
247 /* TAGS: sim_core_write_aligned_4 sim_core_write_aligned_8 */
248 /* TAGS: sim_core_write_aligned_16 */
249
250 #if (M == N)
251 INLINE_SIM_CORE(void)
252 sim_core_write_aligned_N(sim_cpu *cpu,
253                          sim_cia cia,
254                          sim_core_maps map,
255                          address_word xaddr,
256                          unsigned_M val)
257 {
258   sim_cpu_core *cpu_core = CPU_CORE (cpu);
259   sim_core_common *core = &cpu_core->common;
260   sim_core_mapping *mapping;
261   address_word addr;
262 #if WITH_XOR_ENDIAN != 0
263   if (WITH_XOR_ENDIAN)
264     addr = xaddr ^ cpu_core->xor[(N - 1) % WITH_XOR_ENDIAN];
265   else
266 #endif
267     addr = xaddr;
268   mapping = sim_core_find_mapping (core, map, addr, N, write_transfer, 1 /*abort*/, cpu, cia);
269 #if (WITH_DEVICES)
270   if (WITH_CALLBACK_MEMORY && mapping->device != NULL) {
271     unsigned_M data = H2T_M (val);
272     if (device_io_write_buffer (mapping->device, &data, mapping->space, addr, N, cpu, cia) != N)
273       device_error (mapping->device, "internal error - %s - io_write_buffer should not fail",
274                     XSTRING (sim_core_write_aligned_N));
275   }
276   else
277 #endif
278     *(unsigned_M*) sim_core_translate (mapping, addr) = H2T_M (val);
279   PROFILE_COUNT_CORE (cpu, addr, N, map);
280   if (TRACE_P (cpu, TRACE_CORE_IDX))
281     sim_core_trace_M (cpu, cia, __LINE__, write_transfer, map, addr, val, N);
282 }
283 #endif
284
285 /* TAGS: sim_core_write_unaligned_1 sim_core_write_unaligned_2 */
286 /* TAGS: sim_core_write_unaligned_4 sim_core_write_unaligned_8 */
287 /* TAGS: sim_core_write_unaligned_16 */
288
289 #if (M == N && N > 1)
290 INLINE_SIM_CORE(void)
291 sim_core_write_unaligned_N(sim_cpu *cpu,
292                            sim_cia cia,
293                            sim_core_maps map,
294                            address_word addr,
295                            unsigned_M val)
296 {
297   int alignment = N - 1;
298   /* if hardwired to forced alignment just do it */
299   if (WITH_ALIGNMENT == FORCED_ALIGNMENT)
300     sim_core_write_aligned_N (cpu, cia, map, addr & ~alignment, val);
301   else if ((addr & alignment) == 0)
302     sim_core_write_aligned_N (cpu, cia, map, addr, val);
303   else
304     switch (CURRENT_ALIGNMENT)
305       {
306       case STRICT_ALIGNMENT:
307         SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
308                          write_transfer, sim_core_unaligned_signal);
309         break;
310       case NONSTRICT_ALIGNMENT:
311         {
312           unsigned_M data = H2T_M (val);
313           if (sim_core_xor_write_buffer (CPU_STATE (cpu), cpu, map, &data, addr, N) != N)
314             SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
315                              write_transfer, sim_core_unaligned_signal);
316           PROFILE_COUNT_CORE (cpu, addr, N, map);
317           if (TRACE_P (cpu, TRACE_CORE_IDX))
318             sim_core_trace_M (cpu, cia, __LINE__, write_transfer, map, addr, val, N);
319           break;
320         }
321       case FORCED_ALIGNMENT:
322         sim_core_write_aligned_N (cpu, cia, map, addr & ~alignment, val);
323         break;
324       case MIXED_ALIGNMENT:
325         sim_engine_abort (CPU_STATE (cpu), cpu, cia,
326                           "internal error - %s - mixed alignment",
327                           XSTRING (sim_core_write_unaligned_N));
328         break;
329       default:
330         sim_engine_abort (CPU_STATE (cpu), cpu, cia,
331                           "internal error - %s - bad switch",
332                           XSTRING (sim_core_write_unaligned_N));
333         break;
334       }
335 }
336 #endif
337
338 /* TAGS: sim_core_write_misaligned_3 sim_core_write_misaligned_5 */
339 /* TAGS: sim_core_write_misaligned_6 sim_core_write_misaligned_7 */
340
341 #if (M != N)
342 INLINE_SIM_CORE(void)
343 sim_core_write_misaligned_N(sim_cpu *cpu,
344                            sim_cia cia,
345                            sim_core_maps map,
346                            address_word addr,
347                            unsigned_M val)
348 {
349   unsigned_M data = val;
350   if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN)
351     data <<= (M - N) * 8;
352   if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
353     data = SWAP_M (data);
354   if (sim_core_xor_write_buffer (CPU_STATE (cpu), cpu, map, &data, addr, N) != N)
355     SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr,
356                      write_transfer, sim_core_unaligned_signal);
357   PROFILE_COUNT_CORE (cpu, addr, N, map);
358   if (TRACE_P (cpu, TRACE_CORE_IDX))
359     sim_core_trace_M (cpu, cia, __LINE__, write_transfer, map, addr, val, N);
360 }
361 #endif
362
363
364 /* NOTE: see start of file for #define of these macros */
365 #undef unsigned_M
366 #undef T2H_M
367 #undef H2T_M
368 #undef SWAP_M
369 #undef sim_core_read_aligned_N
370 #undef sim_core_read_unaligned_N
371 #undef sim_core_read_misaligned_N
372 #undef sim_core_write_aligned_N
373 #undef sim_core_write_unaligned_N
374 #undef sim_core_write_misaligned_N
375 #undef sim_core_trace_M
376 #undef M
377 #undef N