1 /* mem.c --- memory for M32C simulator. 2 3 Copyright (C) 2005-2015 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 22 #include "config.h" 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <ctype.h> 27 #include <sys/time.h> 28 #include <sys/types.h> 29 #include <unistd.h> 30 #ifdef HAVE_SYS_SELECT_H 31 #include <sys/select.h> 32 #endif 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 (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 () 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 () 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 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 write (m32c_console_ofd, &value, 1); 298 } 299 } 300 break; 301 302 case 0x400: 303 m32c_syscall (value); 304 break; 305 306 case 0x401: 307 putchar (value); 308 break; 309 310 case 0x402: 311 printf ("SimTrace: %06lx %02x\n", regs.r_pc, value); 312 break; 313 314 case 0x403: 315 printf ("SimTrap: %06lx %02x\n", regs.r_pc, value); 316 abort (); 317 } 318 } 319 320 void 321 mem_put_qi (int address, unsigned char value) 322 { 323 S ("<="); 324 mem_put_byte (address, value & 0xff); 325 E (); 326 COUNT (1, 1); 327 } 328 329 void 330 mem_put_hi (int address, unsigned short value) 331 { 332 if (address == 0x402) 333 { 334 printf ("SimTrace: %06lx %04x\n", regs.r_pc, value); 335 return; 336 } 337 S ("<="); 338 mem_put_byte (address, value & 0xff); 339 mem_put_byte (address + 1, value >> 8); 340 E (); 341 COUNT (1, 2); 342 } 343 344 void 345 mem_put_psi (int address, unsigned long value) 346 { 347 S ("<="); 348 mem_put_byte (address, value & 0xff); 349 mem_put_byte (address + 1, (value >> 8) & 0xff); 350 mem_put_byte (address + 2, value >> 16); 351 E (); 352 COUNT (1, 3); 353 } 354 355 void 356 mem_put_si (int address, unsigned long value) 357 { 358 S ("<="); 359 mem_put_byte (address, value & 0xff); 360 mem_put_byte (address + 1, (value >> 8) & 0xff); 361 mem_put_byte (address + 2, (value >> 16) & 0xff); 362 mem_put_byte (address + 3, (value >> 24) & 0xff); 363 E (); 364 COUNT (1, 4); 365 } 366 367 void 368 mem_put_blk (int address, const void *bufptr, int nbytes) 369 { 370 S ("<="); 371 if (enable_counting) 372 mem_counters[1][1] += nbytes; 373 while (nbytes--) 374 mem_put_byte (address++, *(const unsigned char *) bufptr++); 375 E (); 376 } 377 378 unsigned char 379 mem_get_pc () 380 { 381 unsigned char *m = mem_ptr (regs.r_pc & membus_mask); 382 COUNT (0, 0); 383 return *m; 384 } 385 386 #ifdef HAVE_TERMIOS_H 387 static int console_raw = 0; 388 static struct termios oattr; 389 390 static int 391 stdin_ready () 392 { 393 fd_set ifd; 394 int n; 395 struct timeval t; 396 397 t.tv_sec = 0; 398 t.tv_usec = 0; 399 FD_ZERO (&ifd); 400 FD_SET (m32c_console_ifd, &ifd); 401 n = select (1, &ifd, 0, 0, &t); 402 return n > 0; 403 } 404 405 void 406 m32c_sim_restore_console () 407 { 408 if (console_raw) 409 tcsetattr (m32c_console_ifd, TCSANOW, &oattr); 410 console_raw = 0; 411 } 412 #endif 413 414 static unsigned char 415 mem_get_byte (int address) 416 { 417 unsigned char *m; 418 address &= membus_mask; 419 m = mem_ptr (address); 420 switch (address) 421 { 422 #ifdef HAVE_TERMIOS_H 423 case 0x2ed: /* m32c uart1c1 */ 424 case 0x3ad: /* m16c uart1c1 */ 425 426 if (!console_raw && m32c_use_raw_console) 427 { 428 struct termios attr; 429 tcgetattr (m32c_console_ifd, &attr); 430 tcgetattr (m32c_console_ifd, &oattr); 431 /* We want each key to be sent as the user presses them. */ 432 attr.c_lflag &= ~(ICANON | ECHO | ECHOE); 433 tcsetattr (m32c_console_ifd, TCSANOW, &attr); 434 console_raw = 1; 435 atexit (m32c_sim_restore_console); 436 } 437 438 if (stdin_ready ()) 439 return 0x02; /* tx empty and rx full */ 440 else 441 return 0x0a; /* transmitter empty */ 442 443 case 0x2ee: /* m32c uart1 rx */ 444 { 445 char c; 446 read (m32c_console_ifd, &c, 1); 447 if (m32c_console_ifd == 0 && c == 3) /* Ctrl-C */ 448 { 449 printf ("Ctrl-C!\n"); 450 exit (0); 451 } 452 453 if (m32c_console_ifd != 1) 454 { 455 if (isgraph (c)) 456 printf ("\033[31m%c\033[0m", c); 457 else 458 printf ("\033[31m%02x\033[0m", c); 459 } 460 return c; 461 } 462 #endif 463 464 #ifdef TIMER_A 465 case 0x346: /* TA0low */ 466 return timer_a.count & 0xff; 467 case 0x347: /* TA0high */ 468 return (timer_a.count >> 8) & 0xff; 469 case 0x104: /* TRA */ 470 return timer_a.count; 471 #endif 472 473 default: 474 /* In case both cases above are not included. */ 475 ; 476 } 477 478 S ("=>"); 479 if (trace) 480 printf (" %02x", *m); 481 E (); 482 return *m; 483 } 484 485 unsigned char 486 mem_get_qi (int address) 487 { 488 unsigned char rv; 489 S ("=>"); 490 rv = mem_get_byte (address); 491 COUNT (0, 1); 492 E (); 493 return rv; 494 } 495 496 unsigned short 497 mem_get_hi (int address) 498 { 499 unsigned short rv; 500 S ("=>"); 501 rv = mem_get_byte (address); 502 rv |= mem_get_byte (address + 1) * 256; 503 COUNT (0, 2); 504 E (); 505 return rv; 506 } 507 508 unsigned long 509 mem_get_psi (int address) 510 { 511 unsigned long rv; 512 S ("=>"); 513 rv = mem_get_byte (address); 514 rv |= mem_get_byte (address + 1) * 256; 515 rv |= mem_get_byte (address + 2) * 65536; 516 COUNT (0, 3); 517 E (); 518 return rv; 519 } 520 521 unsigned long 522 mem_get_si (int address) 523 { 524 unsigned long rv; 525 S ("=>"); 526 rv = mem_get_byte (address); 527 rv |= mem_get_byte (address + 1) << 8; 528 rv |= mem_get_byte (address + 2) << 16; 529 rv |= mem_get_byte (address + 3) << 24; 530 COUNT (0, 4); 531 E (); 532 return rv; 533 } 534 535 void 536 mem_get_blk (int address, void *bufptr, int nbytes) 537 { 538 S ("=>"); 539 if (enable_counting) 540 mem_counters[0][1] += nbytes; 541 while (nbytes--) 542 *(char *) bufptr++ = mem_get_byte (address++); 543 E (); 544 } 545 546 int 547 sign_ext (int v, int bits) 548 { 549 if (bits < 32) 550 { 551 v &= (1 << bits) - 1; 552 if (v & (1 << (bits - 1))) 553 v -= (1 << bits); 554 } 555 return v; 556 } 557 558 #if TIMER_A 559 void 560 update_timer_a () 561 { 562 if (timer_a.bsr & 1) 563 { 564 timer_a.prescale--; 565 if (timer_a.prescale < 0) 566 { 567 if (A24) 568 { 569 switch (timer_a.mode & 0xc0) 570 { 571 case 0x00: 572 timer_a.prescale = 0; 573 break; 574 case 0x40: 575 timer_a.prescale = 8; 576 break; 577 case 0x80: 578 timer_a.prescale = timer_a.tcspr & 0x0f; 579 break; 580 case 0xc0: 581 timer_a.prescale = 32; 582 break; 583 } 584 } 585 else 586 { 587 timer_a.prescale = timer_a.tcspr; 588 } 589 timer_a.count--; 590 if (timer_a.count < 0) 591 { 592 timer_a.count = timer_a.reload; 593 if (timer_a.ic & 7) 594 { 595 if (A24) 596 mem_put_qi (0x6c, timer_a.ic | 0x08); 597 else 598 mem_put_qi (0x56, timer_a.ic | 0x08); 599 } 600 } 601 } 602 } 603 604 if (regs.r_flags & FLAGBIT_I /* interrupts enabled */ 605 && timer_a.ic & 0x08 /* timer A interrupt triggered */ 606 && (timer_a.ic & 0x07) > ((regs.r_flags >> 12) & 0x07)) 607 { 608 if (A24) 609 trigger_peripheral_interrupt (12, 0x06c); 610 else 611 trigger_peripheral_interrupt (22, 0x056); 612 } 613 } 614 #endif 615