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