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