1 /* mem.c --- memory for RX simulator. 2 3 Copyright (C) 2005-2023 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 } 328 #endif 329 330 case 0x00088263: /* SCI4.TDR */ 331 { 332 static int pending_exit = 0; 333 if (pending_exit == 2) 334 { 335 step_result = RX_MAKE_EXITED(value); 336 longjmp (decode_jmp_buf, 1); 337 } 338 else if (value == 3) 339 pending_exit ++; 340 else 341 pending_exit = 0; 342 343 putchar(value); 344 } 345 break; 346 347 default: 348 if (is_reserved_address (address)) 349 generate_access_exception (); 350 } 351 } 352 353 void 354 mem_put_qi (int address, unsigned char value) 355 { 356 S ("<="); 357 mem_put_byte (address, value & 0xff); 358 E (); 359 COUNT (1, 1); 360 } 361 362 #ifdef CYCLE_ACCURATE 363 static int tpu_base; 364 #endif 365 366 void 367 mem_put_hi (int address, unsigned short value) 368 { 369 S ("<="); 370 switch (address) 371 { 372 #ifdef CYCLE_ACCURATE 373 case 0x00088126: /* TPU1.TCNT */ 374 tpu_base = regs.cycle_count; 375 break; 376 case 0x00088136: /* TPU2.TCNT */ 377 tpu_base = regs.cycle_count; 378 break; 379 #endif 380 default: 381 if (rx_big_endian) 382 { 383 mem_put_byte (address, value >> 8); 384 mem_put_byte (address + 1, value & 0xff); 385 } 386 else 387 { 388 mem_put_byte (address, value & 0xff); 389 mem_put_byte (address + 1, value >> 8); 390 } 391 } 392 E (); 393 COUNT (1, 2); 394 } 395 396 void 397 mem_put_psi (int address, unsigned long value) 398 { 399 S ("<="); 400 if (rx_big_endian) 401 { 402 mem_put_byte (address, value >> 16); 403 mem_put_byte (address + 1, (value >> 8) & 0xff); 404 mem_put_byte (address + 2, value & 0xff); 405 } 406 else 407 { 408 mem_put_byte (address, value & 0xff); 409 mem_put_byte (address + 1, (value >> 8) & 0xff); 410 mem_put_byte (address + 2, value >> 16); 411 } 412 E (); 413 COUNT (1, 3); 414 } 415 416 void 417 mem_put_si (int address, unsigned long value) 418 { 419 S ("<="); 420 if (rx_big_endian) 421 { 422 mem_put_byte (address + 0, (value >> 24) & 0xff); 423 mem_put_byte (address + 1, (value >> 16) & 0xff); 424 mem_put_byte (address + 2, (value >> 8) & 0xff); 425 mem_put_byte (address + 3, value & 0xff); 426 } 427 else 428 { 429 mem_put_byte (address + 0, value & 0xff); 430 mem_put_byte (address + 1, (value >> 8) & 0xff); 431 mem_put_byte (address + 2, (value >> 16) & 0xff); 432 mem_put_byte (address + 3, (value >> 24) & 0xff); 433 } 434 E (); 435 COUNT (1, 4); 436 } 437 438 void 439 mem_put_blk (int address, void *bufptr_void, int nbytes) 440 { 441 unsigned char *bufptr = (unsigned char *) bufptr_void; 442 443 S ("<="); 444 if (enable_counting) 445 mem_counters[1][1] += nbytes; 446 while (nbytes--) 447 mem_put_byte (address++, *bufptr++); 448 E (); 449 } 450 451 unsigned char 452 mem_get_pc (int address) 453 { 454 unsigned char *m = rx_mem_ptr (address, MPA_READING); 455 COUNT (0, 0); 456 return *m; 457 } 458 459 static unsigned char 460 mem_get_byte (unsigned int address) 461 { 462 unsigned char *m; 463 464 S ("=>"); 465 m = rx_mem_ptr (address, MPA_READING); 466 switch (address) 467 { 468 case 0x00088264: /* SCI4.SSR */ 469 E(); 470 return 0x04; /* transmitter empty */ 471 break; 472 default: 473 if (trace) 474 printf (" %02x%c", *m, mtypec (address)); 475 if (is_reserved_address (address)) 476 generate_access_exception (); 477 break; 478 } 479 E (); 480 return *m; 481 } 482 483 unsigned char 484 mem_get_qi (int address) 485 { 486 unsigned char rv; 487 S ("=>"); 488 rv = mem_get_byte (address); 489 COUNT (0, 1); 490 E (); 491 return rv; 492 } 493 494 unsigned short 495 mem_get_hi (int address) 496 { 497 unsigned short rv; 498 S ("=>"); 499 switch (address) 500 { 501 #ifdef CYCLE_ACCURATE 502 case 0x00088126: /* TPU1.TCNT */ 503 rv = (regs.cycle_count - tpu_base) >> 16; 504 break; 505 case 0x00088136: /* TPU2.TCNT */ 506 rv = (regs.cycle_count - tpu_base) >> 0; 507 break; 508 #endif 509 510 default: 511 if (rx_big_endian) 512 { 513 rv = mem_get_byte (address) << 8; 514 rv |= mem_get_byte (address + 1); 515 } 516 else 517 { 518 rv = mem_get_byte (address); 519 rv |= mem_get_byte (address + 1) << 8; 520 } 521 } 522 COUNT (0, 2); 523 E (); 524 return rv; 525 } 526 527 unsigned long 528 mem_get_psi (int address) 529 { 530 unsigned long rv; 531 S ("=>"); 532 if (rx_big_endian) 533 { 534 rv = mem_get_byte (address + 2); 535 rv |= mem_get_byte (address + 1) << 8; 536 rv |= mem_get_byte (address) << 16; 537 } 538 else 539 { 540 rv = mem_get_byte (address); 541 rv |= mem_get_byte (address + 1) << 8; 542 rv |= mem_get_byte (address + 2) << 16; 543 } 544 COUNT (0, 3); 545 E (); 546 return rv; 547 } 548 549 unsigned long 550 mem_get_si (int address) 551 { 552 unsigned long rv; 553 S ("=>"); 554 if (rx_big_endian) 555 { 556 rv = mem_get_byte (address + 3); 557 rv |= mem_get_byte (address + 2) << 8; 558 rv |= mem_get_byte (address + 1) << 16; 559 rv |= mem_get_byte (address) << 24; 560 } 561 else 562 { 563 rv = mem_get_byte (address); 564 rv |= mem_get_byte (address + 1) << 8; 565 rv |= mem_get_byte (address + 2) << 16; 566 rv |= mem_get_byte (address + 3) << 24; 567 } 568 COUNT (0, 4); 569 E (); 570 return rv; 571 } 572 573 void 574 mem_get_blk (int address, void *bufptr_void, int nbytes) 575 { 576 char *bufptr = (char *) bufptr_void; 577 578 S ("=>"); 579 if (enable_counting) 580 mem_counters[0][1] += nbytes; 581 while (nbytes--) 582 *bufptr++ = mem_get_byte (address++); 583 E (); 584 } 585 586 int 587 sign_ext (int v, int bits) 588 { 589 if (bits < 32) 590 { 591 v &= (1 << bits) - 1; 592 if (v & (1 << (bits - 1))) 593 v -= (1 << bits); 594 } 595 return v; 596 } 597 598 void 599 mem_set_content_type (int address, enum mem_content_type type) 600 { 601 unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE); 602 *mt = type; 603 } 604 605 void 606 mem_set_content_range (int start_address, int end_address, enum mem_content_type type) 607 { 608 while (start_address < end_address) 609 { 610 int sz, ofs; 611 unsigned char *mt; 612 613 sz = end_address - start_address; 614 ofs = start_address % L1_LEN; 615 if (sz + ofs > L1_LEN) 616 sz = L1_LEN - ofs; 617 618 mt = rx_mem_ptr (start_address, MPA_CONTENT_TYPE); 619 memset (mt, type, sz); 620 621 start_address += sz; 622 } 623 } 624 625 enum mem_content_type 626 mem_get_content_type (int address) 627 { 628 unsigned char *mt = rx_mem_ptr (address, MPA_CONTENT_TYPE); 629 return *mt; 630 } 631