1 /* reg.c --- register set model for M32C 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 30 int verbose = 0; 31 int trace = 0; 32 int enable_counting = 0; 33 int in_gdb = 1; 34 35 regs_type regs; 36 int addr_mask = 0xffff; 37 int membus_mask = 0xfffff; 38 int m32c_cpu = 0; 39 int step_result; 40 unsigned int heapbottom = 0; 41 unsigned int heaptop = 0; 42 43 char *reg_names[] = { 44 "mem", 45 "r0", "r0h", "r0l", 46 "r1", "r1h", "r1l", 47 "r2", "r2r0", 48 "r3", "r3r1", 49 "r3r1r2r0", 50 "r3r2r1r0", 51 "a0", 52 "a1", "a1a0", 53 "sb", "fb", 54 "intb", "intbl", "intbh", 55 "sp", "usp", "isp", "pc", "flags" 56 }; 57 58 int reg_bytes[] = { 59 0, 60 2, 1, 1, 61 2, 1, 1, 62 2, 4, 63 2, 4, 64 8, 65 8, 66 2, 67 2, 4, 68 2, 2, 69 2, 1, 3, 70 2, 2, 2, 3, 2 71 }; 72 73 74 unsigned int b2mask[] = { 0, 0xff, 0xffff, 0xffffff, 0xffffffff }; 75 unsigned int b2signbit[] = { 0, (1 << 7), (1 << 15), (1 << 24), (1 << 31) }; 76 int b2maxsigned[] = { 0, 0x7f, 0x7fff, 0x7fffff, 0x7fffffff }; 77 int b2minsigned[] = { 0, -128, -32768, -8388608, -2147483647 - 1 }; 78 79 static regs_type oldregs; 80 81 int m32c_opcode_pc; 82 83 void 84 init_regs (void) 85 { 86 memset (®s, 0, sizeof (regs)); 87 memset (&oldregs, 0, sizeof (oldregs)); 88 } 89 90 void 91 set_pointer_width (int bytes) 92 { 93 if (bytes == 2) 94 { 95 addr_mask = 0xffff; 96 membus_mask = 0x000fffff; 97 reg_bytes[a0] = reg_bytes[a1] = reg_bytes[sb] = reg_bytes[fb] = 98 reg_bytes[sp] = reg_bytes[usp] = reg_bytes[isp] = 2; 99 } 100 else 101 { 102 addr_mask = 0xffffff; 103 membus_mask = 0x00ffffff; 104 reg_bytes[a0] = reg_bytes[a1] = reg_bytes[sb] = reg_bytes[fb] = 105 reg_bytes[sp] = reg_bytes[usp] = reg_bytes[isp] = 3; 106 } 107 } 108 109 void 110 m32c_set_cpu (int cpu) 111 { 112 switch (cpu) 113 { 114 case CPU_R8C: 115 case CPU_M16C: 116 set_pointer_width (2); 117 decode_opcode = decode_r8c; 118 break; 119 case CPU_M32CM: 120 case CPU_M32C: 121 set_pointer_width (3); 122 decode_opcode = decode_m32c; 123 break; 124 default: 125 abort (); 126 } 127 m32c_cpu = cpu; 128 } 129 130 static unsigned int 131 get_reg_i (reg_id id) 132 { 133 reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0); 134 135 switch (id) 136 { 137 case r0: 138 return b->r_r0; 139 case r0h: 140 return b->r_r0 >> 8; 141 case r0l: 142 return b->r_r0 & 0xff; 143 case r1: 144 return b->r_r1; 145 case r1h: 146 return b->r_r1 >> 8; 147 case r1l: 148 return b->r_r1 & 0xff; 149 case r2: 150 return b->r_r2; 151 case r2r0: 152 return b->r_r2 * 65536 + b->r_r0; 153 case r3: 154 return b->r_r3; 155 case r3r1: 156 return b->r_r3 * 65536 + b->r_r1; 157 158 case a0: 159 return b->r_a0 & addr_mask; 160 case a1: 161 return b->r_a1 & addr_mask; 162 case a1a0: 163 return (b->r_a1 & 0xffff) * 65536 | (b->r_a0 & 0xffff); 164 165 case sb: 166 return b->r_sb & addr_mask; 167 case fb: 168 return b->r_fb & addr_mask; 169 170 case intb: 171 return regs.r_intbh * 65536 + regs.r_intbl; 172 case intbl: 173 return regs.r_intbl; 174 case intbh: 175 return regs.r_intbh; 176 177 case sp: 178 return ((regs.r_flags & FLAGBIT_U) ? regs.r_usp : regs. 179 r_isp) & addr_mask; 180 case usp: 181 return regs.r_usp & addr_mask; 182 case isp: 183 return regs.r_isp & addr_mask; 184 185 case pc: 186 return regs.r_pc & membus_mask; 187 case flags: 188 return regs.r_flags; 189 default: 190 abort (); 191 } 192 } 193 194 unsigned int 195 get_reg (reg_id id) 196 { 197 unsigned int rv = get_reg_i (id); 198 if (trace > ((id != pc && id != fb && id != sp) ? 0 : 1)) 199 printf ("get_reg (%s) = %0*x\n", reg_names[id], reg_bytes[id] * 2, rv); 200 return rv; 201 } 202 203 DI 204 get_reg_ll (reg_id id) 205 { 206 reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0); 207 208 switch (id) 209 { 210 case r3r1r2r0: 211 return ((DI) b->r_r3 << 48 212 | (DI) b->r_r1 << 32 | (DI) b->r_r2 << 16 | (DI) b->r_r0); 213 case r3r2r1r0: 214 return ((DI) b->r_r3 << 48 215 | (DI) b->r_r2 << 32 | (DI) b->r_r1 << 16 | (DI) b->r_r0); 216 default: 217 return get_reg (id); 218 } 219 } 220 221 static int highest_sp = 0, lowest_sp = 0xffffff; 222 223 void 224 stack_heap_stats (void) 225 { 226 printf ("heap: %08x - %08x (%d bytes)\n", heapbottom, heaptop, 227 heaptop - heapbottom); 228 printf ("stack: %08x - %08x (%d bytes)\n", lowest_sp, highest_sp, 229 highest_sp - lowest_sp); 230 } 231 232 void 233 put_reg (reg_id id, unsigned int v) 234 { 235 reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0); 236 237 if (trace > ((id != pc) ? 0 : 1)) 238 printf ("put_reg (%s) = %0*x\n", reg_names[id], reg_bytes[id] * 2, v); 239 240 switch (id) 241 { 242 case r0: 243 b->r_r0 = v; 244 break; 245 case r0h: 246 b->r_r0 = (b->r_r0 & 0xff) | (v << 8); 247 break; 248 case r0l: 249 b->r_r0 = (b->r_r0 & 0xff00) | (v & 0xff); 250 break; 251 case r1: 252 b->r_r1 = v; 253 break; 254 case r1h: 255 b->r_r1 = (b->r_r1 & 0xff) | (v << 8); 256 break; 257 case r1l: 258 b->r_r1 = (b->r_r1 & 0xff00) | (v & 0xff); 259 break; 260 case r2: 261 b->r_r2 = v; 262 break; 263 case r2r0: 264 b->r_r0 = v & 0xffff; 265 b->r_r2 = v >> 16; 266 break; 267 case r3: 268 b->r_r3 = v; 269 break; 270 case r3r1: 271 b->r_r1 = v & 0xffff; 272 b->r_r3 = v >> 16; 273 break; 274 275 case a0: 276 b->r_a0 = v & addr_mask; 277 break; 278 case a1: 279 b->r_a1 = v & addr_mask; 280 break; 281 case a1a0: 282 b->r_a0 = v & 0xffff; 283 b->r_a1 = v >> 16; 284 break; 285 286 case sb: 287 b->r_sb = v & addr_mask; 288 break; 289 case fb: 290 b->r_fb = v & addr_mask; 291 break; 292 293 case intb: 294 regs.r_intbl = v & 0xffff; 295 regs.r_intbh = v >> 16; 296 break; 297 case intbl: 298 regs.r_intbl = v & 0xffff; 299 break; 300 case intbh: 301 regs.r_intbh = v & 0xff; 302 break; 303 304 case sp: 305 { 306 SI *spp; 307 if (regs.r_flags & FLAGBIT_U) 308 spp = ®s.r_usp; 309 else 310 spp = ®s.r_isp; 311 *spp = v & addr_mask; 312 if (*spp < heaptop) 313 { 314 printf ("collision: pc %08lx heap %08x stack %08lx\n", regs.r_pc, 315 heaptop, *spp); 316 exit (1); 317 } 318 if (*spp < lowest_sp) 319 lowest_sp = *spp; 320 if (*spp > highest_sp) 321 highest_sp = *spp; 322 break; 323 } 324 case usp: 325 regs.r_usp = v & addr_mask; 326 break; 327 case isp: 328 regs.r_isp = v & addr_mask; 329 break; 330 331 case pc: 332 regs.r_pc = v & membus_mask; 333 break; 334 case flags: 335 regs.r_flags = v; 336 break; 337 default: 338 abort (); 339 } 340 } 341 342 int 343 condition_true (int cond_id) 344 { 345 int f; 346 if (A16) 347 { 348 static const char *cond_name[] = { 349 "C", "C&!Z", "Z", "S", 350 "!C", "!(C&!Z)", "!Z", "!S", 351 "(S^O)|Z", "O", "!(S^O)", "unk", 352 "!((S^O)|Z)", "!O", "S^O", "unk" 353 }; 354 switch (cond_id & 15) 355 { 356 case 0: 357 f = FLAG_C; 358 break; /* GEU/C */ 359 case 1: 360 f = FLAG_C & !FLAG_Z; 361 break; /* GTU */ 362 case 2: 363 f = FLAG_Z; 364 break; /* EQ/Z */ 365 case 3: 366 f = FLAG_S; 367 break; /* N */ 368 case 4: 369 f = !FLAG_C; 370 break; /* LTU/NC */ 371 case 5: 372 f = !(FLAG_C & !FLAG_Z); 373 break; /* LEU */ 374 case 6: 375 f = !FLAG_Z; 376 break; /* NE/NZ */ 377 case 7: 378 f = !FLAG_S; 379 break; /* PZ */ 380 381 case 8: 382 f = (FLAG_S ^ FLAG_O) | FLAG_Z; 383 break; /* LE */ 384 case 9: 385 f = FLAG_O; 386 break; /* O */ 387 case 10: 388 f = !(FLAG_S ^ FLAG_O); 389 break; /* GE */ 390 case 12: 391 f = !((FLAG_S ^ FLAG_O) | FLAG_Z); 392 break; /* GT */ 393 case 13: 394 f = !FLAG_O; 395 break; /* NO */ 396 case 14: 397 f = FLAG_S ^ FLAG_O; 398 break; /* LT */ 399 400 default: 401 f = 0; 402 break; 403 } 404 if (trace) 405 printf ("cond[%d] %s = %s\n", cond_id, cond_name[cond_id & 15], 406 f ? "true" : "false"); 407 } 408 else 409 { 410 static const char *cond_name[] = { 411 "!C", "LEU", "!Z", "PZ", 412 "!O", "GT", "GE", "?", 413 "C", "GTU", "Z", "N", 414 "O", "LE", "LT", "!?" 415 }; 416 switch (cond_id & 15) 417 { 418 case 0: 419 f = !FLAG_C; 420 break; /* LTU/NC */ 421 case 1: 422 f = !(FLAG_C & !FLAG_Z); 423 break; /* LEU */ 424 case 2: 425 f = !FLAG_Z; 426 break; /* NE/NZ */ 427 case 3: 428 f = !FLAG_S; 429 break; /* PZ */ 430 431 case 4: 432 f = !FLAG_O; 433 break; /* NO */ 434 case 5: 435 f = !((FLAG_S ^ FLAG_O) | FLAG_Z); 436 break; /* GT */ 437 case 6: 438 f = !(FLAG_S ^ FLAG_O); 439 break; /* GE */ 440 441 case 8: 442 f = FLAG_C; 443 break; /* GEU/C */ 444 case 9: 445 f = FLAG_C & !FLAG_Z; 446 break; /* GTU */ 447 case 10: 448 f = FLAG_Z; 449 break; /* EQ/Z */ 450 case 11: 451 f = FLAG_S; 452 break; /* N */ 453 454 case 12: 455 f = FLAG_O; 456 break; /* O */ 457 case 13: 458 f = (FLAG_S ^ FLAG_O) | FLAG_Z; 459 break; /* LE */ 460 case 14: 461 f = FLAG_S ^ FLAG_O; 462 break; /* LT */ 463 464 default: 465 f = 0; 466 break; 467 } 468 if (trace) 469 printf ("cond[%d] %s = %s\n", cond_id, cond_name[cond_id & 15], 470 f ? "true" : "false"); 471 } 472 return f; 473 } 474 475 void 476 set_flags (int mask, int newbits) 477 { 478 int i; 479 regs.r_flags &= ~mask; 480 regs.r_flags |= newbits & mask; 481 if (trace) 482 { 483 printf ("flags now \033[32m %d", (regs.r_flags >> (A16 ? 8 : 12)) & 7); 484 for (i = 7; i >= 0; i--) 485 if (regs.r_flags & (1 << i)) 486 putchar ("CDZSBOIU"[i]); 487 else 488 putchar ('-'); 489 printf ("\033[0m\n"); 490 } 491 } 492 493 void 494 set_oszc (int value, int b, int c) 495 { 496 int mask = b2mask[b]; 497 int f = 0; 498 499 if (c) 500 f |= FLAGBIT_C; 501 if ((value & mask) == 0) 502 f |= FLAGBIT_Z; 503 if (value & b2signbit[b]) 504 f |= FLAGBIT_S; 505 if ((value > b2maxsigned[b]) || (value < b2minsigned[b])) 506 f |= FLAGBIT_O; 507 set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O | FLAGBIT_C, f); 508 } 509 510 void 511 set_szc (int value, int b, int c) 512 { 513 int mask = b2mask[b]; 514 int f = 0; 515 516 if (c) 517 f |= FLAGBIT_C; 518 if ((value & mask) == 0) 519 f |= FLAGBIT_Z; 520 if (value & b2signbit[b]) 521 f |= FLAGBIT_S; 522 set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_C, f); 523 } 524 525 void 526 set_osz (int value, int b) 527 { 528 int mask = b2mask[b]; 529 int f = 0; 530 531 if ((value & mask) == 0) 532 f |= FLAGBIT_Z; 533 if (value & b2signbit[b]) 534 f |= FLAGBIT_S; 535 if (value & ~mask && (value & ~mask) != ~mask) 536 f |= FLAGBIT_O; 537 set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, f); 538 } 539 540 void 541 set_sz (int value, int b) 542 { 543 int mask = b2mask[b]; 544 int f = 0; 545 546 if ((value & mask) == 0) 547 f |= FLAGBIT_Z; 548 if (value & b2signbit[b]) 549 f |= FLAGBIT_S; 550 set_flags (FLAGBIT_Z | FLAGBIT_S, f); 551 } 552 553 void 554 set_zc (int z, int c) 555 { 556 set_flags (FLAGBIT_C | FLAGBIT_Z, 557 (c ? FLAGBIT_C : 0) | (z ? FLAGBIT_Z : 0)); 558 } 559 560 void 561 set_c (int c) 562 { 563 set_flags (FLAGBIT_C, c ? FLAGBIT_C : 0); 564 } 565 566 void 567 put_reg_ll (reg_id id, DI v) 568 { 569 reg_bank_type *b = regs.r + (FLAG_B ? 1 : 0); 570 571 switch (id) 572 { 573 case r3r1r2r0: 574 b->r_r3 = v >> 48; 575 b->r_r1 = v >> 32; 576 b->r_r2 = v >> 16; 577 b->r_r0 = v; 578 break; 579 case r3r2r1r0: 580 b->r_r3 = v >> 48; 581 b->r_r2 = v >> 32; 582 b->r_r1 = v >> 16; 583 b->r_r0 = v; 584 break; 585 default: 586 put_reg (id, v); 587 } 588 } 589 590 static void 591 print_flags (int f) 592 { 593 int i; 594 static char fn[] = "CDZSBOIU"; 595 printf ("%d.", (f >> 12) & 7); 596 for (i = 7; i >= 0; i--) 597 if (f & (1 << i)) 598 putchar (fn[i]); 599 } 600 601 #define TRC(f,n, id) \ 602 if (oldregs.f != regs.f) \ 603 { \ 604 printf(" %s %0*x:%0*x", n, \ 605 reg_bytes[id]*2, (unsigned int)oldregs.f, \ 606 reg_bytes[id]*2, (unsigned int)regs.f); \ 607 oldregs.f = regs.f; \ 608 } 609 610 void 611 trace_register_changes (void) 612 { 613 if (!trace) 614 return; 615 printf ("\033[36mREGS:"); 616 TRC (r[0].r_r0, "r0", r0); 617 TRC (r[0].r_r1, "r1", r1); 618 TRC (r[0].r_r2, "r2", r2); 619 TRC (r[0].r_r3, "r3", r3); 620 TRC (r[0].r_a0, "a0", a0); 621 TRC (r[0].r_a1, "a1", a1); 622 TRC (r[0].r_sb, "sb", sb); 623 TRC (r[0].r_fb, "fb", fb); 624 TRC (r[1].r_r0, "r0'", r0); 625 TRC (r[1].r_r1, "r1'", r1); 626 TRC (r[1].r_r2, "r2'", r2); 627 TRC (r[1].r_r3, "r3'", r3); 628 TRC (r[1].r_a0, "a0'", a0); 629 TRC (r[1].r_a1, "a1'", a1); 630 TRC (r[1].r_sb, "sb'", sb); 631 TRC (r[1].r_fb, "fb'", fb); 632 TRC (r_intbh, "intbh", intbh); 633 TRC (r_intbl, "intbl", intbl); 634 TRC (r_usp, "usp", usp); 635 TRC (r_isp, "isp", isp); 636 TRC (r_pc, "pc", pc); 637 if (oldregs.r_flags != regs.r_flags) 638 { 639 printf (" flags "); 640 print_flags (oldregs.r_flags); 641 printf (":"); 642 print_flags (regs.r_flags); 643 } 644 printf ("\033[0m\n"); 645 } 646 647 #define DRC(f, n, id) \ 648 printf(" %-3s %0*x", n, \ 649 reg_bytes[id]*2, (unsigned int)regs.f); \ 650 651 void 652 m32c_dump_all_registers (void) 653 { 654 printf ("\033[36mREGS:"); 655 DRC (r[0].r_r0, "r0", r0); 656 DRC (r[0].r_r1, "r1", r1); 657 DRC (r[0].r_r2, "r2", r2); 658 DRC (r[0].r_r3, "r3", r3); 659 DRC (r[0].r_a0, "a0", a0); 660 DRC (r[0].r_a1, "a1", a1); 661 DRC (r[0].r_sb, "sb", sb); 662 DRC (r[0].r_fb, "fb", fb); 663 printf ("\n "); 664 DRC (r[1].r_r0, "r0'", r0); 665 DRC (r[1].r_r1, "r1'", r1); 666 DRC (r[1].r_r2, "r2'", r2); 667 DRC (r[1].r_r3, "r3'", r3); 668 DRC (r[1].r_a0, "a0'", a0); 669 DRC (r[1].r_a1, "a1'", a1); 670 DRC (r[1].r_sb, "sb'", sb); 671 DRC (r[1].r_fb, "fb'", fb); 672 printf (" \n"); 673 DRC (r_intbh, "intbh", intbh); 674 DRC (r_intbl, "intbl", intbl); 675 DRC (r_usp, "usp", usp); 676 DRC (r_isp, "isp", isp); 677 DRC (r_pc, "pc", pc); 678 printf (" flags "); 679 print_flags (regs.r_flags); 680 printf ("\033[0m\n"); 681 /*sim_disasm_one (); */ 682 } 683