1 /* mem.c --- memory for M32C 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 #include <errno.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <ctype.h> 29 #include <sys/time.h> 30 #include <sys/types.h> 31 #include <unistd.h> 32 #include <sys/select.h> 33 #ifdef HAVE_TERMIOS_H 34 #include <termios.h> 35 #endif 36 37 #include "mem.h" 38 #include "cpu.h" 39 #include "syscalls.h" 40 #include "misc.h" 41 #ifdef TIMER_A 42 #include "int.h" 43 #include "timer_a.h" 44 #endif 45 46 #define L1_BITS (10) 47 #define L2_BITS (10) 48 #define OFF_BITS (12) 49 50 #define L1_LEN (1 << L1_BITS) 51 #define L2_LEN (1 << L2_BITS) 52 #define OFF_LEN (1 << OFF_BITS) 53 54 static unsigned char **pt[L1_LEN]; 55 56 #ifdef HAVE_TERMIOS_H 57 int m32c_console_ifd = 0; 58 #endif 59 int m32c_console_ofd = 1; 60 #ifdef HAVE_TERMIOS_H 61 int m32c_use_raw_console = 0; 62 #endif 63 64 #ifdef TIMER_A 65 Timer_A timer_a; 66 #endif 67 68 /* [ get=0/put=1 ][ byte size ] */ 69 static unsigned int mem_counters[2][5]; 70 71 #define COUNT(isput,bytes) \ 72 if (verbose && enable_counting) mem_counters[isput][bytes]++ 73 74 void 75 init_mem (void) 76 { 77 int i, j; 78 79 for (i = 0; i < L1_LEN; i++) 80 if (pt[i]) 81 { 82 for (j = 0; j < L2_LEN; j++) 83 if (pt[i][j]) 84 free (pt[i][j]); 85 free (pt[i]); 86 } 87 memset (pt, 0, sizeof (pt)); 88 memset (mem_counters, 0, sizeof (mem_counters)); 89 } 90 91 static unsigned char * 92 mem_ptr (int address) 93 { 94 static int recursing = 0; 95 int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1); 96 int pt2 = (address >> OFF_BITS) & ((1 << L2_BITS) - 1); 97 int pto = address & ((1 << OFF_BITS) - 1); 98 99 if (address == 0 && !recursing) 100 { 101 recursing = 1; 102 put_reg (pc, m32c_opcode_pc); 103 printf ("NULL pointer dereference at pc=0x%x\n", get_reg (pc)); 104 step_result = M32C_MAKE_HIT_BREAK (); 105 #if 0 106 /* This code can be re-enabled to help diagnose NULL pointer 107 bugs that aren't debuggable in GDB. */ 108 m32c_dump_all_registers (); 109 exit (1); 110 #endif 111 } 112 113 if (pt[pt1] == 0) 114 pt[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **)); 115 if (pt[pt1][pt2] == 0) 116 { 117 pt[pt1][pt2] = (unsigned char *) malloc (OFF_LEN); 118 memset (pt[pt1][pt2], 0, OFF_LEN); 119 } 120 121 return pt[pt1][pt2] + pto; 122 } 123 124 static void 125 used (int rstart, int i, int j) 126 { 127 int rend = i << (L2_BITS + OFF_BITS); 128 rend += j << OFF_BITS; 129 if (rstart == 0xe0000 && rend == 0xe1000) 130 return; 131 printf ("mem: %08x - %08x (%dk bytes)\n", rstart, rend - 1, 132 (rend - rstart) / 1024); 133 } 134 135 static char * 136 mcs (int isput, int bytes) 137 { 138 return comma (mem_counters[isput][bytes]); 139 } 140 141 void 142 mem_usage_stats (void) 143 { 144 int i, j; 145 int rstart = 0; 146 int pending = 0; 147 148 for (i = 0; i < L1_LEN; i++) 149 if (pt[i]) 150 { 151 for (j = 0; j < L2_LEN; j++) 152 if (pt[i][j]) 153 { 154 if (!pending) 155 { 156 pending = 1; 157 rstart = (i << (L2_BITS + OFF_BITS)) + (j << OFF_BITS); 158 } 159 } 160 else if (pending) 161 { 162 pending = 0; 163 used (rstart, i, j); 164 } 165 } 166 else 167 { 168 if (pending) 169 { 170 pending = 0; 171 used (rstart, i, 0); 172 } 173 } 174 /* mem foo: 123456789012 123456789012 123456789012 123456789012 175 123456789012 */ 176 printf (" byte short pointer long" 177 " fetch\n"); 178 printf ("mem get: %12s %12s %12s %12s %12s\n", mcs (0, 1), mcs (0, 2), 179 mcs (0, 3), mcs (0, 4), mcs (0, 0)); 180 printf ("mem put: %12s %12s %12s %12s\n", mcs (1, 1), mcs (1, 2), 181 mcs (1, 3), mcs (1, 4)); 182 } 183 184 static int tpr = 0; 185 static void 186 s (int address, char *dir) 187 { 188 if (tpr == 0) 189 printf ("MEM[%0*x] %s", membus_mask == 0xfffff ? 5 : 6, address, dir); 190 tpr++; 191 } 192 193 #define S(d) if (trace) s(address, d) 194 static void 195 e (void) 196 { 197 if (!trace) 198 return; 199 tpr--; 200 if (tpr == 0) 201 printf ("\n"); 202 } 203 204 #define E() if (trace) e() 205 206 extern int m32c_disassemble; 207 208 static void 209 mem_put_byte (int address, unsigned char value) 210 { 211 unsigned char *m; 212 address &= membus_mask; 213 m = mem_ptr (address); 214 if (trace) 215 printf (" %02x", value); 216 *m = value; 217 switch (address) 218 { 219 case 0x00e1: 220 { 221 static int old_led = -1; 222 static char *led_on[] = 223 { "\033[31m O ", "\033[32m O ", "\033[34m O " }; 224 static char *led_off[] = { "\033[0m · ", "\033[0m · ", "\033[0m · " }; 225 int i; 226 if (old_led != value) 227 { 228 fputs (" ", stdout); 229 for (i = 0; i < 3; i++) 230 if (value & (1 << i)) 231 fputs (led_off[i], stdout); 232 else 233 fputs (led_on[i], stdout); 234 fputs ("\033[0m\r", stdout); 235 fflush (stdout); 236 old_led = value; 237 } 238 } 239 break; 240 #ifdef TIMER_A 241 /* M32C Timer A */ 242 case 0x346: /* TA0low */ 243 timer_a.count = (timer_a.count & 0xff00) | value; 244 timer_a.reload = timer_a.count; 245 break; 246 case 0x347: /* TA0high */ 247 timer_a.count = (timer_a.count & 0x00ff) | (value << 8); 248 timer_a.reload = timer_a.count; 249 break; 250 case 0x340: /* TABSR */ 251 timer_a.bsr = value; 252 break; 253 case 0x356: /* TA0MR */ 254 timer_a.mode = value; 255 break; 256 case 0x35f: /* TCSPR */ 257 timer_a.tcspr = value; 258 break; 259 case 0x006c: /* TA0IC */ 260 timer_a.ic = value; 261 break; 262 263 /* R8C Timer RA */ 264 case 0x100: /* TRACR */ 265 timer_a.bsr = value; 266 break; 267 case 0x102: /* TRAMR */ 268 timer_a.mode = value; 269 break; 270 case 0x104: /* TRA */ 271 timer_a.count = value; 272 timer_a.reload = value; 273 break; 274 case 0x103: /* TRAPRE */ 275 timer_a.tcspr = value; 276 break; 277 case 0x0056: /* TA0IC */ 278 timer_a.ic = value; 279 break; 280 #endif 281 282 case 0x2ea: /* m32c uart1tx */ 283 case 0x3aa: /* m16c uart1tx */ 284 { 285 static int pending_exit = 0; 286 if (value == 0) 287 { 288 if (pending_exit) 289 { 290 step_result = M32C_MAKE_EXITED (value); 291 return; 292 } 293 pending_exit = 1; 294 } 295 else 296 { 297 if (write (m32c_console_ofd, &value, 1) != 1) 298 printf ("write console failed: %s\n", strerror (errno)); 299 } 300 } 301 break; 302 303 case 0x400: 304 m32c_syscall (value); 305 break; 306 307 case 0x401: 308 putchar (value); 309 break; 310 311 case 0x402: 312 printf ("SimTrace: %06lx %02x\n", regs.r_pc, value); 313 break; 314 315 case 0x403: 316 printf ("SimTrap: %06lx %02x\n", regs.r_pc, value); 317 abort (); 318 } 319 } 320 321 void 322 mem_put_qi (int address, unsigned char value) 323 { 324 S ("<="); 325 mem_put_byte (address, value & 0xff); 326 E (); 327 COUNT (1, 1); 328 } 329 330 void 331 mem_put_hi (int address, unsigned short value) 332 { 333 if (address == 0x402) 334 { 335 printf ("SimTrace: %06lx %04x\n", regs.r_pc, value); 336 return; 337 } 338 S ("<="); 339 mem_put_byte (address, value & 0xff); 340 mem_put_byte (address + 1, value >> 8); 341 E (); 342 COUNT (1, 2); 343 } 344 345 void 346 mem_put_psi (int address, unsigned long value) 347 { 348 S ("<="); 349 mem_put_byte (address, value & 0xff); 350 mem_put_byte (address + 1, (value >> 8) & 0xff); 351 mem_put_byte (address + 2, value >> 16); 352 E (); 353 COUNT (1, 3); 354 } 355 356 void 357 mem_put_si (int address, unsigned long value) 358 { 359 S ("<="); 360 mem_put_byte (address, value & 0xff); 361 mem_put_byte (address + 1, (value >> 8) & 0xff); 362 mem_put_byte (address + 2, (value >> 16) & 0xff); 363 mem_put_byte (address + 3, (value >> 24) & 0xff); 364 E (); 365 COUNT (1, 4); 366 } 367 368 void 369 mem_put_blk (int address, const void *bufptr, int nbytes) 370 { 371 const unsigned char *buf = bufptr; 372 373 S ("<="); 374 if (enable_counting) 375 mem_counters[1][1] += nbytes; 376 while (nbytes--) 377 mem_put_byte (address++, *buf++); 378 E (); 379 } 380 381 unsigned char 382 mem_get_pc (void) 383 { 384 unsigned char *m = mem_ptr (regs.r_pc & membus_mask); 385 COUNT (0, 0); 386 return *m; 387 } 388 389 #ifdef HAVE_TERMIOS_H 390 static int console_raw = 0; 391 static struct termios oattr; 392 393 static int 394 stdin_ready (void) 395 { 396 fd_set ifd; 397 int n; 398 struct timeval t; 399 400 t.tv_sec = 0; 401 t.tv_usec = 0; 402 FD_ZERO (&ifd); 403 FD_SET (m32c_console_ifd, &ifd); 404 n = select (1, &ifd, 0, 0, &t); 405 return n > 0; 406 } 407 408 void 409 m32c_sim_restore_console (void) 410 { 411 if (console_raw) 412 tcsetattr (m32c_console_ifd, TCSANOW, &oattr); 413 console_raw = 0; 414 } 415 #endif 416 417 static unsigned char 418 mem_get_byte (int address) 419 { 420 unsigned char *m; 421 address &= membus_mask; 422 m = mem_ptr (address); 423 switch (address) 424 { 425 #ifdef HAVE_TERMIOS_H 426 case 0x2ed: /* m32c uart1c1 */ 427 case 0x3ad: /* m16c uart1c1 */ 428 429 if (!console_raw && m32c_use_raw_console) 430 { 431 struct termios attr; 432 tcgetattr (m32c_console_ifd, &attr); 433 tcgetattr (m32c_console_ifd, &oattr); 434 /* We want each key to be sent as the user presses them. */ 435 attr.c_lflag &= ~(ICANON | ECHO | ECHOE); 436 tcsetattr (m32c_console_ifd, TCSANOW, &attr); 437 console_raw = 1; 438 atexit (m32c_sim_restore_console); 439 } 440 441 if (stdin_ready ()) 442 return 0x02; /* tx empty and rx full */ 443 else 444 return 0x0a; /* transmitter empty */ 445 446 case 0x2ee: /* m32c uart1 rx */ 447 { 448 char c; 449 if (read (m32c_console_ifd, &c, 1) != 1) 450 return 0; 451 if (m32c_console_ifd == 0 && c == 3) /* Ctrl-C */ 452 { 453 printf ("Ctrl-C!\n"); 454 exit (0); 455 } 456 457 if (m32c_console_ifd != 1) 458 { 459 if (isgraph (c)) 460 printf ("\033[31m%c\033[0m", c); 461 else 462 printf ("\033[31m%02x\033[0m", c); 463 } 464 return c; 465 } 466 #endif 467 468 #ifdef TIMER_A 469 case 0x346: /* TA0low */ 470 return timer_a.count & 0xff; 471 case 0x347: /* TA0high */ 472 return (timer_a.count >> 8) & 0xff; 473 case 0x104: /* TRA */ 474 return timer_a.count; 475 #endif 476 477 default: 478 /* In case both cases above are not included. */ 479 ; 480 } 481 482 S ("=>"); 483 if (trace) 484 printf (" %02x", *m); 485 E (); 486 return *m; 487 } 488 489 unsigned char 490 mem_get_qi (int address) 491 { 492 unsigned char rv; 493 S ("=>"); 494 rv = mem_get_byte (address); 495 COUNT (0, 1); 496 E (); 497 return rv; 498 } 499 500 unsigned short 501 mem_get_hi (int address) 502 { 503 unsigned short rv; 504 S ("=>"); 505 rv = mem_get_byte (address); 506 rv |= mem_get_byte (address + 1) * 256; 507 COUNT (0, 2); 508 E (); 509 return rv; 510 } 511 512 unsigned long 513 mem_get_psi (int address) 514 { 515 unsigned long rv; 516 S ("=>"); 517 rv = mem_get_byte (address); 518 rv |= mem_get_byte (address + 1) * 256; 519 rv |= mem_get_byte (address + 2) * 65536; 520 COUNT (0, 3); 521 E (); 522 return rv; 523 } 524 525 unsigned long 526 mem_get_si (int address) 527 { 528 unsigned long rv; 529 S ("=>"); 530 rv = mem_get_byte (address); 531 rv |= mem_get_byte (address + 1) << 8; 532 rv |= mem_get_byte (address + 2) << 16; 533 rv |= mem_get_byte (address + 3) << 24; 534 COUNT (0, 4); 535 E (); 536 return rv; 537 } 538 539 void 540 mem_get_blk (int address, void *bufptr, int nbytes) 541 { 542 char *buf = bufptr; 543 544 S ("=>"); 545 if (enable_counting) 546 mem_counters[0][1] += nbytes; 547 while (nbytes--) 548 *buf++ = mem_get_byte (address++); 549 E (); 550 } 551 552 int 553 sign_ext (int v, int bits) 554 { 555 if (bits < 32) 556 { 557 v &= (1 << bits) - 1; 558 if (v & (1 << (bits - 1))) 559 v -= (1 << bits); 560 } 561 return v; 562 } 563 564 #if TIMER_A 565 void 566 update_timer_a (void) 567 { 568 if (timer_a.bsr & 1) 569 { 570 timer_a.prescale--; 571 if (timer_a.prescale < 0) 572 { 573 if (A24) 574 { 575 switch (timer_a.mode & 0xc0) 576 { 577 case 0x00: 578 timer_a.prescale = 0; 579 break; 580 case 0x40: 581 timer_a.prescale = 8; 582 break; 583 case 0x80: 584 timer_a.prescale = timer_a.tcspr & 0x0f; 585 break; 586 case 0xc0: 587 timer_a.prescale = 32; 588 break; 589 } 590 } 591 else 592 { 593 timer_a.prescale = timer_a.tcspr; 594 } 595 timer_a.count--; 596 if (timer_a.count < 0) 597 { 598 timer_a.count = timer_a.reload; 599 if (timer_a.ic & 7) 600 { 601 if (A24) 602 mem_put_qi (0x6c, timer_a.ic | 0x08); 603 else 604 mem_put_qi (0x56, timer_a.ic | 0x08); 605 } 606 } 607 } 608 } 609 610 if (regs.r_flags & FLAGBIT_I /* interrupts enabled */ 611 && timer_a.ic & 0x08 /* timer A interrupt triggered */ 612 && (timer_a.ic & 0x07) > ((regs.r_flags >> 12) & 0x07)) 613 { 614 if (A24) 615 trigger_peripheral_interrupt (12, 0x06c); 616 else 617 trigger_peripheral_interrupt (22, 0x056); 618 } 619 } 620 #endif 621