1 /* mem.c --- memory for RX simulator. 2 3 Copyright (C) 2005-2024 Free Software Foundation, Inc. 4 Contributed by Red Hat, Inc. 5 6 This file is part of the GNU simulators. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21 /* This must come before any other includes. */ 22 #include "defs.h" 23 24 /* This slows down the simulator and we get some false negatives from 25 gcc, like when it uses a long-sized hole to hold a byte-sized 26 variable, knowing that it doesn't care about the other bits. But, 27 if you need to track down a read-from-unitialized bug, set this to 28 1. */ 29 #define RDCHECK 0 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 35 #include "opcode/rx.h" 36 #include "mem.h" 37 #include "cpu.h" 38 #include "syscalls.h" 39 #include "misc.h" 40 #include "err.h" 41 42 #define L1_BITS (10) 43 #define L2_BITS (10) 44 #define OFF_BITS PAGE_BITS 45 46 #define L1_LEN (1 << L1_BITS) 47 #define L2_LEN (1 << L2_BITS) 48 #define OFF_LEN (1 << OFF_BITS) 49 50 static unsigned char **pt[L1_LEN]; 51 static unsigned char **ptr[L1_LEN]; 52 static RX_Opcode_Decoded ***ptdc[L1_LEN]; 53 54 /* [ get=0/put=1 ][ byte size ] */ 55 static unsigned int mem_counters[2][5]; 56 57 #define COUNT(isput,bytes) \ 58 if (verbose && enable_counting) mem_counters[isput][bytes]++ 59 60 void 61 init_mem (void) 62 { 63 int i, j; 64 65 for (i = 0; i < L1_LEN; i++) 66 if (pt[i]) 67 { 68 for (j = 0; j < L2_LEN; j++) 69 if (pt[i][j]) 70 free (pt[i][j]); 71 free (pt[i]); 72 } 73 memset (pt, 0, sizeof (pt)); 74 memset (ptr, 0, sizeof (ptr)); 75 memset (mem_counters, 0, sizeof (mem_counters)); 76 } 77 78 unsigned char * 79 rx_mem_ptr (unsigned long address, enum mem_ptr_action action) 80 { 81 int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1); 82 int pt2 = (address >> OFF_BITS) & ((1 << L2_BITS) - 1); 83 int pto = address & ((1 << OFF_BITS) - 1); 84 85 if (address == 0) 86 execution_error (SIM_ERR_NULL_POINTER_DEREFERENCE, 0); 87 88 if (pt[pt1] == 0) 89 { 90 pt[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **)); 91 ptr[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **)); 92 ptdc[pt1] = (RX_Opcode_Decoded ***) calloc (L2_LEN, sizeof (RX_Opcode_Decoded ***)); 93 } 94 if (pt[pt1][pt2] == 0) 95 { 96 if (action == MPA_READING) 97 execution_error (SIM_ERR_READ_UNWRITTEN_PAGES, address); 98 99 pt[pt1][pt2] = (unsigned char *) calloc (OFF_LEN, 1); 100 ptr[pt1][pt2] = (unsigned char *) calloc (OFF_LEN, 1); 101 ptdc[pt1][pt2] = (RX_Opcode_Decoded **) calloc (OFF_LEN, sizeof(RX_Opcode_Decoded *)); 102 } 103 else if (action == MPA_READING 104 && ptr[pt1][pt2][pto] == MC_UNINIT) 105 execution_error (SIM_ERR_READ_UNWRITTEN_BYTES, address); 106 107 if (action == MPA_WRITING) 108 { 109 int pto_dc; 110 if (ptr[pt1][pt2][pto] == MC_PUSHED_PC) 111 execution_error (SIM_ERR_CORRUPT_STACK, address); 112 ptr[pt1][pt2][pto] = MC_DATA; 113 114 /* The instruction decoder doesn't store it's decoded instructions 115 at word swapped addresses. Therefore, when clearing the decode 116 cache, we have to account for that here. */ 117 pto_dc = pto ^ (rx_big_endian ? 3 : 0); 118 if (ptdc[pt1][pt2][pto_dc]) 119 { 120 free (ptdc[pt1][pt2][pto_dc]); 121 ptdc[pt1][pt2][pto_dc] = NULL; 122 } 123 } 124 125 if (action == MPA_CONTENT_TYPE) 126 return (unsigned char *) (ptr[pt1][pt2] + pto); 127 128 if (action == MPA_DECODE_CACHE) 129 return (unsigned char *) (ptdc[pt1][pt2] + pto); 130 131 return pt[pt1][pt2] + pto; 132 } 133 134 RX_Opcode_Decoded ** 135 rx_mem_decode_cache (unsigned long address) 136 { 137 return (RX_Opcode_Decoded **) rx_mem_ptr (address, MPA_DECODE_CACHE); 138 } 139 140 static inline int 141 is_reserved_address (unsigned int address) 142 { 143 return (address >= 0x00020000 && address < 0x00080000) 144 || (address >= 0x00100000 && address < 0x01000000) 145 || (address >= 0x08000000 && address < 0xff000000); 146 } 147 148 static void 149 used (int rstart, int i, int j) 150 { 151 int rend = i << (L2_BITS + OFF_BITS); 152 rend += j << OFF_BITS; 153 if (rstart == 0xe0000 && rend == 0xe1000) 154 return; 155 printf ("mem: %08x - %08x (%dk bytes)\n", rstart, rend - 1, 156 (rend - rstart) / 1024); 157 } 158 159 static char * 160 mcs (int isput, int bytes) 161 { 162 return comma (mem_counters[isput][bytes]); 163 } 164 165 void 166 mem_usage_stats (void) 167 { 168 int i, j; 169 int rstart = 0; 170 int pending = 0; 171 172 for (i = 0; i < L1_LEN; i++) 173 if (pt[i]) 174 { 175 for (j = 0; j < L2_LEN; j++) 176 if (pt[i][j]) 177 { 178 if (!pending) 179 { 180 pending = 1; 181 rstart = (i << (L2_BITS + OFF_BITS)) + (j << OFF_BITS); 182 } 183 } 184 else if (pending) 185 { 186 pending = 0; 187 used (rstart, i, j); 188 } 189 } 190 else 191 { 192 if (pending) 193 { 194 pending = 0; 195 used (rstart, i, 0); 196 } 197 } 198 /* mem foo: 123456789012 123456789012 123456789012 123456789012 199 123456789012 */ 200 printf (" byte short 3byte long" 201 " opcode\n"); 202 if (verbose > 1) 203 { 204 /* Only use comma separated numbers when being very verbose. 205 Comma separated numbers are hard to parse in awk scripts. */ 206 printf ("mem get: %12s %12s %12s %12s %12s\n", mcs (0, 1), mcs (0, 2), 207 mcs (0, 3), mcs (0, 4), mcs (0, 0)); 208 printf ("mem put: %12s %12s %12s %12s\n", mcs (1, 1), mcs (1, 2), 209 mcs (1, 3), mcs (1, 4)); 210 } 211 else 212 { 213 printf ("mem get: %12u %12u %12u %12u %12u\n", 214 mem_counters[0][1], mem_counters[0][2], 215 mem_counters[0][3], mem_counters[0][4], 216 mem_counters[0][0]); 217 printf ("mem put: %12u %12u %12u %12u\n", 218 mem_counters [1][1], mem_counters [1][2], 219 mem_counters [1][3], mem_counters [1][4]); 220 } 221 } 222 223 unsigned long 224 mem_usage_cycles (void) 225 { 226 unsigned long rv = mem_counters[0][0]; 227 rv += mem_counters[0][1] * 1; 228 rv += mem_counters[0][2] * 2; 229 rv += mem_counters[0][3] * 3; 230 rv += mem_counters[0][4] * 4; 231 rv += mem_counters[1][1] * 1; 232 rv += mem_counters[1][2] * 2; 233 rv += mem_counters[1][3] * 3; 234 rv += mem_counters[1][4] * 4; 235 return rv; 236 } 237 238 static int tpr = 0; 239 static void 240 s (int address, char *dir) 241 { 242 if (tpr == 0) 243 printf ("MEM[%08x] %s", address, dir); 244 tpr++; 245 } 246 247 #define S(d) if (trace) s(address, d) 248 static void 249 e (void) 250 { 251 if (!trace) 252 return; 253 tpr--; 254 if (tpr == 0) 255 printf ("\n"); 256 } 257 258 static char 259 mtypec (int address) 260 { 261 unsigned char *cp = rx_mem_ptr (address, MPA_CONTENT_TYPE); 262 return "udp"[*cp]; 263 } 264 265 #define E() if (trace) e() 266 267 static void 268 mem_put_byte (unsigned int address, unsigned char value) 269 { 270 unsigned char *m; 271 char tc = ' '; 272 273 if (trace) 274 tc = mtypec (address); 275 m = rx_mem_ptr (address, MPA_WRITING); 276 if (trace) 277 printf (" %02x%c", value, tc); 278 *m = value; 279 switch (address) 280 { 281 case 0x0008c02a: /* PA.DR */ 282 { 283 static int old_led = -1; 284 int red_on = 0; 285 int i; 286 287 if (old_led != value) 288 { 289 fputs (" ", stdout); 290 for (i = 0; i < 8; i++) 291 if (value & (1 << i)) 292 { 293 if (! red_on) 294 { 295 fputs ("\033[31m", stdout); 296 red_on = 1; 297 } 298 fputs (" @", stdout); 299 } 300 else 301 { 302 if (red_on) 303 { 304 fputs ("\033[0m", stdout); 305 red_on = 0; 306 } 307 fputs (" *", stdout); 308 } 309 310 if (red_on) 311 fputs ("\033[0m", stdout); 312 313 fputs ("\r", stdout); 314 fflush (stdout); 315 old_led = value; 316 } 317 } 318 break; 319 320 #ifdef WITH_PROFILE 321 case 0x0008c02b: /* PB.DR */ 322 { 323 if (value == 0) 324 halt_pipeline_stats (); 325 else 326 reset_pipeline_stats (); 327 break; 328 } 329 #endif 330 331 case 0x00088263: /* SCI4.TDR */ 332 { 333 static int pending_exit = 0; 334 if (pending_exit == 2) 335 { 336 step_result = RX_MAKE_EXITED(value); 337 longjmp (decode_jmp_buf, 1); 338 } 339 else if (value == 3) 340 pending_exit ++; 341 else 342 pending_exit = 0; 343 344 putchar(value); 345 } 346 break; 347 348 default: 349 if (is_reserved_address (address)) 350 generate_access_exception (); 351 } 352 } 353 354 void 355 mem_put_qi (int address, unsigned char value) 356 { 357 S ("<="); 358 mem_put_byte (address, value & 0xff); 359 E (); 360 COUNT (1, 1); 361 } 362 363 #ifdef CYCLE_ACCURATE 364 static int tpu_base; 365 #endif 366 367 void 368 mem_put_hi (int address, unsigned short value) 369 { 370 S ("<="); 371 switch (address) 372 { 373 #ifdef CYCLE_ACCURATE 374 case 0x00088126: /* TPU1.TCNT */ 375 tpu_base = regs.cycle_count; 376 break; 377 case 0x00088136: /* TPU2.TCNT */ 378 tpu_base = regs.cycle_count; 379 break; 380 #endif 381 default: 382 if (rx_big_endian) 383 { 384 mem_put_byte (address, value >> 8); 385 mem_put_byte (address + 1, value & 0xff); 386 } 387 else 388 { 389 mem_put_byte (address, value & 0xff); 390 mem_put_byte (address + 1, value >> 8); 391 } 392 } 393 E (); 394 COUNT (1, 2); 395 } 396 397 void 398 mem_put_psi (int address, unsigned long value) 399 { 400 S ("<="); 401 if (rx_big_endian) 402 { 403 mem_put_byte (address, value >> 16); 404 mem_put_byte (address + 1, (value >> 8) & 0xff); 405 mem_put_byte (address + 2, value & 0xff); 406 } 407 else 408 { 409 mem_put_byte (address, value & 0xff); 410 mem_put_byte (address + 1, (value >> 8) & 0xff); 411 mem_put_byte (address + 2, value >> 16); 412 } 413 E (); 414 COUNT (1, 3); 415 } 416 417 void 418 mem_put_si (int address, unsigned long value) 419 { 420 S ("<="); 421 if (rx_big_endian) 422 { 423 mem_put_byte (address + 0, (value >> 24) & 0xff); 424 mem_put_byte (address + 1, (value >> 16) & 0xff); 425 mem_put_byte (address + 2, (value >> 8) & 0xff); 426 mem_put_byte (address + 3, value & 0xff); 427 } 428 else 429 { 430 mem_put_byte (address + 0, value & 0xff); 431 mem_put_byte (address + 1, (value >> 8) & 0xff); 432 mem_put_byte (address + 2, (value >> 16) & 0xff); 433 mem_put_byte (address + 3, (value >> 24) & 0xff); 434 } 435 E (); 436 COUNT (1, 4); 437 } 438 439 void 440 mem_put_blk (int address, void *bufptr_void, int nbytes) 441 { 442 unsigned char *bufptr = (unsigned char *) bufptr_void; 443 444 S ("<="); 445 if (enable_counting) 446 mem_counters[1][1] += nbytes; 447 while (nbytes--) 448 mem_put_byte (address++, *bufptr++); 449 E (); 450 } 451 452 unsigned char 453 mem_get_pc (int address) 454 { 455 unsigned char *m = rx_mem_ptr (address, MPA_READING); 456 COUNT (0, 0); 457 return *m; 458 } 459 460 static unsigned char 461 mem_get_byte (unsigned int address) 462 { 463 unsigned char *m; 464 465 S ("=>"); 466 m = rx_mem_ptr (address, MPA_READING); 467 switch (address) 468 { 469 case 0x00088264: /* SCI4.SSR */ 470 E(); 471 return 0x04; /* transmitter empty */ 472 break; 473 default: 474 if (trace) 475 printf (" %02x%c", *m, mtypec (address)); 476 if (is_reserved_address (address)) 477 generate_access_exception (); 478 break; 479 } 480 E (); 481 return *m; 482 } 483 484 unsigned char 485 mem_get_qi (int address) 486 { 487 unsigned char rv; 488 S ("=>"); 489 rv = mem_get_byte (address); 490 COUNT (0, 1); 491 E (); 492 return rv; 493 } 494 495 unsigned short 496 mem_get_hi (int address) 497 { 498 unsigned short rv; 499 S ("=>"); 500 switch (address) 501 { 502 #ifdef CYCLE_ACCURATE 503 case 0x00088126: /* TPU1.TCNT */ 504 rv = (regs.cycle_count - tpu_base) >> 16; 505 break; 506 case 0x00088136: /* TPU2.TCNT */ 507 rv = (regs.cycle_count - tpu_base) >> 0; 508 break; 509 #endif 510 511 default: 512 if (rx_big_endian) 513 { 514 rv = mem_get_byte (address) << 8; 515 rv |= mem_get_byte (address + 1); 516 } 517 else 518 { 519 rv = mem_get_byte (address); 520 rv |= mem_get_byte (address + 1) << 8; 521 } 522 } 523 COUNT (0, 2); 524 E (); 525 return rv; 526 } 527 528 unsigned long 529 mem_get_psi (int address) 530 { 531 unsigned long rv; 532 S ("=>"); 533 if (rx_big_endian) 534 { 535 rv = mem_get_byte (address + 2); 536 rv |= mem_get_byte (address + 1) << 8; 537 rv |= mem_get_byte (address) << 16; 538 } 539 else 540 { 541 rv = mem_get_byte (address); 542 rv |= mem_get_byte (address + 1) << 8; 543 rv |= mem_get_byte (address + 2) << 16; 544 } 545 COUNT (0, 3); 546 E (); 547 return rv; 548 } 549 550 unsigned long 551 mem_get_si (int address) 552 { 553 unsigned long rv; 554 S ("=>"); 555 if (rx_big_endian) 556 { 557 rv = mem_get_byte (address + 3); 558 rv |= mem_get_byte (address + 2) << 8; 559 rv |= mem_get_byte (address + 1) << 16; 560 rv |= mem_get_byte (address) << 24; 561 } 562 else 563 { 564 rv = mem_get_byte (address); 565 rv |= mem_get_byte (address + 1) << 8; 566 rv |= mem_get_byte (address + 2) << 16; 567 rv |= mem_get_byte (address + 3) << 24; 568 } 569 COUNT (0, 4); 570 E (); 571 return rv; 572 } 573 574 void 575 mem_get_blk (int address, void *bufptr_void, int nbytes) 576 { 577 char *bufptr = (char *) bufptr_void; 578 579 S ("=>"); 580 if (enable_counting) 581 mem_counters[0][1] += nbytes; 582 while (nbytes--) 583 *bufptr++ = mem_get_byte (address++); 584 E (); 585 } 586 587 int 588 sign_ext (int v, int bits) 589 { 590 if (bits < 32) 591 { 592 v &= (1 << bits) - 1; 593 if (v & (1 << (bits - 1))) 594 v -= (1 << bits); 595 } 596 return v; 597 } 598 599 void 600 mem_set_content_type (int address, enum mem_content_type type) 601 { 602 unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE); 603 *mt = type; 604 } 605 606 void 607 mem_set_content_range (int start_address, int end_address, enum mem_content_type type) 608 { 609 while (start_address < end_address) 610 { 611 int sz, ofs; 612 unsigned char *mt; 613 614 sz = end_address - start_address; 615 ofs = start_address % L1_LEN; 616 if (sz + ofs > L1_LEN) 617 sz = L1_LEN - ofs; 618 619 mt = rx_mem_ptr (start_address, MPA_CONTENT_TYPE); 620 memset (mt, type, sz); 621 622 start_address += sz; 623 } 624 } 625 626 enum mem_content_type 627 mem_get_content_type (int address) 628 { 629 unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE); 630 return *mt; 631 } 632