1 /* The common simulator framework for GDB, the GNU Debugger. 2 3 Copyright 2002-2024 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 */ 61 static 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) 70 STATIC_SIM_CORE(void) 71 sim_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) 147 INLINE_SIM_CORE(unsigned_M) 148 sim_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_HW) 168 if (mapping->device != NULL) 169 { 170 unsigned_M data; 171 sim_cpu_hw_io_read_buffer (cpu, cia, mapping->device, &data, mapping->space, addr, N); 172 val = T2H_M (data); 173 break; 174 } 175 #endif 176 val = T2H_M (*(unsigned_M*) sim_core_translate (mapping, addr)); 177 } 178 while (0); 179 PROFILE_COUNT_CORE (cpu, addr, N, map); 180 if (TRACE_P (cpu, TRACE_CORE_IDX)) 181 sim_core_trace_M (cpu, cia, __LINE__, read_transfer, map, addr, val, N); 182 return val; 183 } 184 #endif 185 186 /* TAGS: sim_core_read_unaligned_1 sim_core_read_unaligned_2 */ 187 /* TAGS: sim_core_read_unaligned_4 sim_core_read_unaligned_8 */ 188 /* TAGS: sim_core_read_unaligned_16 */ 189 190 #if (M == N && N > 1) 191 INLINE_SIM_CORE(unsigned_M) 192 sim_core_read_unaligned_N(sim_cpu *cpu, 193 sim_cia cia, 194 unsigned map, 195 address_word addr) 196 { 197 int alignment = N - 1; 198 /* if hardwired to forced alignment just do it */ 199 if (WITH_ALIGNMENT == FORCED_ALIGNMENT) 200 return sim_core_read_aligned_N (cpu, cia, map, addr & ~alignment); 201 else if ((addr & alignment) == 0) 202 return sim_core_read_aligned_N (cpu, cia, map, addr); 203 else 204 switch (CURRENT_ALIGNMENT) 205 { 206 case STRICT_ALIGNMENT: 207 SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr, 208 read_transfer, sim_core_unaligned_signal); 209 case NONSTRICT_ALIGNMENT: 210 { 211 unsigned_M val; 212 if (sim_core_xor_read_buffer (CPU_STATE (cpu), cpu, map, &val, addr, N) != N) 213 SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr, 214 read_transfer, sim_core_unaligned_signal); 215 val = T2H_M(val); 216 PROFILE_COUNT_CORE (cpu, addr, N, map); 217 if (TRACE_P (cpu, TRACE_CORE_IDX)) 218 sim_core_trace_M (cpu, cia, __LINE__, read_transfer, map, addr, val, N); 219 return val; 220 } 221 case FORCED_ALIGNMENT: 222 return sim_core_read_aligned_N (cpu, cia, map, addr & ~alignment); 223 case MIXED_ALIGNMENT: 224 sim_engine_abort (CPU_STATE (cpu), cpu, cia, 225 "internal error - %s - mixed alignment", 226 XSTRING (sim_core_read_unaligned_N)); 227 default: 228 sim_engine_abort (CPU_STATE (cpu), cpu, cia, 229 "internal error - %s - bad switch", 230 XSTRING (sim_core_read_unaligned_N)); 231 /* to keep some compilers happy, we return a dummy */ 232 return sim_core_dummy_M; 233 } 234 } 235 #endif 236 237 /* TAGS: sim_core_read_misaligned_3 sim_core_read_misaligned_5 */ 238 /* TAGS: sim_core_read_misaligned_6 sim_core_read_misaligned_7 */ 239 240 #if (M != N) 241 INLINE_SIM_CORE(unsigned_M) 242 sim_core_read_misaligned_N(sim_cpu *cpu, 243 sim_cia cia, 244 unsigned map, 245 address_word addr) 246 { 247 unsigned_M val = 0; 248 if (sim_core_xor_read_buffer (CPU_STATE (cpu), cpu, map, &val, addr, N) != N) 249 SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr, 250 read_transfer, sim_core_unaligned_signal); 251 if (HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER) 252 val = SWAP_M (val); 253 if (CURRENT_TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) 254 val >>= (M - N) * 8; 255 PROFILE_COUNT_CORE (cpu, addr, N, map); 256 if (TRACE_P (cpu, TRACE_CORE_IDX)) 257 sim_core_trace_M (cpu, cia, __LINE__, read_transfer, map, addr, val, N); 258 return val; 259 } 260 #endif 261 262 /* TAGS: sim_core_write_aligned_1 sim_core_write_aligned_2 */ 263 /* TAGS: sim_core_write_aligned_4 sim_core_write_aligned_8 */ 264 /* TAGS: sim_core_write_aligned_16 */ 265 266 #if (M == N) 267 INLINE_SIM_CORE(void) 268 sim_core_write_aligned_N(sim_cpu *cpu, 269 sim_cia cia, 270 unsigned map, 271 address_word xaddr, 272 unsigned_M val) 273 { 274 sim_cpu_core *cpu_core = CPU_CORE (cpu); 275 sim_core_common *core = &cpu_core->common; 276 sim_core_mapping *mapping; 277 address_word addr; 278 #if WITH_XOR_ENDIAN != 0 279 if (WITH_XOR_ENDIAN) 280 addr = xaddr ^ cpu_core->xor[(N - 1) % WITH_XOR_ENDIAN]; 281 else 282 #endif 283 addr = xaddr; 284 mapping = sim_core_find_mapping (core, map, addr, N, write_transfer, 1 /*abort*/, cpu, cia); 285 do 286 { 287 #if (WITH_HW) 288 if (mapping->device != NULL) 289 { 290 unsigned_M data = H2T_M (val); 291 sim_cpu_hw_io_write_buffer (cpu, cia, mapping->device, &data, mapping->space, addr, N); 292 break; 293 } 294 #endif 295 *(unsigned_M*) sim_core_translate (mapping, addr) = H2T_M (val); 296 } 297 while (0); 298 PROFILE_COUNT_CORE (cpu, addr, N, map); 299 if (TRACE_P (cpu, TRACE_CORE_IDX)) 300 sim_core_trace_M (cpu, cia, __LINE__, write_transfer, map, addr, val, N); 301 } 302 #endif 303 304 /* TAGS: sim_core_write_unaligned_1 sim_core_write_unaligned_2 */ 305 /* TAGS: sim_core_write_unaligned_4 sim_core_write_unaligned_8 */ 306 /* TAGS: sim_core_write_unaligned_16 */ 307 308 #if (M == N && N > 1) 309 INLINE_SIM_CORE(void) 310 sim_core_write_unaligned_N(sim_cpu *cpu, 311 sim_cia cia, 312 unsigned map, 313 address_word addr, 314 unsigned_M val) 315 { 316 int alignment = N - 1; 317 /* if hardwired to forced alignment just do it */ 318 if (WITH_ALIGNMENT == FORCED_ALIGNMENT) 319 sim_core_write_aligned_N (cpu, cia, map, addr & ~alignment, val); 320 else if ((addr & alignment) == 0) 321 sim_core_write_aligned_N (cpu, cia, map, addr, val); 322 else 323 switch (CURRENT_ALIGNMENT) 324 { 325 case STRICT_ALIGNMENT: 326 SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr, 327 write_transfer, sim_core_unaligned_signal); 328 break; 329 case NONSTRICT_ALIGNMENT: 330 { 331 unsigned_M data = H2T_M (val); 332 if (sim_core_xor_write_buffer (CPU_STATE (cpu), cpu, map, &data, addr, N) != N) 333 SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr, 334 write_transfer, sim_core_unaligned_signal); 335 PROFILE_COUNT_CORE (cpu, addr, N, map); 336 if (TRACE_P (cpu, TRACE_CORE_IDX)) 337 sim_core_trace_M (cpu, cia, __LINE__, write_transfer, map, addr, val, N); 338 break; 339 } 340 case FORCED_ALIGNMENT: 341 sim_core_write_aligned_N (cpu, cia, map, addr & ~alignment, val); 342 break; 343 case MIXED_ALIGNMENT: 344 sim_engine_abort (CPU_STATE (cpu), cpu, cia, 345 "internal error - %s - mixed alignment", 346 XSTRING (sim_core_write_unaligned_N)); 347 break; 348 default: 349 sim_engine_abort (CPU_STATE (cpu), cpu, cia, 350 "internal error - %s - bad switch", 351 XSTRING (sim_core_write_unaligned_N)); 352 break; 353 } 354 } 355 #endif 356 357 /* TAGS: sim_core_write_misaligned_3 sim_core_write_misaligned_5 */ 358 /* TAGS: sim_core_write_misaligned_6 sim_core_write_misaligned_7 */ 359 360 #if (M != N) 361 INLINE_SIM_CORE(void) 362 sim_core_write_misaligned_N(sim_cpu *cpu, 363 sim_cia cia, 364 unsigned map, 365 address_word addr, 366 unsigned_M val) 367 { 368 unsigned_M data = val; 369 if (CURRENT_TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) 370 data <<= (M - N) * 8; 371 if (HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER) 372 data = SWAP_M (data); 373 if (sim_core_xor_write_buffer (CPU_STATE (cpu), cpu, map, &data, addr, N) != N) 374 SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr, 375 write_transfer, sim_core_unaligned_signal); 376 PROFILE_COUNT_CORE (cpu, addr, N, map); 377 if (TRACE_P (cpu, TRACE_CORE_IDX)) 378 sim_core_trace_M (cpu, cia, __LINE__, write_transfer, map, addr, val, N); 379 } 380 #endif 381 382 383 /* NOTE: see start of file for #define of these macros */ 384 #undef unsigned_M 385 #undef T2H_M 386 #undef H2T_M 387 #undef SWAP_M 388 #undef sim_core_read_aligned_N 389 #undef sim_core_read_unaligned_N 390 #undef sim_core_read_misaligned_N 391 #undef sim_core_write_aligned_N 392 #undef sim_core_write_unaligned_N 393 #undef sim_core_write_misaligned_N 394 #undef sim_core_trace_M 395 #undef sim_core_dummy_M 396 #undef M 397 #undef N 398