1 /* reg.c --- register set model for RX simulator. 2 3 Copyright (C) 2005-2014 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 27 #include "cpu.h" 28 #include "bfd.h" 29 #include "trace.h" 30 31 int verbose = 0; 32 int trace = 0; 33 int enable_counting = 0; 34 35 int rx_in_gdb = 1; 36 37 int rx_flagmask; 38 int rx_flagand; 39 int rx_flagor; 40 41 int rx_big_endian; 42 regs_type regs; 43 int step_result; 44 unsigned int heapbottom = 0; 45 unsigned int heaptop = 0; 46 47 char *reg_names[] = { 48 /* general registers */ 49 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 50 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 51 /* control register */ 52 "psw", "pc", "usp", "fpsw", "RES", "RES", "RES", "RES", 53 "bpsw", "bpc", "isp", "fintv", "intb", "RES", "RES", "RES", 54 "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", 55 "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", 56 "temp", "acc", "acchi", "accmi", "acclo" 57 }; 58 59 unsigned int b2mask[] = { 0, 0xff, 0xffff, 0xffffff, 0xffffffff }; 60 unsigned int b2signbit[] = { 0, (1 << 7), (1 << 15), (1 << 24), (1 << 31) }; 61 int b2maxsigned[] = { 0, 0x7f, 0x7fff, 0x7fffff, 0x7fffffff }; 62 int b2minsigned[] = { 0, -128, -32768, -8388608, -2147483647 - 1 }; 63 64 static regs_type oldregs; 65 66 void 67 init_regs (void) 68 { 69 memset (®s, 0, sizeof (regs)); 70 memset (&oldregs, 0, sizeof (oldregs)); 71 72 #ifdef CYCLE_ACCURATE 73 regs.rt = -1; 74 oldregs.rt = -1; 75 #endif 76 } 77 78 static unsigned int 79 get_reg_i (int id) 80 { 81 if (id == 0) 82 return regs.r_psw & FLAGBIT_U ? regs.r_usp : regs.r_isp; 83 84 if (id >= 1 && id <= 15) 85 return regs.r[id]; 86 87 switch (id) 88 { 89 case psw: 90 return regs.r_psw; 91 case fpsw: 92 return regs.r_fpsw; 93 case isp: 94 return regs.r_isp; 95 case usp: 96 return regs.r_usp; 97 case bpc: 98 return regs.r_bpc; 99 case bpsw: 100 return regs.r_bpsw; 101 case fintv: 102 return regs.r_fintv; 103 case intb: 104 return regs.r_intb; 105 case pc: 106 return regs.r_pc; 107 case r_temp_idx: 108 return regs.r_temp; 109 case acchi: 110 return (SI)(regs.r_acc >> 32); 111 case accmi: 112 return (SI)(regs.r_acc >> 16); 113 case acclo: 114 return (SI)regs.r_acc; 115 } 116 abort(); 117 } 118 119 unsigned int 120 get_reg (int id) 121 { 122 unsigned int rv = get_reg_i (id); 123 if (trace > ((id != pc && id != sp) ? 0 : 1)) 124 printf ("get_reg (%s) = %08x\n", reg_names[id], rv); 125 return rv; 126 } 127 128 static unsigned long long 129 get_reg64_i (int id) 130 { 131 switch (id) 132 { 133 case acc64: 134 return regs.r_acc; 135 default: 136 abort (); 137 } 138 } 139 140 unsigned long long 141 get_reg64 (int id) 142 { 143 unsigned long long rv = get_reg64_i (id); 144 if (trace > ((id != pc && id != sp) ? 0 : 1)) 145 printf ("get_reg (%s) = %016llx\n", reg_names[id], rv); 146 return rv; 147 } 148 149 static int highest_sp = 0, lowest_sp = 0xffffff; 150 151 void 152 stack_heap_stats () 153 { 154 if (heapbottom < heaptop) 155 printf ("heap: %08x - %08x (%d bytes)\n", heapbottom, heaptop, 156 heaptop - heapbottom); 157 if (lowest_sp < highest_sp) 158 printf ("stack: %08x - %08x (%d bytes)\n", lowest_sp, highest_sp, 159 highest_sp - lowest_sp); 160 } 161 162 void 163 put_reg (int id, unsigned int v) 164 { 165 if (trace > ((id != pc) ? 0 : 1)) 166 printf ("put_reg (%s) = %08x\n", reg_names[id], v); 167 168 169 switch (id) 170 { 171 case psw: 172 regs.r_psw = v; 173 break; 174 case fpsw: 175 { 176 SI anded; 177 /* This is an odd one - The Cx flags are AND'd, and the FS flag 178 is synthetic. */ 179 anded = regs.r_fpsw & v; 180 anded |= ~ FPSWBITS_CMASK; 181 regs.r_fpsw = v & anded; 182 if (regs.r_fpsw & FPSWBITS_FMASK) 183 regs.r_fpsw |= FPSWBITS_FSUM; 184 else 185 regs.r_fpsw &= ~FPSWBITS_FSUM; 186 } 187 break; 188 case isp: 189 regs.r_isp = v; 190 break; 191 case usp: 192 regs.r_usp = v; 193 break; 194 case bpc: 195 regs.r_bpc = v; 196 break; 197 case bpsw: 198 regs.r_bpsw = v; 199 break; 200 case fintv: 201 regs.r_fintv = v; 202 break; 203 case intb: 204 regs.r_intb = v; 205 break; 206 case pc: 207 regs.r_pc = v; 208 break; 209 210 case acchi: 211 regs.r_acc = (regs.r_acc & 0xffffffffULL) | ((DI)v << 32); 212 break; 213 case accmi: 214 regs.r_acc = (regs.r_acc & ~0xffffffff0000ULL) | ((DI)v << 16); 215 break; 216 case acclo: 217 regs.r_acc = (regs.r_acc & ~0xffffffffULL) | ((DI)v); 218 break; 219 220 case 0: /* Stack pointer is "in" R0. */ 221 { 222 if (v < heaptop) 223 { 224 unsigned int line; 225 const char * dummy; 226 const char * fname = NULL; 227 228 sim_get_current_source_location (& dummy, & fname, &line); 229 230 /* The setjmp and longjmp functions play tricks with the stack pointer. */ 231 if (fname == NULL 232 || (strcmp (fname, "_setjmp") != 0 233 && strcmp (fname, "_longjmp") != 0)) 234 { 235 printf ("collision in %s: pc %08x heap %08x stack %08x\n", 236 fname, (unsigned int) regs.r_pc, heaptop, v); 237 exit (1); 238 } 239 } 240 else 241 { 242 if (v < lowest_sp) 243 lowest_sp = v; 244 if (v > highest_sp) 245 highest_sp = v; 246 } 247 248 if (regs.r_psw & FLAGBIT_U) 249 regs.r_usp = v; 250 else 251 regs.r_isp = v; 252 break; 253 } 254 255 default: 256 if (id >= 1 || id <= 15) 257 regs.r[id] = v; 258 else 259 abort (); 260 } 261 } 262 263 void 264 put_reg64 (int id, unsigned long long v) 265 { 266 if (trace > ((id != pc) ? 0 : 1)) 267 printf ("put_reg (%s) = %016llx\n", reg_names[id], v); 268 269 switch (id) 270 { 271 case acc64: 272 regs.r_acc = v; 273 break; 274 default: 275 abort (); 276 } 277 } 278 279 int 280 condition_true (int cond_id) 281 { 282 int f; 283 284 static const char *cond_name[] = { 285 "Z", 286 "!Z", 287 "C", 288 "!C", 289 "C&!Z", 290 "!(C&!Z)", 291 "!S", 292 "S", 293 "!(S^O)", 294 "S^O", 295 "!((S^O)|Z)", 296 "(S^O)|Z", 297 "O", 298 "!O", 299 "always", 300 "never" 301 }; 302 switch (cond_id & 15) 303 { 304 case 0: 305 f = FLAG_Z; 306 break; /* EQ/Z */ 307 case 1: 308 f = !FLAG_Z; 309 break; /* NE/NZ */ 310 case 2: 311 f = FLAG_C; 312 break; /* GEU/C */ 313 case 3: 314 f = !FLAG_C; 315 break; /* LTU/NC */ 316 case 4: 317 f = FLAG_C & !FLAG_Z; 318 break; /* GTU */ 319 case 5: 320 f = !(FLAG_C & !FLAG_Z); 321 break; /* LEU */ 322 case 6: 323 f = !FLAG_S; 324 break; /* PZ */ 325 case 7: 326 f = FLAG_S; 327 break; /* N */ 328 329 case 8: 330 f = !(FLAG_S ^ FLAG_O); 331 break; /* GE */ 332 case 9: 333 f = FLAG_S ^ FLAG_O; 334 break; /* LT */ 335 case 10: 336 f = !((FLAG_S ^ FLAG_O) | FLAG_Z); 337 break; /* GT */ 338 case 11: 339 f = (FLAG_S ^ FLAG_O) | FLAG_Z; 340 break; /* LE */ 341 case 12: 342 f = FLAG_O; 343 break; /* O */ 344 case 13: 345 f = !FLAG_O; 346 break; /* NO */ 347 case 14: 348 f = 1; /* always */ 349 break; 350 default: 351 f = 0; /* never */ 352 break; 353 } 354 if (trace && ((cond_id & 15) != 14)) 355 printf ("cond[%d] %s = %s\n", cond_id, cond_name[cond_id & 15], 356 f ? "true" : "false"); 357 return f; 358 } 359 360 void 361 set_flags (int mask, int newbits) 362 { 363 regs.r_psw &= rx_flagand; 364 regs.r_psw |= rx_flagor; 365 regs.r_psw |= (newbits & mask & rx_flagmask); 366 367 if (trace) 368 { 369 int i; 370 printf ("flags now \033[32m %d", (int)((regs.r_psw >> 24) & 7)); 371 for (i = 17; i >= 0; i--) 372 if (0x3000f & (1 << i)) 373 { 374 if (regs.r_psw & (1 << i)) 375 putchar ("CZSO------------IU"[i]); 376 else 377 putchar ('-'); 378 } 379 printf ("\033[0m\n"); 380 } 381 } 382 383 void 384 set_oszc (long long value, int b, int c) 385 { 386 unsigned int mask = b2mask[b]; 387 int f = 0; 388 389 if (c) 390 f |= FLAGBIT_C; 391 if ((value & mask) == 0) 392 f |= FLAGBIT_Z; 393 if (value & b2signbit[b]) 394 f |= FLAGBIT_S; 395 if ((value > b2maxsigned[b]) || (value < b2minsigned[b])) 396 f |= FLAGBIT_O; 397 set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O | FLAGBIT_C, f); 398 } 399 400 void 401 set_szc (long long value, int b, int c) 402 { 403 unsigned int mask = b2mask[b]; 404 int f = 0; 405 406 if (c) 407 f |= FLAGBIT_C; 408 if ((value & mask) == 0) 409 f |= FLAGBIT_Z; 410 if (value & b2signbit[b]) 411 f |= FLAGBIT_S; 412 set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_C, f); 413 } 414 415 void 416 set_osz (long long value, int b) 417 { 418 unsigned int mask = b2mask[b]; 419 int f = 0; 420 421 if ((value & mask) == 0) 422 f |= FLAGBIT_Z; 423 if (value & b2signbit[b]) 424 f |= FLAGBIT_S; 425 if ((value > b2maxsigned[b]) || (value < b2minsigned[b])) 426 f |= FLAGBIT_O; 427 set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, f); 428 } 429 430 void 431 set_sz (long long value, int b) 432 { 433 unsigned int mask = b2mask[b]; 434 int f = 0; 435 436 if ((value & mask) == 0) 437 f |= FLAGBIT_Z; 438 if (value & b2signbit[b]) 439 f |= FLAGBIT_S; 440 set_flags (FLAGBIT_Z | FLAGBIT_S, f); 441 } 442 443 void 444 set_zc (int z, int c) 445 { 446 set_flags (FLAGBIT_C | FLAGBIT_Z, 447 (c ? FLAGBIT_C : 0) | (z ? FLAGBIT_Z : 0)); 448 } 449 450 void 451 set_c (int c) 452 { 453 set_flags (FLAGBIT_C, c ? FLAGBIT_C : 0); 454 } 455 456 static char * 457 psw2str(int rpsw) 458 { 459 static char buf[10]; 460 char *bp = buf; 461 int i, ipl; 462 463 ipl = (rpsw & FLAGBITS_IPL) >> FLAGSHIFT_IPL; 464 if (ipl > 9) 465 { 466 *bp++ = (ipl / 10) + '0'; 467 ipl %= 10; 468 } 469 *bp++ = ipl + '0'; 470 for (i = 20; i >= 0; i--) 471 if (0x13000f & (1 << i)) 472 { 473 if (rpsw & (1 << i)) 474 *bp++ = "CZSO------------IU--P"[i]; 475 else 476 *bp++ = '-'; 477 } 478 *bp = 0; 479 return buf; 480 } 481 482 static char * 483 fpsw2str(int rpsw) 484 { 485 static char buf[100]; 486 char *bp = buf; 487 int i; /* ---+---+---+---+---+---+---+---+ */ 488 const char s1[] = "FFFFFF-----------EEEEE-DCCCCCCRR"; 489 const char s2[] = "SXUZOV-----------XUZOV-NEXUZOV01"; 490 const char rm[4][3] = { "RC", "RZ", "RP", "RN" }; 491 492 for (i = 31; i >= 0; i--) 493 if (0xfc007dfc & (1 << i)) 494 { 495 if (rpsw & (1 << i)) 496 { 497 if (bp > buf) 498 *bp++ = '.'; 499 *bp++ = s1[31-i]; 500 *bp++ = s2[31-i]; 501 } 502 } 503 if (bp > buf) 504 *bp++ = '.'; 505 strcpy (bp, rm[rpsw&3]); 506 return buf; 507 } 508 509 #define TRC(f,n) \ 510 if (oldregs.f != regs.f) \ 511 { \ 512 if (tag) { printf (tag); tag = 0; } \ 513 printf(" %s %08x:%08x", n, \ 514 (unsigned int)oldregs.f, \ 515 (unsigned int)regs.f); \ 516 oldregs.f = regs.f; \ 517 } 518 519 void 520 trace_register_changes (void) 521 { 522 char *tag = "\033[36mREGS:"; 523 int i; 524 525 if (!trace) 526 return; 527 for (i=1; i<16; i++) 528 TRC (r[i], reg_names[i]); 529 TRC (r_intb, "intb"); 530 TRC (r_usp, "usp"); 531 TRC (r_isp, "isp"); 532 if (oldregs.r_psw != regs.r_psw) 533 { 534 if (tag) { printf (tag); tag = 0; } 535 printf(" psw %s:", psw2str(oldregs.r_psw)); 536 printf("%s", psw2str(regs.r_psw)); 537 oldregs.r_psw = regs.r_psw; 538 } 539 540 if (oldregs.r_fpsw != regs.r_fpsw) 541 { 542 if (tag) { printf (tag); tag = 0; } 543 printf(" fpsw %s:", fpsw2str(oldregs.r_fpsw)); 544 printf("%s", fpsw2str(regs.r_fpsw)); 545 oldregs.r_fpsw = regs.r_fpsw; 546 } 547 548 if (oldregs.r_acc != regs.r_acc) 549 { 550 if (tag) { printf (tag); tag = 0; } 551 printf(" acc %016llx:", oldregs.r_acc); 552 printf("%016llx", regs.r_acc); 553 oldregs.r_acc = regs.r_acc; 554 } 555 556 if (tag == 0) 557 printf ("\033[0m\n"); 558 } 559