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