fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 802 lines 14 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/cpu/e68000/ea.c * 7 * Created: 2006-05-17 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2005-2018 Hampa Hug <hampa@hampa.ch> * 9 *****************************************************************************/ 10 11/***************************************************************************** 12 * This program is free software. You can redistribute it and / or modify it * 13 * under the terms of the GNU General Public License version 2 as published * 14 * by the Free Software Foundation. * 15 * * 16 * This program is distributed in the hope that it will be useful, but * 17 * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 * Public License for more details. * 20 *****************************************************************************/ 21 22 23#include <stdio.h> 24#include <stdlib.h> 25#include <string.h> 26 27#include "e68000.h" 28#include "internal.h" 29 30 31/* 32 * valid ea mask: 33 * 0 001: Dx 34 * 1 002: Ax 35 * 2 004: (Ax) 36 * 3 008: (Ax)+ 37 * 4 010: -(Ax) 38 * 5 020: XXXX(Ax) 39 * 6 040: XX(Ax, Rx.S) 40 * 7 080: XXXX 41 * 8 100: XXXXXXXX 42 * 9 200: XXXX(PC) 43 * 10 400: XX(PC, Rx.S) 44 * 11 800: #XXXX 45*/ 46 47 48static 49int e68_ea_full (e68000_t *c, unsigned ext, unsigned mask) 50{ 51 uint32_t ix, bd, od; 52 unsigned scale; 53 int bs, is; 54 55 /* base register is in c->ea_val */ 56 57 bs = (ext & 0x0080) != 0; 58 is = (ext & 0x0040) != 0; 59 60 if (bs) { 61 c->ea_val = 0; 62 } 63 64 scale = (ext >> 9) & 3; 65 66 if (is) { 67 ix = 0; 68 } 69 else { 70 if (ext & 0x8000) { 71 ix = e68_get_areg32 (c, (ext >> 12) & 7); 72 } 73 else { 74 ix = e68_get_dreg32 (c, (ext >> 12) & 7); 75 } 76 77 if ((ext & 0x0800) == 0) { 78 ix = e68_exts16 (ix); 79 } 80 } 81 82 bd = 0; 83 84 switch ((ext >> 4) & 3) { 85 case 0: 86 e68_exception_illegal (c); 87 return (1); 88 89 case 1: 90 bd = 0; 91 break; 92 93 case 2: 94 if (e68_prefetch (c)) { 95 return (1); 96 } 97 bd = e68_exts16 (c->ir[1]); 98 break; 99 100 case 3: 101 if (e68_prefetch (c)) { 102 return (1); 103 } 104 bd = c->ir[1]; 105 if (e68_prefetch (c)) { 106 return (1); 107 } 108 bd = (bd << 16) | c->ir[1]; 109 break; 110 } 111 112 if ((ext & 7) == 0) { 113 c->ea_val += (ix << scale) + bd; 114 return (0); 115 } 116 117 od = 0; 118 119 switch (ext & 3) { 120 case 0: 121 e68_exception_illegal (c); 122 return (1); 123 124 case 1: 125 od = 0; 126 break; 127 128 case 2: 129 if (e68_prefetch (c)) { 130 return (1); 131 } 132 od = e68_exts16 (c->ir[1]); 133 break; 134 135 case 3: 136 if (e68_prefetch (c)) { 137 return (1); 138 } 139 od = c->ir[1]; 140 if (e68_prefetch (c)) { 141 return (1); 142 } 143 od = (od << 16) | c->ir[1]; 144 break; 145 } 146 147 if (ext & 4) { 148 /* indirect postindexed */ 149 if (is) { 150 e68_exception_illegal (c); 151 return (1); 152 } 153 154 c->ea_val = e68_get_mem32 (c, c->ea_val + bd); 155 c->ea_val += (ix << scale) + od; 156 } 157 else { 158 /* indirect preindexed */ 159 c->ea_val = e68_get_mem32 (c, c->ea_val + bd + (ix << scale)); 160 c->ea_val += od; 161 } 162 163 return (0); 164} 165 166/* Dx */ 167static 168int e68_ea_000_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size) 169{ 170 if ((mask & 0x0001) == 0) { 171 e68_exception_illegal (c); 172 return (1); 173 } 174 175 c->ea_typ = E68_EA_TYPE_REG; 176 c->ea_val = ea & 7; 177 178 return (0); 179} 180 181/* Ax */ 182static 183int e68_ea_001_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size) 184{ 185 if ((mask & 0x0002) == 0) { 186 e68_exception_illegal (c); 187 return (1); 188 } 189 190 c->ea_typ = E68_EA_TYPE_REG; 191 c->ea_val = (ea & 7) + 8; 192 193 return (0); 194} 195 196/* (Ax) */ 197static 198int e68_ea_010_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size) 199{ 200 if ((mask & 0x0004) == 0) { 201 e68_exception_illegal (c); 202 return (1); 203 } 204 205 c->ea_typ = E68_EA_TYPE_MEM; 206 c->ea_val = e68_get_areg32 (c, ea & 7); 207 208 return (0); 209} 210 211/* (Ax)+ */ 212static 213int e68_ea_011_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size) 214{ 215 unsigned reg; 216 217 if ((mask & 0x0008) == 0) { 218 e68_exception_illegal (c); 219 return (1); 220 } 221 222 reg = ea & 7; 223 224 c->ea_typ = E68_EA_TYPE_MEM; 225 c->ea_val = e68_get_areg32 (c, reg); 226 227 e68_set_areg32 (c, reg, c->ea_val + (size >> 3)); 228 229 return (0); 230} 231 232/* (A7)+ */ 233static 234int e68_ea_011_111 (e68000_t *c, unsigned ea, unsigned mask, unsigned size) 235{ 236 if ((mask & 0x0008) == 0) { 237 e68_exception_illegal (c); 238 return (1); 239 } 240 241 if (size == 8) { 242 size = 16; 243 } 244 245 c->ea_typ = E68_EA_TYPE_MEM; 246 c->ea_val = e68_get_areg32 (c, 7); 247 248 e68_set_areg32 (c, 7, c->ea_val + (size >> 3)); 249 250 return (0); 251} 252 253/* -(Ax) */ 254static 255int e68_ea_100_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size) 256{ 257 unsigned reg; 258 259 if ((mask & 0x0010) == 0) { 260 e68_exception_illegal (c); 261 return (1); 262 } 263 264 reg = ea & 7; 265 266 c->ea_typ = E68_EA_TYPE_MEM; 267 c->ea_val = e68_get_areg32 (c, reg) - (size >> 3); 268 269 e68_set_areg32 (c, reg, c->ea_val); 270 e68_set_clk (c, 2); 271 272 return (0); 273} 274 275/* -(A7) */ 276static 277int e68_ea_100_111 (e68000_t *c, unsigned ea, unsigned mask, unsigned size) 278{ 279 if ((mask & 0x0010) == 0) { 280 e68_exception_illegal (c); 281 return (1); 282 } 283 284 if (size == 8) { 285 size = 16; 286 } 287 288 c->ea_typ = E68_EA_TYPE_MEM; 289 c->ea_val = e68_get_areg32 (c, 7) - (size >> 3); 290 291 e68_set_areg32 (c, 7, c->ea_val); 292 e68_set_clk (c, 2); 293 294 return (0); 295} 296 297/* XXXX(Ax) */ 298static 299int e68_ea_101_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size) 300{ 301 if ((mask & 0x0020) == 0) { 302 e68_exception_illegal (c); 303 return (1); 304 } 305 306 if (e68_prefetch (c)) { 307 return (1); 308 } 309 310 c->ea_typ = E68_EA_TYPE_MEM; 311 c->ea_val = e68_get_areg32 (c, ea & 7) + e68_exts16 (c->ir[1]); 312 313 e68_set_clk (c, 4); 314 315 return (0); 316} 317 318/* XX(Ax, Rx.S) */ 319static 320int e68_ea_110_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size) 321{ 322 uint32_t idx; 323 unsigned scale; 324 325 if ((mask & 0x0040) == 0) { 326 e68_exception_illegal (c); 327 return (1); 328 } 329 330 if (e68_prefetch (c)) { 331 return (1); 332 } 333 334 c->ea_typ = E68_EA_TYPE_MEM; 335 c->ea_val = e68_get_areg32 (c, ea & 7); 336 337 if (c->flags & E68_FLAG_68020) { 338 if (c->ir[1] & 0x0100) { 339 return (e68_ea_full (c, c->ir[1], mask)); 340 } 341 else { 342 scale = (c->ir[1] >> 9) & 3; 343 } 344 } 345 else { 346 scale = 0; 347 } 348 349 c->ea_val += e68_exts8 (c->ir[1]); 350 351 if (c->ir[1] & 0x8000) { 352 idx = e68_get_areg32 (c, (c->ir[1] >> 12) & 7); 353 } 354 else { 355 idx = e68_get_dreg32 (c, (c->ir[1] >> 12) & 7); 356 } 357 358 if ((c->ir[1] & 0x0800) == 0) { 359 idx = e68_exts16 (idx); 360 } 361 362 c->ea_val += idx << scale; 363 364 e68_set_clk (c, 6); 365 366 return (0); 367} 368 369/* XXXX */ 370static 371int e68_ea_111_000 (e68000_t *c, unsigned ea, unsigned mask, unsigned size) 372{ 373 if ((mask & 0x0080) == 0) { 374 e68_exception_illegal (c); 375 return (1); 376 } 377 378 if (e68_prefetch (c)) { 379 return (1); 380 } 381 382 c->ea_typ = E68_EA_TYPE_MEM; 383 c->ea_val = e68_exts16 (c->ir[1]); 384 385 e68_set_clk (c, 4); 386 387 return (0); 388} 389 390/* XXXXXXXX */ 391static 392int e68_ea_111_001 (e68000_t *c, unsigned ea, unsigned mask, unsigned size) 393{ 394 if ((mask & 0x0100) == 0) { 395 e68_exception_illegal (c); 396 return (1); 397 } 398 399 if (e68_prefetch (c)) { 400 return (1); 401 } 402 403 c->ea_typ = E68_EA_TYPE_MEM; 404 c->ea_val = c->ir[1]; 405 406 if (e68_prefetch (c)) { 407 return (1); 408 } 409 410 c->ea_val = (c->ea_val << 16) | c->ir[1]; 411 412 e68_set_clk (c, 8); 413 414 return (0); 415} 416 417/* XXXX(PC) */ 418static 419int e68_ea_111_010 (e68000_t *c, unsigned ea, unsigned mask, unsigned size) 420{ 421 if ((mask & 0x0200) == 0) { 422 e68_exception_illegal (c); 423 return (1); 424 } 425 426 c->ea_typ = E68_EA_TYPE_MEM; 427 c->ea_val = e68_get_ir_pc (c) - 2; 428 429 if (e68_prefetch (c)) { 430 return (1); 431 } 432 433 c->ea_val += e68_exts16 (c->ir[1]); 434 435 e68_set_clk (c, 4); 436 437 return (0); 438} 439 440/* XX(PC, Rx.S) */ 441static 442int e68_ea_111_011 (e68000_t *c, unsigned ea, unsigned mask, unsigned size) 443{ 444 uint32_t idx; 445 unsigned scale; 446 447 if ((mask & 0x0400) == 0) { 448 e68_exception_illegal (c); 449 return (1); 450 } 451 452 c->ea_typ = E68_EA_TYPE_MEM; 453 c->ea_val = e68_get_ir_pc (c) - 2; 454 455 if (e68_prefetch (c)) { 456 return (1); 457 } 458 459 if (c->flags & E68_FLAG_68020) { 460 if (c->ir[1] & 0x0100) { 461 return (e68_ea_full (c, c->ir[1], mask)); 462 } 463 else { 464 scale = (c->ir[1] >> 9) & 3; 465 } 466 } 467 else { 468 scale = 0; 469 } 470 471 c->ea_val += e68_exts8 (c->ir[1]); 472 473 if (c->ir[1] & 0x8000) { 474 idx = e68_get_areg32 (c, (c->ir[1] >> 12) & 7); 475 } 476 else { 477 idx = e68_get_dreg32 (c, (c->ir[1] >> 12) & 7); 478 } 479 480 if ((c->ir[1] & 0x0800) == 0) { 481 idx = e68_exts16 (idx); 482 } 483 484 c->ea_val += idx << scale; 485 486 e68_set_clk (c, 6); 487 488 return (0); 489} 490 491/* #XXXX */ 492static 493int e68_ea_111_100 (e68000_t *c, unsigned ea, unsigned mask, unsigned size) 494{ 495 if ((mask & 0x0800) == 0) { 496 e68_exception_illegal (c); 497 return (1); 498 } 499 500 if (e68_prefetch (c)) { 501 return (1); 502 } 503 504 c->ea_typ = E68_EA_TYPE_IMM; 505 c->ea_val = c->ir[1]; 506 507 if (size == 32) { 508 if (e68_prefetch (c)) { 509 return (1); 510 } 511 c->ea_val = (c->ea_val << 16) | c->ir[1]; 512 e68_set_clk (c, 8); 513 } 514 else if (size == 16) { 515 e68_set_clk (c, 4); 516 } 517 else { 518 c->ea_val &= 0xff; 519 e68_set_clk (c, 4); 520 } 521 522 return (0); 523} 524 525static 526int e68_ea_111_xxx (e68000_t *c, unsigned ea, unsigned mask, unsigned size) 527{ 528 e68_exception_illegal (c); 529 530 return (1); 531} 532 533e68_get_ea_ptr_f e68_ea_tab[64] = { 534 e68_ea_000_xxx, e68_ea_000_xxx, e68_ea_000_xxx, e68_ea_000_xxx, 535 e68_ea_000_xxx, e68_ea_000_xxx, e68_ea_000_xxx, e68_ea_000_xxx, 536 537 e68_ea_001_xxx, e68_ea_001_xxx, e68_ea_001_xxx, e68_ea_001_xxx, 538 e68_ea_001_xxx, e68_ea_001_xxx, e68_ea_001_xxx, e68_ea_001_xxx, 539 540 e68_ea_010_xxx, e68_ea_010_xxx, e68_ea_010_xxx, e68_ea_010_xxx, 541 e68_ea_010_xxx, e68_ea_010_xxx, e68_ea_010_xxx, e68_ea_010_xxx, 542 543 e68_ea_011_xxx, e68_ea_011_xxx, e68_ea_011_xxx, e68_ea_011_xxx, 544 e68_ea_011_xxx, e68_ea_011_xxx, e68_ea_011_xxx, e68_ea_011_111, 545 546 e68_ea_100_xxx, e68_ea_100_xxx, e68_ea_100_xxx, e68_ea_100_xxx, 547 e68_ea_100_xxx, e68_ea_100_xxx, e68_ea_100_xxx, e68_ea_100_111, 548 549 e68_ea_101_xxx, e68_ea_101_xxx, e68_ea_101_xxx, e68_ea_101_xxx, 550 e68_ea_101_xxx, e68_ea_101_xxx, e68_ea_101_xxx, e68_ea_101_xxx, 551 552 e68_ea_110_xxx, e68_ea_110_xxx, e68_ea_110_xxx, e68_ea_110_xxx, 553 e68_ea_110_xxx, e68_ea_110_xxx, e68_ea_110_xxx, e68_ea_110_xxx, 554 555 e68_ea_111_000, e68_ea_111_001, e68_ea_111_010, e68_ea_111_011, 556 e68_ea_111_100, e68_ea_111_xxx, e68_ea_111_xxx, e68_ea_111_xxx, 557}; 558 559 560int e68_ea_get_val8 (e68000_t *c, uint8_t *val) 561{ 562 switch (c->ea_typ) { 563 case E68_EA_TYPE_IMM: 564 *val = c->ea_val & 0xff; 565 return (0); 566 567 case E68_EA_TYPE_REG: 568 if (c->ea_val < 8) { 569 *val = e68_get_dreg8 (c, c->ea_val); 570 } 571 else { 572 e68_exception_illegal (c); 573 return (1); 574 } 575 return (0); 576 577 case E68_EA_TYPE_MEM: 578 *val = e68_get_mem8 (c, c->ea_val); 579 e68_set_clk (c, 4); 580 581 if (c->bus_error) { 582 e68_exception_bus (c, c->ea_val, 1, 0); 583 return (1); 584 } 585 586 return (0); 587 } 588 589 e68_exception_illegal (c); 590 591 return (1); 592} 593 594int e68_ea_get_val16 (e68000_t *c, uint16_t *val) 595{ 596 switch (c->ea_typ) { 597 case E68_EA_TYPE_IMM: 598 *val = c->ea_val & 0xffff; 599 return (0); 600 601 case E68_EA_TYPE_REG: 602 if (c->ea_val < 8) { 603 *val = e68_get_dreg16 (c, c->ea_val); 604 } 605 else if (c->ea_val < 16) { 606 *val = e68_get_areg16 (c, c->ea_val - 8); 607 } 608 else { 609 e68_exception_illegal (c); 610 return (1); 611 } 612 return (0); 613 614 case E68_EA_TYPE_MEM: 615 if (c->ea_val & 1) { 616 if ((c->flags & E68_FLAG_NOADDR) == 0) { 617 e68_exception_address (c, c->ea_val, 1, 0); 618 return (1); 619 } 620 } 621 622 *val = e68_get_mem16 (c, c->ea_val); 623 e68_set_clk (c, 4); 624 625 if (c->bus_error) { 626 e68_exception_bus (c, c->ea_val, 1, 0); 627 return (1); 628 } 629 630 return (0); 631 } 632 633 e68_exception_illegal (c); 634 635 return (1); 636} 637 638int e68_ea_get_val32 (e68000_t *c, uint32_t *val) 639{ 640 switch (c->ea_typ) { 641 case E68_EA_TYPE_IMM: 642 *val = c->ea_val & 0xffffffff; 643 return (0); 644 645 case E68_EA_TYPE_REG: 646 if (c->ea_val < 8) { 647 *val = e68_get_dreg32 (c, c->ea_val); 648 } 649 else if (c->ea_val < 16) { 650 *val = e68_get_areg32 (c, c->ea_val - 8); 651 } 652 else { 653 e68_exception_illegal (c); 654 return (1); 655 } 656 return (0); 657 658 case E68_EA_TYPE_MEM: 659 if (c->ea_val & 1) { 660 if ((c->flags & E68_FLAG_NOADDR) == 0) { 661 e68_exception_address (c, c->ea_val, 1, 0); 662 return (1); 663 } 664 } 665 666 *val = e68_get_mem32 (c, c->ea_val); 667 e68_set_clk (c, 8); 668 669 if (c->bus_error) { 670 e68_exception_bus (c, c->ea_val, 1, 0); 671 return (1); 672 } 673 674 return (0); 675 } 676 677 e68_exception_illegal (c); 678 679 return (1); 680} 681 682int e68_ea_set_val8 (e68000_t *c, uint8_t val) 683{ 684 switch (c->ea_typ) { 685 case E68_EA_TYPE_IMM: 686 e68_exception_illegal (c); 687 return (1); 688 689 case E68_EA_TYPE_REG: 690 if (c->ea_val < 8) { 691 e68_set_dreg8 (c, c->ea_val, val); 692 } 693 else { 694 e68_exception_illegal (c); 695 return (1); 696 } 697 return (0); 698 699 case E68_EA_TYPE_MEM: 700 e68_set_mem8 (c, c->ea_val, val); 701 e68_set_clk (c, 4); 702 703 if (c->bus_error) { 704 e68_exception_bus (c, c->ea_val, 1, 1); 705 return (1); 706 } 707 708 return (0); 709 } 710 711 e68_exception_illegal (c); 712 713 return (1); 714} 715 716int e68_ea_set_val16 (e68000_t *c, uint16_t val) 717{ 718 switch (c->ea_typ) { 719 case E68_EA_TYPE_IMM: 720 e68_exception_illegal (c); 721 return (1); 722 723 case E68_EA_TYPE_REG: 724 if (c->ea_val < 8) { 725 e68_set_dreg16 (c, c->ea_val, val); 726 } 727 else if (c->ea_val < 16) { 728 e68_set_areg16 (c, c->ea_val - 8, val); 729 } 730 else { 731 e68_exception_illegal (c); 732 return (1); 733 } 734 return (0); 735 736 case E68_EA_TYPE_MEM: 737 if (c->ea_val & 1) { 738 if ((c->flags & E68_FLAG_NOADDR) == 0) { 739 e68_exception_address (c, c->ea_val, 1, 1); 740 return (1); 741 } 742 } 743 744 e68_set_mem16 (c, c->ea_val, val); 745 e68_set_clk (c, 4); 746 747 if (c->bus_error) { 748 e68_exception_bus (c, c->ea_val, 1, 1); 749 return (1); 750 } 751 752 return (0); 753 } 754 755 e68_exception_illegal (c); 756 757 return (1); 758} 759 760int e68_ea_set_val32 (e68000_t *c, uint32_t val) 761{ 762 switch (c->ea_typ) { 763 case E68_EA_TYPE_IMM: 764 e68_exception_illegal (c); 765 return (1); 766 767 case E68_EA_TYPE_REG: 768 if (c->ea_val < 8) { 769 e68_set_dreg32 (c, c->ea_val, val); 770 } 771 else if (c->ea_val < 16) { 772 e68_set_areg32 (c, c->ea_val - 8, val); 773 } 774 else { 775 e68_exception_illegal (c); 776 return (1); 777 } 778 return (0); 779 780 case E68_EA_TYPE_MEM: 781 if (c->ea_val & 1) { 782 if ((c->flags & E68_FLAG_NOADDR) == 0) { 783 e68_exception_address (c, c->ea_val, 1, 1); 784 return (1); 785 } 786 } 787 788 e68_set_mem32 (c, c->ea_val, val); 789 e68_set_clk (c, 8); 790 791 if (c->bus_error) { 792 e68_exception_bus (c, c->ea_val, 1, 1); 793 return (1); 794 } 795 796 return (0); 797 } 798 799 e68_exception_illegal (c); 800 801 return (1); 802}