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