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