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