this repo has no description
at main 1218 lines 26 kB view raw
1/* 2 FPCPEMDV.h 3 4 Copyright (C) 2007 Ross Martin, Paul C. Pratt 5 6 You can redistribute this file and/or modify it under the terms 7 of version 2 of the GNU General Public License as published by 8 the Free Software Foundation. You should have received a copy 9 of the license along with this file; see the file COPYING. 10 11 This file is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 license for more details. 15*/ 16 17/* 18 Floating Point CoProcessor Emulated Device 19 (included by MINEM68K.c) 20*/ 21 22/* 23 ReportAbnormalID unused 0x0306 - 0x03FF 24*/ 25 26 27LOCALVAR struct fpustruct 28{ 29 myfpr fp[8]; 30 CPTR FPIAR; /* Floating point instruction address register */ 31} fpu_dat; 32 33LOCALPROC myfp_SetFPIAR(ui5r v) 34{ 35 fpu_dat.FPIAR = v; 36} 37 38LOCALFUNC ui5r myfp_GetFPIAR(void) 39{ 40 return fpu_dat.FPIAR; 41} 42 43LOCALFUNC blnr DecodeAddrModeRegister(ui5b sz) 44{ 45 ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat; 46 ui4r themode = (Dat >> 3) & 7; 47 ui4r thereg = Dat & 7; 48 49 switch (themode) { 50 case 2 : 51 case 3 : 52 case 4 : 53 case 5 : 54 case 6 : 55 return DecodeModeRegister(sz); 56 break; 57 case 7 : 58 switch (thereg) { 59 case 0 : 60 case 1 : 61 case 2 : 62 case 3 : 63 case 4 : 64 return DecodeModeRegister(sz); 65 break; 66 default : 67 return falseblnr; 68 break; 69 } 70 break; 71 default : 72 return falseblnr; 73 break; 74 } 75} 76 77LOCALPROC read_long_double(ui5r addr, myfpr *r) 78{ 79 ui4r v2; 80 ui5r v1; 81 ui5r v0; 82 83 v2 = get_word(addr + 0); 84 /* ignore word at offset 2 */ 85 v1 = get_long(addr + 4); 86 v0 = get_long(addr + 8); 87 88 myfp_FromExtendedFormat(r, v2, v1, v0); 89} 90 91LOCALPROC write_long_double(ui5r addr, myfpr *xx) 92{ 93 ui4r v2; 94 ui5r v1; 95 ui5r v0; 96 97 myfp_ToExtendedFormat(xx, &v2, &v1, &v0); 98 99 put_word(addr + 0, v2); 100 put_word(addr + 2, 0); 101 put_long(addr + 4, v1); 102 put_long(addr + 8, v0); 103} 104 105LOCALPROC read_double(ui5r addr, myfpr *r) 106{ 107 ui5r v1; 108 ui5r v0; 109 110 v1 = get_long(addr + 0); 111 v0 = get_long(addr + 4); 112 113 myfp_FromDoubleFormat(r, v1, v0); 114} 115 116LOCALPROC write_double(ui5r addr, myfpr *dd) 117{ 118 ui5r v1; 119 ui5r v0; 120 121 myfp_ToDoubleFormat(dd, &v1, &v0); 122 123 put_long(addr + 0, v1); 124 put_long(addr + 4, v0); 125} 126 127#if 0 128LOCALPROC read_single(ui5r addr, myfpr *r) 129{ 130 myfp_FromSingleFormat(r, get_long(addr)); 131} 132 133LOCALPROC write_single(ui5r addr, myfpr *ff) 134{ 135 put_long(addr, myfp_ToSingleFormat(ff)); 136} 137#endif 138 139 140LOCALFUNC int CheckFPCondition(ui4b predicate) 141{ 142 int condition_true = 0; 143 144 ui3r cc = myfp_GetConditionCodeByte(); 145 146 int c_nan = (cc) & 1; 147 /* int c_inf = (cc >> 1) & 1; */ 148 int c_zero = (cc >> 2) & 1; 149 int c_neg = (cc >> 3) & 1; 150 151 /* 152 printf( 153 "FPSR Checked: c_nan=%d, c_zero=%d, c_neg=%d," 154 " predicate=0x%04x\n", 155 c_nan, c_zero, c_neg, predicate); 156 */ 157 158 switch (predicate) { 159 case 0x11: /* SEQ */ 160 case 0x01: /* EQ */ 161 condition_true = c_zero; 162 break; 163 case 0x1E: /* SNE */ 164 case 0x0E: /* NE */ 165 condition_true = ! c_zero; 166 break; 167 case 0x02: /* OGT */ 168 case 0x12: /* GT */ 169 condition_true = (! c_neg) && (! c_zero) && (! c_nan); 170 break; 171 case 0x0D: /* ULE */ 172 case 0x1D: /* NGT */ 173 condition_true = c_neg || c_zero || c_nan; 174 break; 175 case 0x03: /* OGE */ 176 case 0x13: /* GE */ 177 condition_true = c_zero || ((! c_neg) && (! c_nan)); 178 break; 179 case 0x0C: /* ULT */ 180 case 0x1C: /* NGE */ 181 condition_true = c_nan || ((! c_zero) && c_neg) ; 182 break; 183 case 0x04: /* OLT */ 184 case 0x14: /* LT */ 185 condition_true = c_neg && (! c_nan) && (! c_zero); 186 break; 187 case 0x0B: /* UGE */ 188 case 0x1B: /* NLT */ 189 condition_true = c_nan || c_zero || (! c_neg); 190 break; 191 case 0x05: /* OLE */ 192 case 0x15: /* LE */ 193 condition_true = ((! c_nan) && c_neg) || c_zero; 194 break; 195 case 0x0A: /* UGT */ 196 case 0x1A: /* NLE */ 197 condition_true = c_nan || ((! c_neg) && (! c_zero)); 198 break; 199 case 0x06: /* OGL */ 200 case 0x16: /* GL */ 201 condition_true = (! c_nan) && (! c_zero); 202 break; 203 case 0x09: /* UEQ */ 204 case 0x19: /* NGL */ 205 condition_true = c_nan || c_zero; 206 break; 207 case 0x07: /* OR */ 208 case 0x17: /* GLE */ 209 condition_true = ! c_nan; 210 break; 211 case 0x08: /* NGLE */ 212 case 0x18: /* NGLE */ 213 condition_true = c_nan; 214 break; 215 case 0x00: /* SFALSE */ 216 case 0x10: /* FALSE */ 217 condition_true = 0; 218 break; 219 case 0x0F: /* STRUE */ 220 case 0x1F: /* TRUE */ 221 condition_true = 1; 222 break; 223 } 224 225 /* printf("condition_true=%d\n", condition_true); */ 226 227 return condition_true; 228} 229 230LOCALIPROC DoCodeFPU_dflt(void) 231{ 232 ReportAbnormalID(0x0301, 233 "unimplemented Floating Point Instruction"); 234#if dbglog_HAVE 235 { 236 ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8) 237 | V_regs.CurDecOpY.v[0].ArgDat; 238 239 dbglog_writelnNum("opcode", opcode); 240 } 241#endif 242 DoCodeFdefault(); 243} 244 245LOCALIPROC DoCodeFPU_Save(void) 246{ 247 ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8) 248 | V_regs.CurDecOpY.v[0].ArgDat; 249 if ((opcode == 0xF327) || (opcode == 0xF32D)) { 250#if 0 251 DecodeModeRegister(4); 252 SetArgValueL(0); /* for now, try null state frame */ 253#endif 254 /* 28 byte 68881 IDLE frame */ 255 256 if (! DecodeAddrModeRegister(28)) { 257 DoCodeFPU_dflt(); 258#if dbglog_HAVE 259 dbglog_writeln( 260 "DecodeAddrModeRegister fails in DoCodeFPU_Save"); 261#endif 262 } else { 263 put_long(V_regs.ArgAddr.mem, 0x1f180000); 264 put_long(V_regs.ArgAddr.mem + 4, 0); 265 put_long(V_regs.ArgAddr.mem + 8, 0); 266 put_long(V_regs.ArgAddr.mem + 12, 0); 267 put_long(V_regs.ArgAddr.mem + 16, 0); 268 put_long(V_regs.ArgAddr.mem + 20, 0); 269 put_long(V_regs.ArgAddr.mem + 24, 0x70000000); 270 } 271 272 } else { 273 DoCodeFPU_dflt(); 274#if dbglog_HAVE 275 dbglog_writeln("unimplemented FPU Save"); 276#endif 277 } 278} 279 280LOCALIPROC DoCodeFPU_Restore(void) 281{ 282 ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8) 283 | V_regs.CurDecOpY.v[0].ArgDat; 284 ui4r themode = (opcode >> 3) & 7; 285 ui4r thereg = opcode & 7; 286 if ((opcode == 0xF35F) || (opcode == 0xF36D)) { 287 ui5r dstvalue; 288 289 if (! DecodeAddrModeRegister(4)) { 290 DoCodeFPU_dflt(); 291#if dbglog_HAVE 292 dbglog_writeln( 293 "DecodeAddrModeRegister fails in DoCodeFPU_Restore"); 294#endif 295 } else { 296 dstvalue = get_long(V_regs.ArgAddr.mem); 297 if (dstvalue != 0) { 298 if (0x1f180000 == dstvalue) { 299 if (3 == themode) { 300 m68k_areg(thereg) = V_regs.ArgAddr.mem + 28; 301 } 302 } else { 303 DoCodeFPU_dflt(); 304#if dbglog_HAVE 305 dbglog_writeln("unknown restore"); 306 /* not a null state we saved */ 307#endif 308 } 309 } 310 } 311 } else { 312 DoCodeFPU_dflt(); 313#if dbglog_HAVE 314 dbglog_writeln("unimplemented FPU Restore"); 315#endif 316 } 317} 318 319LOCALIPROC DoCodeFPU_FBccW(void) 320{ 321 /* 322 Also get here for a NOP instruction (opcode 0xF280), 323 which is simply a FBF.w with offset 0 324 */ 325 ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat; 326 327 if (CheckFPCondition(Dat & 0x3F)) { 328 DoCodeBraW(); 329 } else { 330 SkipiWord(); 331 } 332 333 /* printf("pc_p set to 0x%p in FBcc (32bit)\n", V_pc_p); */ 334} 335 336LOCALIPROC DoCodeFPU_FBccL(void) 337{ 338 ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat; 339 340 if (CheckFPCondition(Dat & 0x3F)) { 341 DoCodeBraL(); 342 } else { 343 SkipiLong(); 344 } 345} 346 347LOCALIPROC DoCodeFPU_DBcc(void) 348{ 349 ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat; 350 ui4r thereg = Dat & 7; 351 ui4b word2 = (int)nextiword(); 352 353 ui4b predicate = word2 & 0x3F; 354 355 int condition_true = CheckFPCondition(predicate); 356 357 if (! condition_true) { 358 ui5b fdb_count = ui5r_FromSWord(m68k_dreg(thereg)) - 1; 359 360 m68k_dreg(thereg) = 361 (m68k_dreg(thereg) & ~ 0xFFFF) | (fdb_count & 0xFFFF); 362 if ((si5b)fdb_count == -1) { 363 SkipiWord(); 364 } else { 365 DoCodeBraW(); 366 } 367 } else { 368 SkipiWord(); 369 } 370} 371 372LOCALIPROC DoCodeFPU_Trapcc(void) 373{ 374 ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat; 375 ui4r thereg = Dat & 7; 376 377 ui4b word2 = (int)nextiword(); 378 379 ui4b predicate = word2 & 0x3F; 380 381 int condition_true = CheckFPCondition(predicate); 382 383 if (thereg == 2) { 384 (void) nextiword(); 385 } else if (thereg == 3) { 386 (void) nextilong(); 387 } else if (thereg == 4) { 388 } else { 389 ReportAbnormalID(0x0302, "Invalid FTRAPcc (?"); 390 } 391 392 if (condition_true) { 393 ReportAbnormalID(0x0303, "FTRAPcc trapping"); 394 Exception(7); 395 } 396} 397 398LOCALIPROC DoCodeFPU_Scc(void) 399{ 400 ui4b word2 = (int)nextiword(); 401 402 if (! DecodeModeRegister(1)) { 403 DoCodeFPU_dflt(); 404#if dbglog_HAVE 405 dbglog_writeln("bad mode/reg in DoCodeFPU_Scc"); 406#endif 407 } else { 408 if (CheckFPCondition(word2 & 0x3F)) { 409 SetArgValueB(0xFFFF); 410 } else { 411 SetArgValueB(0x0000); 412 } 413 } 414} 415 416LOCALPROC DoCodeF_InvalidPlusWord(void) 417{ 418 BackupPC(); 419 DoCodeFPU_dflt(); 420} 421 422LOCALFUNC int CountCSIAlist(ui4b word2) 423{ 424 ui4b regselect = (word2 >> 10) & 0x7; 425 int num = 0; 426 427 if (regselect & 1) { 428 num++; 429 } 430 if (regselect & 2) { 431 num++; 432 } 433 if (regselect & 4) { 434 num++; 435 } 436 437 return num; 438} 439 440LOCALPROC DoCodeFPU_Move_EA_CSIA(ui4b word2) 441{ 442 int n; 443 ui5b ea_value[3]; 444 ui4b regselect = (word2 >> 10) & 0x7; 445 int num = CountCSIAlist(word2); 446 447 if (regselect == 0) { 448 DoCodeF_InvalidPlusWord(); 449#if dbglog_HAVE 450 dbglog_writeln("Invalid FMOVE instruction"); 451#endif 452 return; 453 } 454 455 /* FMOVEM.L <EA>, <FP CR,SR,IAR list> */ 456 457 if (! DecodeModeRegister(4 * num)) { 458 DoCodeF_InvalidPlusWord(); 459#if dbglog_HAVE 460 dbglog_writeln("bad mode/reg in DoCodeFPU_Move_EA_CSIA"); 461#endif 462 } else { 463 ea_value[0] = GetArgValueL(); 464 if (num > 1) { 465 ea_value[1] = get_long(V_regs.ArgAddr.mem + 4); 466 } 467 if (num > 2) { 468 ea_value[2] = get_long(V_regs.ArgAddr.mem + 8); 469 } 470 471 n = 0; 472 if (regselect & (1 << 2)) { 473 myfp_SetFPCR(ea_value[n++]); 474 } 475 if (regselect & (1 << 1)) { 476 myfp_SetFPSR(ea_value[n++]); 477 } 478 if (regselect & (1 << 0)) { 479 myfp_SetFPIAR(ea_value[n++]); 480 } 481 } 482} 483 484LOCALPROC DoCodeFPU_MoveM_CSIA_EA(ui4b word2) 485{ 486 int n; 487 ui5b ea_value[3]; 488 int num = CountCSIAlist(word2); 489 490 ui4b regselect = (word2 >> 10) & 0x7; 491 492 /* FMOVEM.L <FP CR,SR,IAR list>, <EA> */ 493 494 if (0 == regselect) { 495 DoCodeF_InvalidPlusWord(); 496#if dbglog_HAVE 497 dbglog_writeln("Invalid FMOVE instruction"); 498#endif 499 } else 500 if (! DecodeModeRegister(4 * num)) { 501 DoCodeF_InvalidPlusWord(); 502#if dbglog_HAVE 503 dbglog_writeln("bad mode/reg in DoCodeFPU_MoveM_CSIA_EA"); 504#endif 505 } else 506 { 507 n = 0; 508 if (regselect & (1 << 2)) { 509 ea_value[n++] = myfp_GetFPCR(); 510 } 511 if (regselect & (1 << 1)) { 512 ea_value[n++] = myfp_GetFPSR(); 513 } 514 if (regselect & (1 << 0)) { 515 ea_value[n++] = myfp_GetFPIAR(); 516 } 517 518 SetArgValueL(ea_value[0]); 519 if (num > 1) { 520 put_long(V_regs.ArgAddr.mem + 4, ea_value[1]); 521 } 522 if (num > 2) { 523 put_long(V_regs.ArgAddr.mem + 8, ea_value[2]); 524 } 525 } 526} 527 528LOCALPROC DoCodeFPU_MoveM_EA_list(ui4b word2) 529{ 530 int i; 531 ui5r myaddr; 532 ui5r count; 533 ui4b register_list = word2; 534 535 ui4b fmove_mode = (word2 >> 11) & 0x3; 536 537 /* FMOVEM.X <ea>, <list> */ 538 539 if ((fmove_mode == 0) || (fmove_mode == 1)) { 540 DoCodeF_InvalidPlusWord(); 541#if dbglog_HAVE 542 dbglog_writeln("Invalid FMOVEM.X instruction"); 543#endif 544 return; 545 } 546 547 if (fmove_mode == 3) { 548 /* Dynamic mode */ 549 register_list = V_regs.regs[(word2 >> 4) & 7]; 550 } 551 552 count = 0; 553 for (i = 0; i <= 7; i++) { 554 int j = 1 << (7 - i); 555 if (j & register_list) { 556 ++count; 557 } 558 } 559 560 if (! DecodeModeRegister(12 * count)) { 561 DoCodeF_InvalidPlusWord(); 562#if dbglog_HAVE 563 dbglog_writeln( 564 "DecodeModeRegister fails DoCodeFPU_MoveM_EA_list"); 565#endif 566 } else { 567 /* Postincrement mode or Control mode */ 568 569 myaddr = V_regs.ArgAddr.mem; 570 571 for (i = 0; i <= 7; i++) { 572 int j = 1 << (7 - i); 573 if (j & register_list) { 574 read_long_double(myaddr, &fpu_dat.fp[i]); 575 myaddr += 12; 576 } 577 } 578 } 579} 580 581LOCALPROC DoCodeFPU_MoveM_list_EA(ui4b word2) 582{ 583 /* FMOVEM.X <list>, <ea> */ 584 585 int i; 586 ui5r myaddr; 587 ui5r count; 588 ui4b register_list = word2; 589 ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat; 590 ui4r themode = (Dat >> 3) & 7; 591 592 ui4b fmove_mode = (word2 >> 11) & 0x3; 593 594 if ((fmove_mode == 1) || (fmove_mode == 3)) { 595 /* Dynamic mode */ 596 register_list = V_regs.regs[(word2 >> 4) & 7]; 597 } 598 599 count = 0; 600 for (i = 7; i >= 0; i--) { 601 int j = 1 << i; 602 if (j & register_list) { 603 ++count; 604 } 605 } 606 607 if (! DecodeModeRegister(12 * count)) { 608 DoCodeF_InvalidPlusWord(); 609#if dbglog_HAVE 610 dbglog_writeln( 611 "DecodeModeRegister fails DoCodeFPU_MoveM_list_EA"); 612#endif 613 } else { 614 if (themode == 4) { 615 /* Predecrement mode */ 616 617 myaddr = V_regs.ArgAddr.mem + 12 * count; 618 619 for (i = 7; i >= 0; i--) { 620 int j = 1 << i; 621 if (j & register_list) { 622 myaddr -= 12; 623 write_long_double(myaddr, &fpu_dat.fp[i]); 624 } 625 } 626 } else { 627 /* Control mode */ 628 629 myaddr = V_regs.ArgAddr.mem; 630 631 for (i = 0; i <= 7; i++) { 632 int j = 1 << (7 - i); 633 if (j & register_list) { 634 write_long_double(myaddr, &fpu_dat.fp[i]); 635 myaddr += 12; 636 } 637 } 638 } 639 } 640} 641 642LOCALPROC DoCodeFPU_MoveCR(ui4b word2) 643{ 644 /* FMOVECR */ 645 ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8) 646 | V_regs.CurDecOpY.v[0].ArgDat; 647 648 if (opcode != 0xF200) { 649 DoCodeF_InvalidPlusWord(); 650#if dbglog_HAVE 651 dbglog_writeln("bad opcode in FMOVECR"); 652#endif 653 } else { 654 ui4b RomOffset = word2 & 0x7F; 655 ui4b DestReg = (word2 >> 7) & 0x7; 656 657 if (! myfp_getCR(&fpu_dat.fp[DestReg], RomOffset)) { 658 DoCodeF_InvalidPlusWord(); 659#if dbglog_HAVE 660 dbglog_writeln("Invalid constant number in FMOVECR"); 661#endif 662 } 663 } 664} 665 666LOCALPROC SaveResultAndFPSR(myfpr *DestReg, myfpr *result) 667{ 668 *DestReg = *result; 669 myfp_SetConditionCodeByteFromResult(result); 670} 671 672LOCALPROC DoCodeFPU_GenOp(ui4b word2, myfpr *source) 673{ 674 myfpr result; 675 myfpr t0; 676 myfpr *DestReg = &fpu_dat.fp[(word2 >> 7) & 0x7]; 677 678 switch (word2 & 0x7F) { 679 680 case 0x00: /* FMOVE */ 681 SaveResultAndFPSR(DestReg, source); 682 break; 683 684 case 0x01: /* FINT */ 685 myfp_Int(&result, source); 686 SaveResultAndFPSR(DestReg, &result); 687 break; 688 689 case 0x02: /* FSINH */ 690 myfp_Sinh(&result, source); 691 SaveResultAndFPSR(DestReg, &result); 692 break; 693 694 case 0x03: /* FINTRZ */ 695 myfp_IntRZ(&result, source); 696 SaveResultAndFPSR(DestReg, &result); 697 break; 698 699 case 0x04: /* FSQRT */ 700 myfp_Sqrt(&result, source); 701 SaveResultAndFPSR(DestReg, &result); 702 break; 703 704 case 0x06: /* FLOGNP1 */ 705 myfp_LogNP1(&result, source); 706 SaveResultAndFPSR(DestReg, &result); 707 break; 708 709 case 0x08: /* FETOXM1 */ 710 myfp_EToXM1(&result, source); 711 SaveResultAndFPSR(DestReg, &result); 712 break; 713 714 case 0x09: /* FTANH */ 715 myfp_Tanh(&result, source); 716 SaveResultAndFPSR(DestReg, &result); 717 break; 718 719 case 0x0A: /* FATAN */ 720 myfp_ATan(&result, source); 721 SaveResultAndFPSR(DestReg, &result); 722 break; 723 724 case 0x0C: /* FASIN */ 725 myfp_ASin(&result, source); 726 SaveResultAndFPSR(DestReg, &result); 727 break; 728 729 case 0x0D: /* FATANH */ 730 myfp_ATanh(&result, source); 731 SaveResultAndFPSR(DestReg, &result); 732 break; 733 734 case 0x0E: /* FSIN */ 735 myfp_Sin(&result, source); 736 SaveResultAndFPSR(DestReg, &result); 737 break; 738 739 case 0x0F: /* FTAN */ 740 myfp_Tan(&result, source); 741 SaveResultAndFPSR(DestReg, &result); 742 break; 743 744 case 0x10: /* FETOX */ 745 myfp_EToX(&result, source); 746 SaveResultAndFPSR(DestReg, &result); 747 break; 748 749 case 0x11: /* FTWOTOX */ 750 myfp_TwoToX(&result, source); 751 SaveResultAndFPSR(DestReg, &result); 752 break; 753 754 case 0x12: /* FTENTOX */ 755 myfp_TenToX(&result, source); 756 SaveResultAndFPSR(DestReg, &result); 757 break; 758 759 case 0x14: /* FLOGN */ 760 myfp_LogN(&result, source); 761 SaveResultAndFPSR(DestReg, &result); 762 break; 763 764 case 0x15: /* FLOG10 */ 765 myfp_Log10(&result, source); 766 SaveResultAndFPSR(DestReg, &result); 767 break; 768 769 case 0x16: /* FLOG2 */ 770 myfp_Log2(&result, source); 771 SaveResultAndFPSR(DestReg, &result); 772 break; 773 774 case 0x18: /* FABS */ 775 myfp_Abs(&result, source); 776 SaveResultAndFPSR(DestReg, &result); 777 break; 778 779 case 0x19: /* FCOSH */ 780 myfp_Cosh(&result, source); 781 SaveResultAndFPSR(DestReg, &result); 782 break; 783 784 case 0x1A: /* FNEG */ 785 myfp_Neg(&result, source); 786 SaveResultAndFPSR(DestReg, &result); 787 break; 788 789 case 0x1C: /* FACOS */ 790 myfp_ACos(&result, source); 791 SaveResultAndFPSR(DestReg, &result); 792 break; 793 794 case 0x1D: /* FCOS */ 795 myfp_Cos(&result, source); 796 SaveResultAndFPSR(DestReg, &result); 797 break; 798 799 case 0x1E: /* FGETEXP */ 800 myfp_GetExp(&result, source); 801 SaveResultAndFPSR(DestReg, &result); 802 break; 803 804 case 0x1F: /* FGETMAN */ 805 myfp_GetMan(&result, source); 806 SaveResultAndFPSR(DestReg, &result); 807 break; 808 809 case 0x20: /* FDIV */ 810 myfp_Div(&result, DestReg, source); 811 SaveResultAndFPSR(DestReg, &result); 812 break; 813 814 case 0x21: /* FMOD */ /* 0x2D in some docs, 0x21 in others ? */ 815 myfp_Mod(&result, DestReg, source); 816 SaveResultAndFPSR(DestReg, &result); 817 break; 818 819 case 0x22: /* FADD */ 820 myfp_Add(&result, DestReg, source); 821 SaveResultAndFPSR(DestReg, &result); 822 break; 823 824 case 0x23: /* FMUL */ 825 myfp_Mul(&result, DestReg, source); 826 SaveResultAndFPSR(DestReg, &result); 827 break; 828 829 case 0x24: /* FSGLDIV */ 830 myfp_Div(&t0, DestReg, source); 831 myfp_RoundToSingle(&result, &t0); 832 SaveResultAndFPSR(DestReg, &result); 833 break; 834 835 case 0x25: /* FREM */ 836 myfp_Rem(&result, DestReg, source); 837 SaveResultAndFPSR(DestReg, &result); 838 break; 839 840 case 0x26: /* FSCALE */ 841 myfp_Scale(&result, DestReg, source); 842 SaveResultAndFPSR(DestReg, &result); 843 break; 844 845 case 0x27: /* FSGLMUL */ 846 myfp_Mul(&t0, DestReg, source); 847 myfp_RoundToSingle(&result, &t0); 848 SaveResultAndFPSR(DestReg, &result); 849 break; 850 851 case 0x28: /* FSUB */ 852 myfp_Sub(&result, DestReg, source); 853 SaveResultAndFPSR(DestReg, &result); 854 break; 855 856 case 0x30: 857 case 0x31: 858 case 0x32: 859 case 0x33: 860 case 0x34: 861 case 0x35: 862 case 0x36: 863 case 0x37: 864 /* FSINCOS */ 865 myfp_SinCos(&result, &fpu_dat.fp[word2 & 0x7], source); 866 SaveResultAndFPSR(DestReg, &result); 867 break; 868 869 case 0x38: /* FCMP */ 870 myfp_Sub(&result, DestReg, source); 871 /* don't save result */ 872 myfp_SetConditionCodeByteFromResult(&result); 873 break; 874 875 case 0x3A: /* FTST */ 876 myfp_SetConditionCodeByteFromResult(source); 877 break; 878 879 /* 880 everything after here is not in 68881/68882, 881 appears first in 68040 882 */ 883 884 case 0x40: /* FSMOVE */ 885 myfp_RoundToSingle(&result, source); 886 SaveResultAndFPSR(DestReg, &result); 887 break; 888 889 case 0x41: /* FSSQRT */ 890 myfp_Sqrt(&t0, source); 891 myfp_RoundToSingle(&result, &t0); 892 SaveResultAndFPSR(DestReg, &result); 893 break; 894 895 case 0x44: /* FDMOVE */ 896 myfp_RoundToDouble(&result, source); 897 SaveResultAndFPSR(DestReg, &result); 898 break; 899 900 case 0x45: /* FDSQRT */ 901 myfp_Sqrt(&t0, source); 902 myfp_RoundToDouble(&result, &t0); 903 SaveResultAndFPSR(DestReg, &result); 904 break; 905 906 case 0x58: /* FSABS */ 907 myfp_Abs(&t0, source); 908 myfp_RoundToSingle(&result, &t0); 909 SaveResultAndFPSR(DestReg, &result); 910 break; 911 912 case 0x5A: /* FSNEG */ 913 myfp_Neg(&t0, source); 914 myfp_RoundToSingle(&result, &t0); 915 SaveResultAndFPSR(DestReg, &result); 916 break; 917 918 case 0x5C: /* FDABS */ 919 myfp_Abs(&t0, source); 920 myfp_RoundToDouble(&result, &t0); 921 SaveResultAndFPSR(DestReg, &result); 922 break; 923 924 case 0x5E: /* FDNEG */ 925 myfp_Neg(&t0, source); 926 myfp_RoundToDouble(&result, &t0); 927 SaveResultAndFPSR(DestReg, &result); 928 break; 929 930 case 0x60: /* FSDIV */ 931 myfp_Div(&t0, DestReg, source); 932 myfp_RoundToSingle(&result, &t0); 933 SaveResultAndFPSR(DestReg, &result); 934 break; 935 936 case 0x62: /* FSADD */ 937 myfp_Add(&t0, DestReg, source); 938 myfp_RoundToSingle(&result, &t0); 939 SaveResultAndFPSR(DestReg, &result); 940 break; 941 942 case 0x63: /* FSMUL */ 943 myfp_Mul(&t0, DestReg, source); 944 myfp_RoundToSingle(&result, &t0); 945 SaveResultAndFPSR(DestReg, &result); 946 break; 947 948 case 0x64: /* FDDIV */ 949 myfp_Div(&t0, DestReg, source); 950 myfp_RoundToDouble(&result, &t0); 951 SaveResultAndFPSR(DestReg, &result); 952 break; 953 954 case 0x66: /* FDADD */ 955 myfp_Add(&t0, DestReg, source); 956 myfp_RoundToDouble(&result, &t0); 957 SaveResultAndFPSR(DestReg, &result); 958 break; 959 960 case 0x67: /* FDMUL */ 961 myfp_Mul(&t0, DestReg, source); 962 myfp_RoundToDouble(&result, &t0); 963 SaveResultAndFPSR(DestReg, &result); 964 break; 965 966 case 0x68: /* FSSUB */ 967 myfp_Sub(&t0, DestReg, source); 968 myfp_RoundToSingle(&result, &t0); 969 SaveResultAndFPSR(DestReg, &result); 970 break; 971 972 case 0x6C: /* FDSUB */ 973 myfp_Sub(&t0, DestReg, source); 974 myfp_RoundToDouble(&result, &t0); 975 SaveResultAndFPSR(DestReg, &result); 976 break; 977 978 default: 979 DoCodeF_InvalidPlusWord(); 980#if dbglog_HAVE 981 dbglog_writeln("Invalid DoCodeFPU_GenOp"); 982#endif 983 break; 984 } 985} 986 987LOCALPROC DoCodeFPU_GenOpReg(ui4b word2) 988{ 989 ui4r regselect = (word2 >> 10) & 0x7; 990 991 DoCodeFPU_GenOp(word2, &fpu_dat.fp[regselect]); 992} 993 994LOCALPROC DoCodeFPU_GenOpEA(ui4b word2) 995{ 996 myfpr source; 997 998 switch ((word2 >> 10) & 0x7) { 999 case 0: /* long-word integer */ 1000 if (! DecodeModeRegister(4)) { 1001 DoCodeF_InvalidPlusWord(); 1002#if dbglog_HAVE 1003 dbglog_writeln( 1004 "DecodeModeRegister fails GetFPSource L"); 1005#endif 1006 } else { 1007 myfp_FromLong(&source, GetArgValueL()); 1008 DoCodeFPU_GenOp(word2, &source); 1009 } 1010 break; 1011 case 1: /* Single-Precision real */ 1012 if (! DecodeModeRegister(4)) { 1013 DoCodeF_InvalidPlusWord(); 1014#if dbglog_HAVE 1015 dbglog_writeln( 1016 "DecodeModeRegister fails GetFPSource S"); 1017#endif 1018 } else { 1019 myfp_FromSingleFormat(&source, GetArgValueL()); 1020 DoCodeFPU_GenOp(word2, &source); 1021 } 1022 break; 1023 case 2: /* extended precision real */ 1024 if (! DecodeAddrModeRegister(12)) { 1025 DoCodeF_InvalidPlusWord(); 1026#if dbglog_HAVE 1027 dbglog_writeln( 1028 "DecodeAddrModeRegister fails GetFPSource X"); 1029#endif 1030 } else { 1031 read_long_double(V_regs.ArgAddr.mem, &source); 1032 DoCodeFPU_GenOp(word2, &source); 1033 } 1034 break; 1035 case 3: /* packed-decimal real */ 1036 if (! DecodeAddrModeRegister(16)) { 1037 DoCodeF_InvalidPlusWord(); 1038#if dbglog_HAVE 1039 dbglog_writeln( 1040 "DecodeAddrModeRegister fails GetFPSource P"); 1041#endif 1042 } else { 1043 ReportAbnormalID(0x0304, 1044 "Packed Decimal in GetFPSource"); 1045 /* correct? just set to a constant for now */ 1046 /* *r = 9123456789.0; */ 1047 DoCodeFPU_GenOp(word2, &source); 1048 } 1049 break; 1050 case 4: /* Word integer */ 1051 if (! DecodeModeRegister(2)) { 1052 DoCodeF_InvalidPlusWord(); 1053#if dbglog_HAVE 1054 dbglog_writeln( 1055 "DecodeModeRegister fails GetFPSource W"); 1056#endif 1057 } else { 1058 myfp_FromLong(&source, GetArgValueW()); 1059 DoCodeFPU_GenOp(word2, &source); 1060 } 1061 break; 1062 case 5: /* Double-precision real */ 1063 if (! DecodeAddrModeRegister(8)) { 1064 DoCodeF_InvalidPlusWord(); 1065#if dbglog_HAVE 1066 dbglog_writeln( 1067 "DecodeAddrModeRegister fails GetFPSource D"); 1068#endif 1069 } else { 1070 read_double(V_regs.ArgAddr.mem, &source); 1071 DoCodeFPU_GenOp(word2, &source); 1072 } 1073 break; 1074 case 6: /* Byte Integer */ 1075 if (! DecodeModeRegister(1)) { 1076 DoCodeF_InvalidPlusWord(); 1077#if dbglog_HAVE 1078 dbglog_writeln( 1079 "DecodeModeRegister fails GetFPSource B"); 1080#endif 1081 } else { 1082 myfp_FromLong(&source, GetArgValueB()); 1083 DoCodeFPU_GenOp(word2, &source); 1084 } 1085 break; 1086 case 7: /* Not a valid source specifier */ 1087 DoCodeFPU_MoveCR(word2); 1088 break; 1089 default: 1090 /* should not be able to get here */ 1091 break; 1092 } 1093} 1094 1095LOCALPROC DoCodeFPU_Move_FP_EA(ui4b word2) 1096{ 1097 /* FMOVE FP?, <EA> */ 1098 1099 ui4r SourceReg = (word2 >> 7) & 0x7; 1100 myfpr *source = &fpu_dat.fp[SourceReg]; 1101 1102 switch ((word2 >> 10) & 0x7) { 1103 case 0: /* long-word integer */ 1104 if (! DecodeModeRegister(4)) { 1105 DoCodeF_InvalidPlusWord(); 1106#if dbglog_HAVE 1107 dbglog_writeln("DecodeModeRegister fails FMOVE L"); 1108#endif 1109 } else { 1110 SetArgValueL(myfp_ToLong(source)); 1111 } 1112 break; 1113 case 1: /* Single-Precision real */ 1114 if (! DecodeModeRegister(4)) { 1115 DoCodeF_InvalidPlusWord(); 1116#if dbglog_HAVE 1117 dbglog_writeln("DecodeModeRegister fails FMOVE S"); 1118#endif 1119 } else { 1120 SetArgValueL(myfp_ToSingleFormat(source)); 1121 } 1122 break; 1123 case 2: /* extended precision real */ 1124 if (! DecodeAddrModeRegister(12)) { 1125 DoCodeF_InvalidPlusWord(); 1126#if dbglog_HAVE 1127 dbglog_writeln("DecodeAddrModeRegister fails FMOVE X"); 1128#endif 1129 } else { 1130 write_long_double(V_regs.ArgAddr.mem, source); 1131 } 1132 break; 1133 case 3: /* packed-decimal real */ 1134 if (! DecodeAddrModeRegister(16)) { 1135 DoCodeF_InvalidPlusWord(); 1136#if dbglog_HAVE 1137 dbglog_writeln("DecodeAddrModeRegister fails FMOVE P"); 1138#endif 1139 } else { 1140 ReportAbnormalID(0x0305, "Packed Decimal in FMOVE"); 1141 /* ? */ 1142 } 1143 break; 1144 case 4: /* Word integer */ 1145 if (! DecodeModeRegister(2)) { 1146 DoCodeF_InvalidPlusWord(); 1147#if dbglog_HAVE 1148 dbglog_writeln("DecodeModeRegister fails FMOVE W"); 1149#endif 1150 } else { 1151 SetArgValueW(myfp_ToLong(source)); 1152 } 1153 break; 1154 case 5: /* Double-precision real */ 1155 if (! DecodeAddrModeRegister(8)) { 1156 DoCodeF_InvalidPlusWord(); 1157#if dbglog_HAVE 1158 dbglog_writeln("DecodeAddrModeRegister fails FMOVE D"); 1159#endif 1160 } else { 1161 write_double(V_regs.ArgAddr.mem, source); 1162 } 1163 break; 1164 case 6: /* Byte Integer */ 1165 if (! DecodeModeRegister(1)) { 1166 DoCodeF_InvalidPlusWord(); 1167#if dbglog_HAVE 1168 dbglog_writeln("DecodeModeRegister fails FMOVE B"); 1169#endif 1170 } else { 1171 SetArgValueB(myfp_ToLong(source)); 1172 } 1173 break; 1174 default: 1175 DoCodeF_InvalidPlusWord(); 1176#if dbglog_HAVE 1177 dbglog_writelnNum("Bad Source Specifier in FMOVE", 1178 (word2 >> 10) & 0x7); 1179#endif 1180 break; 1181 } 1182} 1183 1184LOCALIPROC DoCodeFPU_md60(void) 1185{ 1186 ui4b word2 = (int)nextiword(); 1187 1188 switch ((word2 >> 13) & 0x7) { 1189 case 0: 1190 DoCodeFPU_GenOpReg(word2); 1191 break; 1192 case 2: 1193 DoCodeFPU_GenOpEA(word2); 1194 break; 1195 case 3: 1196 DoCodeFPU_Move_FP_EA(word2); 1197 break; 1198 case 4: 1199 DoCodeFPU_Move_EA_CSIA(word2); 1200 break; 1201 case 5: 1202 DoCodeFPU_MoveM_CSIA_EA(word2); 1203 break; 1204 case 6: 1205 DoCodeFPU_MoveM_EA_list(word2); 1206 break; 1207 case 7: 1208 DoCodeFPU_MoveM_list_EA(word2); 1209 break; 1210 default: 1211 DoCodeF_InvalidPlusWord(); 1212#if dbglog_HAVE 1213 dbglog_writelnNum("Invalid DoCodeFPU_md60", 1214 (word2 >> 13) & 0x7); 1215#endif 1216 break; 1217 } 1218}